深入理解 Android:PowerManagerService、BatteryService/BatteryStatsService
PowerManagerService 简介:
PowerManagerService从IPowerManager.Stub类派生,并实现了Watchdog.Monitor和LocalPowerManager接口;客户端使用
PowerManager类,其内部通过代表BinderProxy端的mService成员变量与PowerManagerService进行 Binder 通信;PowerManagerService和BatteryService、BatteryStatsService、LightService、SensorManager、ActivityManagerService、WindowManagerService等许多系统服务均有交互;
PowerManagerService 的创建:
PowerManagerService由SystemServer在ServerThread线程中创建;调用构造方法:
获取当前进程的 uid 和 pid;
调用
Power.setLastUserActivityTimeout()设置超时为一周,Power类封装了同 Linux 内核交互的接口;初始化
mUserState和mPowerState变量为0;调用
Watchdog.getInstance().addMonitor()将自己添加到Watchdog监控队列;
调用
PowerManagerService.init():获取
LightsService、ActivityManagerService、BatteryService(查询电池状态及电量)、BatteryStatsService(统计耗电量)四个对象;调用
nativeInit()函数,创建全局引用对象gPowerManagerServiceObj;创建两个
HandlerThread类型的工作线程mScreenOffThread(控制屏幕关闭时的亮度来调节)和mHandlerThread(主要工作线程):创建
UnsynchronizedWakeLock对象,保证工作中不至于突然掉电;创建广播通知的
Intent,用于通知SCREEN_ON和SCREEN_OFF消息;获取配置参数,有的是编译时确定的,有的是
Settings数据库维护的;创建
ContentQueryMap对象,用于查询Settings数据库,并创建SettingsObserver监视其变化;注册接收通知的
BoroadcastReceiver;添加
ContentObserver监视Settings数据库中secure表的变化;
4.调用
updateNativePowerStateLocked()更新 Native 层的电源状态;5.调用
forceUserActivityLocked()强制触发 UserActivity,它意味着手机将被唤醒,且屏幕超时时间也将重新计算;调用
PowerManagerService.systemReady():创建
SensorManager对象,用于和传感器交互;调用
setPowerState()设置电源状态;判断是否启用LightSensor;调用
BatteryStatsService的noteScreenBrightness()和noteScreenOn()方法;
处理
ACTION_BOOT_COMPLETED广播:再次调用
userActivity()触发 UserActivity 事件;如果处于 USB 充电状态,调用
WakeLock的acquire()方法保持唤醒,否则调用release()进入休眠;
WakeLock:
newWakeLock():创建
PowerManager.WakeLock对象.通过传入的flags参数控制 CPU 、屏幕、键盘的休眠状态;创建
Binder对象,除了作为 Token,也用于PowerManagerService监听客户端的生死;
acquire(),实际调用PowerManagerService.acquireWakeLock()方法:读取 Binder 调用方 uid 和 pid;
检查 Manifest 中的
WAKE_LOCK权限;如果传入的WorkSource参数不为空,检查是否有UPDATE_DEVICE_STATS权限;创建
PowerManagerService.WakeLock对象,它实现了IBinder.DeathRecipient接口,用于接收 Binder 死亡通知;将客户端传入的
flags转换为minState成员变量,将当前WakeLock加入到mLocks;判断
flags是否和屏幕有关,更新引用计数,调用gatherSate()统计当前活跃的WakeLock的minState(进行或运算);调用
setPowerState(mWakeLockState|mUserState):内部通过
Power类(android_os_Power.cpp)、LightService(com_android_server_LightService.cpp)与内核和底层硬件交互;mWakeLockState参数来源于当前活跃的WakeLock的minState,而mUserState表示用户触发事件导致的电源状态;检查是否否打开 Proximity 传感器(不需要点亮屏幕),是否电量低,是否未启动完成(需要全亮);
根据
mStillNeedSleepNotification判断是否调用sendNotificationLocked(),该方法用于触发SCREEN_ON/SCREEN_OFF广播;PowerManagerService还提供了一个preventScreenOn()方法用于切换页面时阻止屏幕点亮(比如启动 Activity 时突然来电);根据
reallyTurnScreenOn判断是否需要点亮屏幕,并通知BatteryStatsService做电量统计;更新键盘灯和按键灯状态;
当 WakeLock 标志和
PARTIAL_WAKE_LOCK(只有 CPU 唤醒) 有关时,仅简单调用Power.acquireWakeLock();
BatteryService初始化:
创建
Led对象,用于控制提示灯;获取BatteryStatsService对象;读取三个阈值:
mCriticalBatteryLevel(电量低于该值会关机)、mLowBatteryWarningLevel(电量低于该值会警告)、mLowBatteryCloseWarningLevel(电量高于该值停止提示);启动
mPowerSupplyOberver,监听 power_supply 信息;如果 /sys/devices/virtual/switch/invalid_charger/state 文件存在,启动
mInvalidChargerObserver;调用
update()查询 HAL 层电池信息:通过 JNI 设置 Java 层的 temp 文件路径等变量;
通过文件读取电池温度、电压、电量等信息,并通过 JNI 写入 Java 层;
调用
BatteryStatsService.setBatteryState()设置电池状态;如果电量不够或电池过热,弹窗提示;
5.记录信息到日志文件;发送低电广播(如果需要);更新 LED 灯状态;
BatteryStatsService:
与其他系统服务不同,
BatteryStatsService是在ActivityManagerService中创建和注册的:创建
BatteryStatsService对象;调用
BatteryStatsService.getActiveStatistics().readLocked()和BatteryStatsService.getActiveStatistics().writeAsyncLocked()操作日志文件;调用
BatteryStatsService.getActiveStatistics().setCallback()设置回调,该回调也用于信息统计;调用
BatteryStatsService.publish()注册到ServiceManager,并从 /frameworks/base/core/res/res/xml/power_profile.xml 文件读取相关参数,该文件定义了和硬件相关的各种操作的耗电情况(以 mA.h 为单位);
BatteryStatsService内部通过成员变量mStats指向其子类BatteryStatsImpl对象,它实现了Parcelable接口;getStatistics()方法:检查调用进程是否有
BATTERY_STATS权限;将
BatteryStatsImpl信息写入Parcel包,序列化为一个 buffer,通过 Binder 传递;
BatteryStatus.Uid家族:在 Android 4.0 中,和进程相关的用电统计并非以 pid 划分,而是 uid;
Wakelock用于统计该 Uid 对应进程使用WakeLock的用电情况;Proc用于统计 Uid 中某个进程的用电情况;Pkg用于统计某个特定 Package 用电情况,其内部类Serv用于统计该 Package 下Service用电情况;Sensor用于统计传感器用电情况;
BatteryStatsImpl:
BatteryStatsImpl实现了StopwatchTimer、SamplingTimer、Counter、SamplingCounter等用于电量统计的测量工具类;BatteryStatsImpl还定义了一个Unpluggable接口用于统计电量,比如 USB 连接时调用plug(),断开时调用unplug();构造方法:
创建
JournaledFile日志文件对象,内部包含原始文件和临时文件,双备份防止读写过程中信息丢失或出错;创建
Handler对象和StopwatchTimer、Counter等对象;调用
initTimes()初始化统计时间,注意系统时间分为 uptime 和 realtime,二者都从系统启动开始算,但 uptime 不包括休眠时间;调用
initDischarge()初始化和电池 level 相关的变量;调用
clearHistoryLocked()删除用电统计历史记录;
setBatteryState():判断是否为电池供电状态是否变化,如果变化(USB 插拔),调用
setOnBatteryLocked();如果供电状态未变化,判断电池信息是否变化(电量电压等),如果变化则调用
addHistoryRecordLocked()添加一次历史记录;
setOnBatteryLocked():发送消息给
Handler,将在内部调用ActivityManagerService设置的回调函数;如果是电池供电,在满足条件的情况下会清空电量统计数据;
读取 /proc/wakelock 文件;
调用
addHistoryRecordLocked()添加一次历史记录;记录时间和电量;
noteScrrenOnLocked():调用
addHistoryRecordLocked()添加一次历史记录;启动
StopwatchTimer;调用
noteStartWakeLocked()更新WakeLock用电统计;调用
updateDischargeScreenLevelLocked()更新电池 Level;
noteUserActivity():调用
getUidStatsLocked()获得 Uid 对象,并调用其noteUserActivityLocked();内部定义了一个七元
Counter数组mUserActivityCounters,对应其中不同的事件类型;调用对应 type 的
Counter.stepAtomic()使计数器加一;
StopwatchTimer:
构造方法会传入一个
ArrayList<Unpluggable>类型的mUnpluggables参数;调用
startRunningLocked()开始统计,主要是读取电池总的使用时间、计数控制;调用
stopRunningLocked()结束统计,主要是统计此次启动/停止周期的时间、计数控制;
参考: