深入理解 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()
结束统计,主要是统计此次启动/停止周期的时间、计数控制;
参考: