Android6.0新特性之DozeMode

来源:互联网 发布:下载中国建筑网软件 编辑:程序博客网 时间:2024/04/29 18:36
电量消耗问题一直是困扰Android设备商和Google的大问题。
由于Android的开放特性,越来越多的应用会在后台运行时“假死”,即不进入真正的Sleep,而是不断在后台轮询搜集用户行为或者保持某些长链接来保障数据的实时性,而Android自身并未出台对应的策略来约束或者限制这类应用行为,当这类应用越来越多,就会导致用户的Android设备电量越来越难维持,甚至手机越来越烫。
以PUSH为例,由于Google未在中国市场推行G(oogle) C(loud) M(essaging)的PUSH机制, 导致中国市场PUSH开发包分散凌乱,APP VENDOR各家有各家的解决方案,这样就造成一台Android设备上会同时存在几个进程到十几个进程在后台做PUSH轮询,电量消耗变大。
为了应对这类行为,也为了节约设备电量,Google从Android M开始引入了Doze Mode(打盹模式)。
这个模式的优势在于当用户熄灭显示屏后,如果各传感器反馈数据表示设备已经进入静置,在一段时间后,仅有白名单内的应用或进程可以使用网络,CPU等资源。
如此以来,设备制造商只需要关注于哪些应用需要加入白名单即可防止用户进程无意义的电力消耗。
请注意,Google此举并非为了限制某些行为,而是为了将资源集中配置,又以PUSH为例:Google在原生实现中将G(oogle) M(obile) S(ervice)的包都加入了白名单,也即是APP Vendor仍然可以使用GCM来做Push,这样Google就达到了一举两得:一方面保证了设备DOZE时只有一个PUSH轮询进程,另一方面强制推广GCM。
下面是Developer网站的介绍:

Doze mode is introduced in Android 6.0 (API level 23), Doze improves battery life by deferring CPU and network activities when a user leaves a device unplugged, stationary, and with the screen turned off

DozeMode工作原理

Doze Mode从设计上采用了状态机模式。
一共将Android设备运行状态划分了7个有效状态:

这7个状态会根据设备运行时外设的变化而发生如下的状态迁移:


如上图,当用户关闭屏幕后,立刻从ACTIVE迁移至INACTIVE
INACTIVE 10分钟后,若设备仍然保持静置,则迁入IDLE_SUSPENDING状态,进入这状态表示Android设备已经开始准备进入IDLE考察期
进入考察期30分钟后,如果没有出现屏幕被点亮的情况,则继续迁入SENSING状态
在接下来的4分钟内,如果设备依然保持静置,或者在4分钟内收到来自AnyMotionDetector的回报被告知Android设备处于静置状态,那么将会迁入状态LOCATING
LOCATING会进行30秒,如果在30秒后设备保持静置,又或者30秒内收到来自AnyMotionDetector的回报被告知Android设备已经处于静置状态,那么就会迁入Doze模式的第一个状态IDLE_MAINTENANCE
IDLE_MAINTENANCE的目的会在之后详细介绍,IDLE_MAINTENANCE第一次会等待5分钟,之后均为10分钟,若在此期间没有出现屏幕点亮或者AnyMotionDetector计算出的大幅度运动,那么就会迁入真正的IDLE状态
IDLE状态就是真正的DOZE模式了,第一次进入时会保持60分钟,之后每次递增60分钟,最多至360分钟,如果这期间没有屏幕点亮或者AnyMotionDetector计算出大幅度运动,那么在时间耗尽时会迁入IDLE_MAINTENANCE状态,整个DOZE模式就是这两个状态的相互迁移
对于任何模式,在发生迁移前如果AnyMotionDetector有侦测出大幅度运动,都将会重新回到ACTIVE的起点。

DeviceIdleController有四个内部类
Class                                Details
BinderService         提供跨进程的Service服务
LocalService     为SystemServer进程内其他线程提供函数调用
MyHandler               处理主线程消息队列
Constans   提供常量配置,如各个状态迁移的等待时间等


DeviceIdleController内关键成员的作用
Member Details
mAlarmManager Alarm的发送,主要用于处理各个状态间迁移的时间控制
mBatteryStats 控制BatteryStats启停,在进入IDLE状态后停止BatteryStats统计,在进入IDLE_MAINTENANCE后恢复BatteryStats统计
mLocalPowerManager PowerManager代理,用于通知PowerManager更新白名单
mNetworkPolicyManager NetworkPolicyManager代理,用于通知NetworkPolicy开启或关闭IDLE模式
mDisplayManager DisplayManager代理,用于获得当前Screen亮灭回调,从而判断是否需要进入INACTIVE模式
mSensorManager SensorManager,用于获取当前用户是否出现移动,若出现移动,无论当前状态,开始新一轮的Doze模式倒计时
mSigMotionSensor 实际的Sensor代理,与mSensorManager协同工作
mLocationManager LocationManager代理,用于判定用户是否出现移动,如果出现移动,无视当前状态,开始新一轮的Doze模式倒计时
mAnyMotionDetector AnyMotionDetector实例,用于判定当前用户行为是否是大幅度运动
mEnabled Doze模式是否被支援,在属性R.bool.config_enableAutoPowerModes内被定义
mScreenOn 当前Screen是否被点亮,这是处理Screen亮灭的关键信息mCharging,若该值为True,将无法进入Doze模式
mCharging 当前设备是否在充电,若该值为True,将无法进入Doze模式
mState 当前状态机状态
mHandler 当前Handler,用于POST消息至主线程队列
    

   

DeviceIdleController内关键成员函数的作用
Member Function Details
onStart DeviceIdleController被SystemServer启动,白名单的初始化会在此处完成
onBootPhase System Ready后,此时各个System Service均已经Standy By,Listener的初始化会在此处完成,同时PowerManager会被通知到更新白名单
onAnyMotionResult 用户出现了移动状态变化,若从静置到大幅度移动,同时Screen熄灭,且未在充电,那么会开始全新一轮的Doze模式倒计时;若从运动到静置,则Doze模式倒计时向前迁移一个状态
updateDisplayLocked Screen状态发生变化,若由亮到灭且未充电,则开始新一轮的Doze模式倒计时,若由灭到亮,则退出Doze模式,回到ACTIVE状态
updateChargingLocked Cable连接发生变化,若由连接到断开且Screen熄灭,则开始新一轮的Doze模式倒计时,若由断开到连接,则退出Doze模式,回到ACTIVE状态
scheduleAlarmLocked 发送Alarm,若从IDLE_MAINTENANCE,则发送IDLE_UNTIL Alarm,也即是在下次广播来之前AlarmManager均保持IDLE,其他则发送普通Alarm
stepIdleStateLocked 状态机迁移控制进程,完成状态机各个状态的迁移
dump dumpsys方法,用于系统调试,使用方法将在下面介绍s


DeviceIdleController同时实现了AnyMotionDetector内部Interface:DeviceIdleCallback,该回调函数用于AnyMotionDetector分析Sensor数据后发现Android设备出现状态的大幅度转变时通知回调的实现者
综上看出,DeviceIdleController主要完成三部分工作:
1. 搜集外设信息,判断用户状态
2. 根据用户状态控制状态迁移,完成Doze模式启停
3. Doze模式启动时通知电量管理部件进入省电模式,Doze模式停止时通知电量管理部件恢复正常模式
因此, Doze模式的核心是DeviceIdleController,但是DeviceIdleController并不是Doze模式的实际执行者,它只负责根据外设状态推测用户行为,并一步步将Android设备推入Doze模式,但是进入Doze模式后实际的省电操作者仍然是涉及电量控制的各个模块
       

如何调试DOZE模式 直接使用adb shell dumpsys deviceidle -h就可以查看dumpsys提供的调试手段:命令输出-h显示帮助菜单step每次调用就会进入一次stepIdleStateLocked,从而实现状态机的状态逐步迁移force-idle让Android设备忽视Screen状态以及Cable连接状态,直接开始一轮Doze模式倒计时disable取消对Doze模式的支持enable恢复对Doze模式的支持enabled若支持Doze模式,返回1;否则返回0whitelist终端打印当前的白名单whitelist +/- [xxxxxx]将xxxxxx包加入/移出白名单tempwhitelist [xxxxxx]将xxxxxx包加入临时白名单

   

1 0