1. 电源管理架构
PowerManagerService是android系统电源管理的核心服务。
PowerManagerService在Framework层本质为策略控制方案,其作用为:
- 向上提供给应用程序接口,例如音频场景中保持系统唤醒、消息通知中唤醒手机屏幕场景;
- 向下决策HAL层以及Kernel层来控制设备待机状态,控制显示屏、背光灯、距离传感器、光线传感器等硬件设备的状态;
2. 电源管理的4个层次
- 应用接口层(PowerManager.java)
PowerManager 中开发给应用一系列接口,应用可以调用PM的接口申请wakelock,让系统唤醒或休眠; - Framework层(PowerManagerService.java)
应用调用PowerManager开发的接口的实现方为 PowerManagerService;
PowerManagerService是整个电源管理的决策系统,例如亮灭屏、系统唤醒休眠; - Hal层(Power.c)
该层只有一个power.c文件。通过接受上层参数,向/sys/power/wake_lock或/sys/power/wake_unlock文件节点写数据来与Kernel进行通信。主要功能为申请/释放锁,维持屏幕亮灭; - 内核层(Kernel/Power)
- 实现系统电源管理框架机制:Kernel/power/
- 实现对特定板的处理器电源管理:Arch/arm/match-xxx/pm.c
- 电源驱动为设备电源管理提供基础框架: Drivers/power
3. 电源管理服务 – PowerManagerService
frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
负责管理、协调设备电源管理的系统服务之一,设备中常见功能如亮灭屏、亮度调节、低电量模式、保持CPU唤醒都是通过PMS进行协调和处理。
3.1 SystemServer startService PowerManagerService
PowerManagerService 继承SystemSerive即具备生命周期, SystemService系的服务都是在SystemServer中启动、注册到系统服务中,通过Binder和其他组件进行交互
故我们先看下SystemServer的启动流程。
SystemServer.main
->SystemServer.run
->->SystemServer.startBootstrapServices() 启动引导服务
->->->mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class); // 通过Java的newInstance()反射启动电源管理服务,好处是代码很解耦
3.2 PowerManagerService 的构造函数
- 建立Handle: 消息发送与处理
- 2种WakeLock锁,分别为 mWakeLockSuspendBlocker 和 mDisplaySuspendBlocker
a. mDisplaySuspendBlocker: 上层调用,控制屏幕的点亮和息屏
b. mWakeLockSuspendBlocker: 系统内部调用,控制CPU的唤醒
PowerManagerService(Context context, Injector injector) {...mHandlerThread = new ServiceThread(TAG,Process.THREAD_PRIORITY_DISPLAY, false /*allowIo*/);mHandlerThread.start();mHandler = injector.createHandler(mHandlerThread.getLooper(),new PowerManagerHandlerCallback());...// 控制CPU的唤醒mWakeLockSuspendBlocker =mInjector.createSuspendBlocker(this, "PowerManagerService.WakeLocks");// 控制屏幕的点亮和息屏mDisplaySuspendBlocker =mInjector.createSuspendBlocker(this, "PowerManagerService.Display");...}看到上述的2个锁,让我联系到经常使用的如下Flag Flag Value CPUScreenKeyboard PARTIAL_WAKE_LOCKOn Off Off 0x00000001 1 SCREEN_DIM_WAKE_LOCK On Dim Off 0x00000006 6 SCREEN_BRIGHT_WAKE_LOCKOn BrightOff 0x0000000a 10 FULL_WAKE_LOCK On BrightBright 0x0000001a 26
3.3 PowerManagerService.onStart()
Onstart的作用:
- 将 POWER_SERVICE 注册到 Binder 服务端,这样其他模块就可以通过Binder获取实例。同理当进行本地注册后,只有在Sysem进程才能获得到其实例。
- 设置 Watchdog 监视 PowerManagerService 和 Handler
@Overridepublic void onStart() {// 其他模块就可以通过Binder获取实例publishBinderService(Context.POWER_SERVICE, mBinderService, /* allowIsolated= */ false,DUMP_FLAG_PRIORITY_DEFAULT | DUMP_FLAG_PRIORITY_CRITICAL);// 当进行本地注册后,只有在Sysem进程才能获得到其实例publishLocalService(PowerManagerInternal.class, mLocalService);Watchdog.getInstance().addMonitor(this);Watchdog.getInstance().addThread(mHandler);}
3.4 PowerManagerService.systemReady()
systemReady()函数作用:初始化工作,即我们可以看到电源管理策略的需要用的功能初始化。
- 初始化互动屏保
- 初始化屏幕显示管理服务
- 初始化电池管理服务
- 获取屏幕亮度信息
- 获取传感器管理服务
- 初始化电量统计服务
- SettingsProvier监听
- LED指示灯管理服务
- 初始化屏幕显示服务
- 广播相关:电池广播、用户切换广播
- 更新电源相关信息
例如我们在做冻结策略、场景识别策略的ROM定制也大体都是在 systemReady 进行init
public void systemReady(IAppOpsService appOps) {...mDreamManager = getLocalService(DreamManagerInternal.class); // 1. 初始化互动屏保mDisplayManagerInternal = getLocalService(DisplayManagerInternal.class);// 2. 初始化屏幕显示管理服务mBatteryManagerInternal = getLocalService(BatteryManagerInternal.class);// 3. 初始化电池管理服务SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper());//5. 获取传感器管理服务mBatteryStats = BatteryStatsService.getService();//6. 初始化电量统计服务mLightsManager = getLocalService(LightsManager.class);//8. LED指示灯管理服务mAttentionLight = mLightsManager.getLight(LightsManager.LIGHT_ID_ATTENTION);//8. LED指示灯管理服务mDisplayManagerInternal.initPowerManagement(mDisplayPowerCallbacks, mHandler, sensorManager);// 9. 初始化屏幕显示服务// 整个 PMS 中最重要的方法updatePowerStateLocked();// 11. 更新电源相关信息...}
总结一下:SystemReady完成的工作主要如下:
- 获取与PowerManangerService相关的系统服务以及本地服务;
- 获取屏幕最大、最小以及默认亮度值
- 创建SensorManager对象用于与SensorService交互
- 创建Notifier对象,用户通知系统电源状态的改变
- 调用DisplayManangerService的initPowerMannagerMent()方法来初始化Power显示模块
- 注册SettingsObserver监听系统设置的变化
3.5 PowerManager 的相关接口
PowerMananger 是PowerManangerService的代理类,PowerMananger向上层应用提供交互的接口。上层调用对应的接口后,具体的工作内容交予PowerManangerService完成。可以重点关注如下接口:
- wakeUp()
hide接口,不开放给应用。作用:强制系统从睡眠状态唤醒。 - gotoSleep()
hide接口,不开放给应用。作用:强制系统进入睡眠状态 - userActivity()
向PowerManagerService报告影响系统休眠的用户活动,重新计算灭屏时间,背光亮度,例如触屏、滑屏、power键等用户行为。 - Wakelock(特别常用)
wakelock是PowerManager的一个内部类,提供了相关的接口来操作wakelock锁。应用层可以使用newWakeLock方法创建wakelock锁,使用acquire()和release()来申请和释放锁。例如如下demo的使用
package com.sufadi.commlib.utilsimport android.annotation.SuppressLintimport android.content.Contextimport android.os.PowerManager/* Flag Value CPUScreenKeyboard PARTIAL_WAKE_LOCKOn Off Off 0x00000001 1 SCREEN_DIM_WAKE_LOCK On Dim Off 0x00000006 6 SCREEN_BRIGHT_WAKE_LOCKOn BrightOff 0x0000000a 10 FULL_WAKE_LOCK On BrightBright 0x0000001a 26 */object AlertWakeLock {private val TAG = "AlertWakeLock"private var sCpuWakeLock: PowerManager.WakeLock? = null@SuppressLint("InvalidWakeLockTag")internal fun createPartialWakeLock(context: Context): PowerManager.WakeLock? {// 第一步:获取PowerManager的实例val pm = context.getSystemService(Context.POWER_SERVICE) as PowerManager ?: return null// 第二步:调用PowerManager中的newWakeLock方法创建一个WakeLock对象return pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, TAG)//return pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.ON_AFTER_RELEASE, TAG);}fun acquireCpuWakeLock(context: Context) {if (sCpuWakeLock != null) {return}sCpuWakeLock = createPartialWakeLock(context)// 第三步:acquire()获取相应的锁sCpuWakeLock!!.acquire()}fun releaseCpuLock() {if (sCpuWakeLock != null) {// 最后:release释放sCpuWakeLock!!.release()sCpuWakeLock = null}}}
- isDeviceIdleMode
查看是否进入了Doze低功耗模式