Android5.1--PowerManagerService电源管理

2019-07-14 03:01发布

系统电源管理简介

Android电源管理概述

电源管理(PowerManager)在任何设备中都是最重要的组成部分之一,良好的电源管理方案可以达到节能、延长电池寿命、降低辐射、降温等目的。 移动设备的电量主要有两种元件消耗:CPU和显示屏。设法降低这两种元件的耗电量就是电源管理的关键。为移动设备设计的CPU大都有两种工作频率,为了省电,大部分时间CPU都工作在较低的频率下,只有进行密集计算时,如视频解码,才会切换到高频状态。而显示屏省电的方法是尽量减少亮屏的时间,但是显示屏的开关和应用有很大的关系,因此,系统需要有一套机制来控制显示屏的开关和亮度,这是电源管理模块的主要工作之一。

Android电源管理组织架构

Android的电源管理主要是通过锁和定时器来切换系统的状态,使系统的功耗降至最低,整个系统的框架可以分为四个层次,分别是应用程序层、Framework层、硬件抽象层(HAL)和内核层。Android电源管理框架如图1-1所示。 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、Kernelpower:实现了系统电源管理框架机制。 2、Archarm(ormips or powerpc)mach-XXXpm.c:实现对特定板的处理器电源管理。 3、driverspower:是设备电源管理的基础框架,为驱动提供了电源管理接口。 图1-1 Android电源管理框架图 系统正常开机后,Brightness的亮度会设置成用户设定的亮度,系统Screen off timer开始计时,在计时时间到之前,如果有任何的userActivity事件发生,比如Touch click等事件,则将重新设置screen off timer,系统保持在Awake状态。如果应用程序在这段时间申请了Full wakelock,系统也将保持在Awake状态。在没有交互的情况下,首先进入到Awake状态,之后进入Dozing状态,最后进入Asleep状态。

电源管理服务--PowerManagerService

PowerManagerService是Android电源管理的核心服务,主要功能是控制系统的待机状态,控制显示屏的开关和亮度调节,以及查询和控制光线传感器和距离传感器等。PowerManagerService的启动流程如下图2-1所示。
图2-1PowerManagerService启动流程

初始化过程

PowerManagerService也是在SystemServer中创建并加入到ServiceManager中的,代码如下: [java] view plain copy
  1. mPowerManagerService = mSystemServiceManager.startService(  
  2. PowerManagerService.class);  

    调用SystemServiceManager的startService方法创建PowerManagerService对象并注册到ServiceManager中。PowerManagerService的构造方法代码如下: [java] view plain copy
  1. public PowerManagerService(Context context) {  
  2.     super(context);  
  3.     mContext = context;  
  4. //创建处理消息的线程和Handler对象  
  5.     mHandlerThread = new ServiceThread(TAG,  
  6.            Process.THREAD_PRIORITY_DISPLAY, false/*allowIo*/);  
  7.     mHandlerThread.start();  
  8.     mHandler = new PowerManagerHandler(mHandlerThread.getLooper());  
  9.   
  10.     synchronized (mLock) {  
  11.         mWakeLockSuspendBlocker =createSuspendBlockerLocked("PowerManagerService.WakeLocks");  
  12.         mDisplaySuspendBlocker =createSuspendBlockerLocked("PowerManagerService.Display");  
  13.         mDisplaySuspendBlocker.acquire();  
  14.         mHoldingDisplaySuspendBlocker = true;  
  15.         mHalAutoSuspendModeEnabled = false;  
  16.         mHalInteractiveModeEnabled = true;  
  17.   
  18.         mWakefulness = WAKEFULNESS_AWAKE;//设置PowerManagerService的状态  
  19.   
  20.         nativeInit();  
  21.         nativeSetAutoSuspend(false);  
  22.         nativeSetInteractive(true);  
  23.     }  
  24. }  

         PowerManagerService的构造方法中首先创建了处理消息的线程和发送消息的PowerManagerHandler对象,接着创建了mWakeLockSuspendBlocker对象、mDisplaySuspendBlocker对象。          变量mWakefulness的值被设置成WAKEFULNESS_AWAKE,它用来标示PowerManagerService的状态,一共有四种定义: l  WAKEFULNESS_ASLEEP:表示系统当前处于休眠状态,只能被wakeUp()调用唤醒。 l  WAKEFULNESS_AWAKE:表示系统目前处于正常运行状态。 l  WAKEFULNESS_DREAMING:表示系统当前正处于播放屏保的状态。 l  WAKEFULNESS_DOZING:表示系统正处于“doze”状态。这种状态下只有低耗电的“屏保”可以运行,其他应用进程都被挂起。 最后,构造方法调用了nativeInit()方法,主要工作就是装载”Power”模块,之后调用模块的初始化函数init()。

系统准备工作—SystemReady方法

SystemServer创建PowerManagerService后,还会调用它的SystemReady()方法,相当于在系统准备就绪后对PowerManagerService再进行一些初始化工作。SystemReady()方法代码如下: [java] view plain copy
  1. public void systemReady(IAppOpsService appOps) {  
  2.     synchronized (mLock) {  
  3.         mSystemReady = true;  
  4.         mAppOps = appOps;  
  5.         mDreamManager =getLocalService(DreamManagerInternal.class);//获取DreamManagerService对象  
  6.         mDisplayManagerInternal =getLocalService(DisplayManagerInternal.class);//DisplayManagerService  
  7.         mPolicy = getLocalService(WindowManagerPolicy.class);//WindowManagerPolicy  
  8.         mBatteryManagerInternal =getLocalService(BatteryManagerInternal.class);//BatteryService  
  9.   
  10. //获取最小、最大、默认屏幕亮度  
  11.         。。。。。。  
  12. //创建SensorManager对象,用于和SensorService交互  
  13.         SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper());  
  14.   
  15.         mBatteryStats = BatteryStatsService.getService();//获得BatteryStatsService的引用对象  
  16.         mNotifier = new Notifier(Looper.getMainLooper(), mContext, mBatteryStats,  
  17.                 mAppOps,createSuspendBlockerLocked("PowerManagerService.Broadcasts"),  
  18.                 mPolicy);//创建Notifier对象  
  19.   
  20.         mWirelessChargerDetector = new WirelessChargerDetector(sensorManager,  
  21.                createSuspendBlockerLocked("PowerManagerService.WirelessChargerDetector"),  
  22.                 mHandler);//创建检测无线充电的对象WirelessChargerDetector  
  23.         mSettingsObserver = new SettingsObserver(mHandler);//创建监听系统设置项变化的对象  
  24.   
  25.         mLightsManager = getLocalService(LightsManager.class);//LightsManager对象  
  26.         mAttentionLight =mLightsManager.getLight(LightsManager.LIGHT_ID_ATTENTION);  
  27.   
  28.         //初始化Power的管理模块  
  29.         mDisplayManagerInternal.initPowerManagement(  
  30.                 mDisplayPowerCallbacks,mHandler, sensorManager);  
  31.   
  32.         。。。。。。 //注册广播接收器  
  33.         。。。。。。//注册监听更多的settngs项的变化  
  34.         // Go.  
  35.         readConfigurationLocked();  
  36.         updateSettingsLocked();  
  37.         mDirty |= DIRTY_BATTERY_STATE;  
  38.         updatePowerStateLocked();  
  39.     }  
  40. }  

       systemReady()方法中通过调用getLocalService()方法得到一些在SystemServer中运行的内部服务的对象。在systemservice中也创建了一些内部使用的服务,这些服务没有通过ServiceManager发布,而是通过内部的LocalService类来管理。这些内部服务的共同特征是从SystemService类派生,通过getLocalService()方法可以获得参数关联的内部服务对象。 systemReady()方法完成的主要工作如下: l  获取最小、最大、默认3种屏幕亮度。 l  创建SystemSensorManager对象,用于和SensorService交互。 l  创建Notifer对象。用于广播系统中和Power相关的变化。 l  创建WirelessChargerDetector对象,用于无线充电检测的传感器。 l  调用DisplayManagerService的initPowerManagement()方法来初始化Power管理模块。 l  注册Observer监听系统设置的变化。 l  监听其他模块广播的Intent。PowerManagerService需要关注系统的变化,这里注册了很多系统广播的接收器。包括系统启动完成、“屏保”启动和关闭、用户切换、Dock插拔等。

报告用户活动—userActivity接口

PowerManager是PowerManagerService的代理类,它提供了一些接口让用户进程可以和PowerManagerService交互,下面分析一些接口来进一步了解PowerManagerService的工作。 userActivity()接口用于用户进程向PowerManagerService报告用户影响系统休眠的活动。例如,用户点击屏幕时,系统会调用该方法来告诉PowerManagerService用户点击的时间,这样PowerManagerService将更新内部保存的时间值,从而推迟系统休眠的时间。userActivity()方法主要通过调用内部的userActivityInternal()方法来完成工作,userActivity流程图如图2-2所示: 图2-2 userActivity流程图 具体代码如下: [java] view plain copy
  1.    private void userActivityInternal(long eventTime, int event, int flags, int uid) {  
  2.     synchronized (mLock) {  
  3.         if (userActivityNoUpdateLocked(eventTime, event, flags, uid)) {  
  4.             updatePowerStateLocked();  
  5.         }  
  6.     }  
  7. }  
userActivityInternal()先调用了userActivityNoUpdateLocked()方法,然后再调用updatePowerStateLocked()方法。userActivityNoUpdateLocked()方法只是把参数保存到内部变量中,并不会采取任何动作,而PowerManagerService中核心的方法是updatePowerStateLocked()。我们先看下userActivityNoUpdateLocked()方法: [java] view plain copy
  1. private boolean userActivityNoUpdateLocked(longeventTime,intevent,intflags,intuid) {  
  2.     if (eventTime< mLastSleepTime || eventTime < mLastWakeTime  
  3.             || !mBootCompleted ||!mSystemReady) {  
  4.         return false;  
  5.     }  
  6.   
  7.    Trace.traceBegin(Trace.TRACE_TAG_POWER, "userActivity");  
  8.     try {  
  9.         if (eventTime> mLastInteractivePowerHintTime) {  
  10.            powerHintInternal(POWER_HINT_INTERACTION, 0);