Android电源管理框架
Android电源管理框架
管理策略:通过锁和定时器来切换系统的状态,使系统的功耗降至最低
层次结构:App、Framework、HAL和kernel层
l 应用层:这里所谓的应用层主要是指应用程序和其他使用电源管理的Service,包括但不限于以下Services: PowerManagerService、BatteryService、LightService等。
l 框架层:在Android框架层包含了对应用层接口的API调用以及电源的协调工作,主要包含PowerManager.java、PowerManagerService.java、com_android_server_PowerManagerService.cpp、Power.java、android_os_Power.cpp。其中PowerManagerService.java是核心,Power.java提供底层的函数接口,与JNI层进行交互。PowerManager.java是提供给应用层调用的。android_os_power.cpp是jni交互文件。这一层的功能相对比较复杂,比如系统状态的切换,背光的调节及开关,Wake Lock的申请和释放等等,但这一层跟硬件平台无关。
l HAL层:该层只有一个Power.c文件,该文件通过sysfs的方式与kernel进行通信。主要功能有申请wake_lock,释放wake_lock,设置屏幕状态等。用户空间的native库绝不能直接调用Android电源管理(见下图)。绕过Android运行时的电源管理政策,将破坏该系统。所有对电源管理的调用应通过Android的PowerManagerAPI来完成。
l Kernel层:内核层的电源管理方案实现主要包含三部分:
1、Kernel/power/:实现了系统电源管理框架机制。
2、Arch/arm(ormips or powerpc)/mach-XXX/pm.c:实现对特定板的处理器电源管理。
3、drivers/power:是设备电源管理的基础框架,为驱动提供了电源管理接口。
Android的电源管理框架
Android系统提供的几个低功耗模式
earlysuspend:让设备进入低功耗,如LCD关闭
suspend:只有电源模块和
hibernation:内存镜像写入磁盘,下次开机可恢复
PowerManager是PMS的代理类,实现如下常用功能
reboot、gotoSleep、wakeUp、shutDown、isDeviceIdleMode、userActivity和屏幕信息操作等接口
userActivity:向PowerManagerService报告影响系统休眠的用户活动,重计算灭屏时间,背光亮度等,例如触屏,划屏,power键等用户活动;
isDeviceIdleMode:返回设备当前的状态,如果处于Idle状态,则返回true,Idle状态是在手机长时间没有被使用以及没有运动的情况下,手机进入到一种Doze低功耗的模式下,这种状态下手机可能会关掉网络数据访问,可以通过监视DEVICE_IDLE_MODE_CHANGED这个广播信息,来监控手机状态的改变
电源管理的核心服务PowerManagerService(PMS)流程
PowerManager是通过binder与PowerManagerService进行通信的,PowerManer中的大部分方法在PMS中都有阈值对应的方法,PMS是整个电源管理的决策系统
参考链接:
http://blog.csdn.net/gaugamela/article/details/52785041
http://www.myexception.cn/android/2076061.html
http://blog.csdn.net/kitty_landon/article/details/47107045
PMS:PowerNamagerService的启动
在SystemServer中启动PMS和SensorService
frameworks/base/services/java/com/android/server/SystemServer.java
private void startBootstrapServices()
{mActivityManagerService = mSystemServiceManager.startService(ActivityManagerService.Lifecycle.class).getService();mActivityManagerService.setSystemServiceManager(mSystemServiceManager);mActivityManagerService.setInstaller(installer);mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);//启动PMS.......startSensorService(); //native函数,sensor管理
}
上面的函数为Android系统的引导程序,启动PMS时候会通过反射方式调用服务(PMS)的构造函数,同时执行服务(PMS)的onStart()函数
public <T extends SystemService> T startService(Class<T> serviceClass) {......Constructor<T> constructor = serviceClass.getConstructor(Context.class);service = constructor.newInstance(mContext);//调用PMS的构造函数......mServices.add(service);//将PMS作为系统服务添加到服务列表service.onStart();//调用PMS的onStart方法return service;
}
PMS的构造函数实现如下
public PowerManagerService(Context context) {super(context);mContext = context;mHandlerThread = new ServiceThread(TAG,Process.THREAD_PRIORITY_DISPLAY, false /*allowIo*/);mHandlerThread.start();mHandler = new PowerManagerHandler(mHandlerThread.getLooper());synchronized (mLock) {mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks");//控制CPUmDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display");//控制屏幕mDisplaySuspendBlocker.acquire();mHoldingDisplaySuspendBlocker = true;mHalAutoSuspendModeEnabled = false;mHalInteractiveModeEnabled = true;mWakefulness = WAKEFULNESS_AWAKE;//系统所处的状态(系统正常状态,休眠状态,屏保状态,doze状态)nativeInit();nativeSetAutoSuspend(false);nativeSetInteractive(true);nativeSetFeature(POWER_FEATURE_DOUBLE_TAP_TO_WAKE, 0);}}
mWakefulness有四种取值标识系统当前的状态
WAKEFULNESS_ASLEEP:表示系统当前处于休眠状态,只能被wakeUp()调用唤醒。
WAKEFULNESS_AWAKE:表示系统目前处于正常运行状态。
WAKEFULNESS_DREAMING:表示系统当前正处于屏保的状态。
WAKEFULNESS_DOZING:表示系统正处于“doze”状态。这种状态下只有低耗电的“屏保”可以运行,其他应用进程都被挂起。
关于createSuspendBlockerLocked的实现
private SuspendBlocker createSuspendBlockerLocked(String name) { SuspendBlocker suspendBlocker = new SuspendBlockerImpl(name); mSuspendBlockers.add(suspendBlocker); return suspendBlocker;
}
acquire()函数的实现
public void acquire() { synchronized (this) { mReferenceCount += 1; if (mReferenceCount == 1) { nativeAcquireSuspendBlocker(mName); } } }
所以每次acquire() count都会加1, nativeAcquireSuspendBlocker(mName)方法通过JNI调用native层的 nativeAcquireSuspendBlocker 方法。
static void nativeAcquireSuspendBlocker(JNIEnv *env, jclass clazz, jstring nameStr) { ScopedUtfChars name(env, nameStr); acquire_wake_lock(PARTIAL_WAKE_LOCK, name.c_str());
}
acquire_wake_lock()调用的是power.c文件中的acquire_wake_lock()方法。在该方法中通过往/sys/power/wake_lock,/sys/power/wake_unlock等文件中写入数据来进行底层持锁
下面看nativeInit()函数,通过JNI方法在native层初始化相关资源
static void nativeInit(JNIEnv* env, jobject obj) {//创建一个全局引用对象,引用PMSgPowerManagerServiceObj = env->NewGlobalRef(obj);//利用hw_get_module加载底层动态库,具体实现还是依赖与dlsym函数status_t err = hw_get_module(POWER_HARDWARE_MODULE_ID,(hw_module_t const**)&gPowerModule);if (!err) {//调用底层动态库的init函数gPowerModule->init(gPowerModule);} else {ALOGE("Couldn't load %s module (%s)", POWER_HARDWARE_MODULE_ID, strerror(-err));}
}static void nativeSetAutoSuspend(JNIEnv* /* env */, jclass /* clazz */, jboolean enable) {if (enable) {ALOGD_IF_SLOW(100, "Excessive delay in autosuspend_enable() while turning screen off");autosuspend_enable();} else {ALOGD_IF_SLOW(100, "Excessive delay in autosuspend_disable() while turning screen on");//初始时调用autosuspend_disable函数,定义于system/core/libsuspend/autosuspend.c中//最终将调用到autosuspend_earlysuspend_disable函数,就是将底层的置为pwr_state_on的状态autosuspend_disable();}
}static void nativeSetInteractive(JNIEnv* /* env */, jclass /* clazz */, jboolean enable) {if (gPowerModule) {if (enable) {ALOGD_IF_SLOW(20, "Excessive delay in setInteractive(true) while turning screen on");//初始时,调用动态库的setInteractive函数,目前还不确定这个函数调用后的效果gPowerModule->setInteractive(gPowerModule, true);} else {ALOGD_IF_SLOW(20, "Excessive delay in setInteractive(false) while turning screen off");gPowerModule->setInteractive(gPowerModule, false);}}
}static void nativeSetFeature(JNIEnv *env, jclass clazz, jint featureId, jint data) {int data_param = data;if (gPowerModule && gPowerModule->setFeature) {//初始时,调用动态库的setFeature函数,将POWER_FEATURE_DOUBLE_TAP_TO_WAKE置为0gPowerModule->setFeature(gPowerModule, (feature_t)featureId, data_param);}
}
nativeInit()方法中,创建了一个对应的Native层PowerManagerService,然后调用了gPowerModule的init函数。以下是power_module的结构类型
struct power_module HAL_MODULE_INFO_SYM = { .common = { .tag = HARDWARE_MODULE_TAG, .module_api_version = POWER_MODULE_API_VERSION_0_2, .hal_api_version = HARDWARE_HAL_API_VERSION, .id = POWER_HARDWARE_MODULE_ID, .name = "Default Power HAL", .author = "The Android Open Source Project", .methods = &power_module_methods, }, .init = power_init, .setInteractive = power_set_interactive, .powerHint = power_hint,
};
gPowerModule->init方法对应的是power_init 这个应该是由硬件厂商来实现的,不同的硬件初始化方式也不一样,我们看先htc相关的实现方式. Power_init实际就是在cpu的节点中写入了一些初始化的值,以下是htc一个例子
static void power_init(struct power_module __unused *module)
{ sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/timer_rate", "20000"); sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/timer_slack", "20000"); sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/min_sample_time", "80000"); sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/hispeed_freq", "1530000"); sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/go_hispeed_load", "99"); sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/target_loads", "65 228000:75 624000:85"); sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/above_hispeed_delay", "20000"); sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/boostpulse_duration", "1000000"); sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/io_is_busy", "0"); calculate_max_cpu_freq();
}
所以构造函数实际上时设置了一些标志位,设置系统的状态,加载底层与硬件设置相关的函数
PMS的onStart()函数
@Overridepublic void onStart() {publishBinderService(Context.POWER_SERVICE, new BinderService());//最终通过ServiceManager的Add函数注册BinderServicepublishLocalService(PowerManagerInternal.class, new LocalService());Watchdog.getInstance().addMonitor(this);Watchdog.getInstance().addThread(mHandler);}
将PowerManagerService注册到ServiceManager中和LocalService中
PMS的systemReady()函数
在中SystemServer的run()函数中
private void run()
{.......Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices");startBootstrapServices();//启动必要的引导服务如PMSstartCoreServices();startOtherServices();.......
}
在startOtherServices()中
private void startOtherServices()
{........try {// TODO: use boot phasemPowerManagerService.systemReady(mActivityManagerService.getAppOpsService());Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);} catch (Throwable e) {reportWtf("making Power Manager Service ready", e);}........
}
PMS的systemReady函数具体实现如下
public void systemReady(IAppOpsService appOps) {//这里持锁,意味者内部所有函数必须在规定事件内执行完毕//否则watchDog将会检测到错误synchronized (mLock) {mSystemReady = true;mAppOps = appOps;//注意下面的对象都是从LocalServices取出的,从之前PMS加入LocalServices的流程来看//下面取出的实际上应该是继承抽象类的实际子类//因此大概可以理解LocalServices的作用了,以抽象类名为key,保存实际的子类//以key取出子类对象时,子类退化为抽象类,于是得到了实际对象,但仅能利用父类的接口//整个设计演变为面向接口的编程//从注释来看,与doze有关mDreamManager = getLocalService(DreamManagerInternal.class);//显示管理相关mDisplayManagerInternal = getLocalService(DisplayManagerInternal.class);//Window管理相关mPolicy = getLocalService(WindowManagerPolicy.class);//电源管理相关mBatteryManagerInternal = getLocalService(BatteryManagerInternal.class);//这里获取PowerManager就是为了方便获取下面三个系统属性PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);mScreenBrightnessSettingMinimum = pm.getMinimumScreenBrightnessSetting();mScreenBrightnessSettingMaximum = pm.getMaximumScreenBrightnessSetting();mScreenBrightnessSettingDefault = pm.getDefaultScreenBrightnessSetting();//Sensor相关SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper());//系统电量统计有关mBatteryStats = BatteryStatsService.getService();// The notifier runs on the system server's main looper so as not to interfere// with the animations and other critical functions of the power manager.mNotifier = new Notifier(Looper.getMainLooper(), mContext, mBatteryStats,mAppOps, createSuspendBlockerLocked("PowerManagerService.Broadcasts"),mPolicy);//无线充电检测相关mWirelessChargerDetector = new WirelessChargerDetector(sensorManager,createSuspendBlockerLocked("PowerManagerService.WirelessChargerDetector"),mHandler);mSettingsObserver = new SettingsObserver(mHandler);//lightService相关mLightsManager = getLocalService(LightsManager.class);mAttentionLight = mLightsManager.getLight(LightsManager.LIGHT_ID_ATTENTION);// Initialize display power management.//调用DisplayManagerService内部的LocalService的函数//创建出DisplayBlanker和DisplayPowerControllermDisplayManagerInternal.initPowerManagement(mDisplayPowerCallbacks, mHandler, sensorManager);//定义一堆BroadcastReceiver..................//利用mSettingsObserver监听一堆数据库字段的变化..................//VR相关IVrManager vrManager =(IVrManager) getBinderService(VrManagerService.VR_MANAGER_BINDER_SERVICE);try {vrManager.registerListener(mVrStateCallbacks);} catch (RemoteException e) {Slog.e(TAG, "Failed to register VR mode state listener: " + e);}//从资源文件中读取大量配置信息readConfigurationLocked();//读取数据库字段,保存到本地变量中//必要时会进行一些实际的操作,例如设置feature到native层的动态库updateSettingsLocked();mDirty |= DIRTY_BATTERY_STATE;//更新全局的电源状态updatePowerStateLocked();}
}
进一步初始化PMS,获取与PowerManager相关的本地服务
比如屏保(mDreamManager)
屏幕显示(mDisplayManagerInternal)
窗口策略(mPolicy)
电池电量(mBatteryManagerInternal)等服务,然后初始化屏幕最大亮度,最小亮度,和默认亮度;
sensor(sensorManager)用于与sensor交互,比如距离传感器,光线传感器,加速度传感器(doze上使用)
背光(mLightsManager)
电池状态(mBatteryStats)
创建mSettingsObserver 监听系统设置变化,比如亮屏时间,自动背光,屏幕亮度,屏保,低电模式等等
唤醒流程
屏保唤醒通过线程监听来实现,具体的在DreamManagerService.java中
private final Runnable mSystemPropertiesChanged = new Runnable() {@Overridepublic void run() {if (DEBUG) Slog.d(TAG, "System properties changed");synchronized (mLock) {if (mCurrentDreamName != null && mCurrentDreamCanDoze&& !mCurrentDreamName.equals(getDozeComponent())) {// May have updated the doze component, wake upmPowerManager.wakeUp(SystemClock.uptimeMillis(),"android.server.dreams:SYSPROP");}}}};
PM中的wakeUp方法最终会调用到PMS中的wakeUp方法,PMS具体如下
@Override // Binder call//该方法通过Binder白PM的wakeUp函数调用public void wakeUp(long eventTime, String reason, String opPackageName) {if (eventTime > SystemClock.uptimeMillis()) {throw new IllegalArgumentException("event time must not be in the future");}mContext.enforceCallingOrSelfPermission(//权限检查android.Manifest.permission.DEVICE_POWER, null);final int uid = Binder.getCallingUid();final long ident = Binder.clearCallingIdentity();try {wakeUpInternal(eventTime, reason, uid, opPackageName, uid);//唤醒逻辑} finally {Binder.restoreCallingIdentity(ident);}}
具体唤醒逻辑如下:
private void wakeUpInternal(long eventTime, String reason, int uid, String opPackageName,int opUid) {synchronized (mLock) {if (mIPOShutdown && reason != PowerManager.WAKE_UP_REASON_SHUTDOWN)return;if (wakeUpNoUpdateLocked(eventTime, reason, uid, opPackageName, opUid)) {updatePowerStateLocked();//此方法为PMS的核心方法,专门处理wakeUp与sleep的逻辑}}}
只有wakeUpNoUpdateLocked返回true时才会执行updatePowerStateLocked()函数
private boolean wakeUpNoUpdateLocked(long eventTime, String reason, int reasonUid,String opPackageName, int opUid) {......switch (mWakefulness) {case WAKEFULNESS_ASLEEP:Slog.i(TAG, "Waking up from sleep (uid " + reasonUid +")...");break;case WAKEFULNESS_DREAMING:Slog.i(TAG, "Waking up from dream (uid " + reasonUid +")...");break;case WAKEFULNESS_DOZING:Slog.i(TAG, "Waking up from dozing (uid " + reasonUid +")...");break;}mLastWakeTime = eventTime;setWakefulnessLocked(WAKEFULNESS_AWAKE, 0);//不论系统目前处于何种状态,都会将系统当前的状态设置为WAKE状态......return true;//返回true
}
updatePowerStateLocked函数用于更新整个系统的状态,决定系统当前所处的状态
private void updatePowerStateLocked() {......// Phase 0: Basic state updates.updateIsPoweredLocked(mDirty);updateStayOnLocked(mDirty);updateScreenBrightnessBoostLocked(mDirty);// Phase 1: Update wakefulness.// Loop because the wake lock and user activity computations are influenced// by changes in wakefulness.final long now = SystemClock.uptimeMillis();int dirtyPhase2 = 0;for (;;) {int dirtyPhase1 = mDirty;dirtyPhase2 |= dirtyPhase1;mDirty = 0;updateWakeLockSummaryLocked(dirtyPhase1);updateUserActivitySummaryLocked(now, dirtyPhase1);if (!updateWakefulnessLocked(dirtyPhase1)) {break;}}// Phase 2: Update display power state.boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);// Phase 3: Update dream state (depends on display ready signal).updateDreamLocked(dirtyPhase2, displayBecameReady);// Phase 4: Send notifications, if needed.finishWakefulnessChangeIfNeededLocked();// Phase 5: Update suspend blocker.// Because we might release the last suspend blocker here, we need to make sure// we finished everything else first!updateSuspendBlockerLocked();......
}
updatePowerStateLocked是PMS的核心函数,主要分为5个步骤进行
主要处理屏幕显示,背光处理,用户ACTION,suspend blockers的申请与释放
updateDisplayPowerStateLocked主要用于按键灯,屏幕亮度自动调节,处理显示请求
Android电源管理框架相关推荐
- Android电源管理介绍
一.电源管理基础知识 1.1电源管理的几种状态 Android kernel源码中,定义了三种电源状态,在kernel/power/suspend.c中: 对应的宏定义/include/linux/s ...
- android 电源管理 wakelock 唤醒锁机制
Android 电源管理 - 唤醒锁全新上市 大多数人可能都遭遇过手机的电池续航时间较短带来的尴尬. 这极其令人讨厌. 没电的手机和一块水泥砖没什么差别. 一般而言,如果用户的手机电池无法持续一整天, ...
- 关闭Android电池温度告警框,android电源信息查看(电量、温度、电压)实例代码
本文实例讲述了android电源信息查看方法.分享给大家供大家参考.具体如下: 1. PowerTestActivity: import android.app.Activity; import an ...
- AliOS Things 电源管理框架使用说明
一.电源管理框架简介 电源管理框架的目的在于节约CPU的功耗.传统上,当操作系统处于空闲状态时,比如所有用户任务和系统任务处于阻塞状态,将执行idle task.idle task的通常做法是一个wh ...
- Android 资源管理框架(Resources和AssetManager) 及 资源编译(aapt)
android应用资源预编译,编译和打包全解析- https://cloud.tencent.com/developer/article/1033926 Android系统提供了一套强大的资源管理 ...
- RT-Thread 4.1.0 开启 PM 电源管理框架
前言 如今嵌入式产品越来越关注低功耗设计,也就是PM电源管理 如果使用裸机程序,低功耗的管理流程相对简单一些,在多任务的操作系统中,如基于RT-Thread,如何进行低功耗管理呢? RT-Thread ...
- Android电源管理分析
Android电源管理 1.电源管理服务–PowerManagerService PowerManagerService提供Android系统的电源管理服务,主要功能是控制系统的待机状态,控制显示 ...
- Linux运行时I/O设备的电源管理框架
本文介绍Linux运行时I/O设备的电源管理框架.属于Linux内核文档的翻译. 原文:http://www.kernel.org/doc/Documentation/power/runtime_pm ...
- Linux运行时I/O设备的电源管理框架【转】
转自:https://www.cnblogs.com/coryxie/archive/2013/03/01/2951243.html 本文介绍Linux运行时I/O设备的电源管理框架.属于Linux内 ...
- Android资源管理框架(Asset Manager)简要介绍和学习计划
Android应用程序主要由两部分内容组成:代码和资源.资源主要就是指那些与UI相关的东西,例如UI布局.字符串和图片等.代码和资源分开可以使得应用程序在运行时根据实际需要来组织UI.这样就可使得应用 ...
最新文章
- linux存储--可执行文件结构和进程内存模型(三)
- STM32 定时器中断
- java两个数之间质数求法,求任意两个整数之间质数的个数的代码!!!(新手编写)...
- Python_51job爬虫
- python 工具ScreenShoot
- 贪心算法—建立雷达(POJ 1328)
- 如何在ASP.NET Core中编写自定义日志记录提供程序
- 3gpp协议_C-V2X: 3GPP协议阅读前的一些准备
- matlab 概率论,matlab.概率论.doc
- 软件性能中几个主要的术语
- 易速联服务器稳定吗,异速联如何保障应用安全性?
- python对称加密算法库_对称加密算法
- 爱加密加固病毒分析-破解篇
- 登录mysql服务器的典型命令_Mysql 远程登录及常用命令
- Snipaste截图软件的下载和使用(日常常用的一些功能)
- 崔荣容,英语如法入门1-50讲
- PIX飞控中POS数据读取方法(实用工具)
- 三栏式布局详解(代码+图解)
- ISP—自动白平衡(AWB)
- win10系统c盘C:Users后面的用户名怎么更改