Android 8.1 Doze模式分析(二)——Light Doze模式

本文深入分析了Android 8.1的Light Doze模式,介绍了其在设备屏幕关闭但未静止时如何限制网络访问,延迟Job执行,并通过DeviceIdleController的状态转换阐述了Light Doze的工作原理和维护机制。
摘要由CSDN通过智能技术生成

概述

LightDoze表示轻度doze模式,如果设备处于未充电且屏幕关闭状态,但未处于静止状态时,就会进入Light Doze模式,在LightDoze模式中,会定期进行维护,这种维护会持续N分钟,在维护状态(maintenance)时,会进行网络的访问,和同步、JobScheduler的操作,然后又会进入Idle状态,持续多次。之后如果设备仍旧保持静止,则会进入Deep Doze模式,因此,如果没有运动传感器,则无法检测设备是否处于静止,因此无法进入Deep Doze模式。

原理

在DeviceIdleController(以下简称DIC)中,定义了几个用来表示Light Doze模式有关的值,这些值及其意义如下:


//表示轻度doze模式
private int mLightState;
//mLightState状态值,表示设备处于活动状态
private static final int LIGHT_STATE_ACTIVE = 0;
//mLightState状态值,表示设备处于不活动状态
private static final int LIGHT_STATE_INACTIVE = 1;
//mLightState状态值,表示设备进入空闲状态前,需要等待完成必要操作
private static final int LIGHT_STATE_PRE_IDLE = 3;
//mLightState状态值,表示设备处于空闲状态,该状态内将进行优化
private static final int LIGHT_STATE_IDLE = 4;
//mLightState状态值,表示设备处于空闲状态,要进入维护状态,先等待网络连接
private static final int LIGHT_STATE_WAITING_FOR_NETWORK = 5;
//mLightState状态值,表示设备处于维护状态
private static final int LIGHT_STATE_IDLE_MAINTENANCE = 6;
//mLightState状态值,表示设备轻度Doze被覆盖,开始进入深度Doze模式
private static final int LIGHT_STATE_OVERRIDE = 7;

从上述代码中可知,共有7个状态类表示Light Doze模式的不同状态。接下来开始分析Light Doze的实现以及其七个状态之间的转换。

在第一部分中分析启动流程时,当DCI启动流程的最后,会调用becomeInactiveIfAppropriateLocked()方法和becomeActiveLocked()方法,这两个方法用来切换交互/不可交互状态,这里先看第一个方法:

void becomeInactiveIfAppropriateLocked() {
   
    //仅当屏幕灭屏且没充电时,才能进入Doze模式,mForceIdle是shell设置相关
    if ((!mScreenOn && !mCharging) || mForceIdle) {
   
        //处理深度Doze,该状态表示当前设备处于交互状态,即亮屏、有动作移动
        if (mState == STATE_ACTIVE && mDeepEnabled) {
   
            //该状态表示DeepDoze的不可交互状态
            mState = STATE_INACTIVE;
            //重置标记值、取消原有的用于DeepDoze的alarm等
            resetIdleManagementLocked();
            //设置DeepAlarm,时间为30mins
            scheduleAlarmLocked(mInactiveTimeout, false);//30mins
        }
        //进入轻度Doze模式
        if (mLightState == LIGHT_STATE_ACTIVE && mLightEnabled) {
   
            //处理LightDoze模式进入不可交互状态
            mLightState = LIGHT_STATE_INACTIVE;
            //取消用于LightDoze的定时Alarm,重置标记值
            resetLightIdleManagementLocked();
            //设置用于LightDoze模式的Alarm,到达时间后回调
            //mLightAlarmListener,时间为5mins
            scheduleLightAlarmLocked(mConstants.LIGHT_IDLE_
                 AFTER_INACTIVE_TIMEOUT);//5mins
        }
    }
}

如果要执行该方法,首要条件必须是灭屏且放电,或者mForceIdle为true,mForceIdle是用于在adb shell下使用命令设置的,因此分析时可忽略。
如果满足灭屏且放电,则分别进行DeepDoze和LightDoze的判断.这里先分析Light Doze的判断,如果当前LightDoze处于LIGHT_STATE_ACTIVE状态,且mLightEnabled为true,则进行如下的处理:

  • 1.将mLightState变为LIGHT_STATE_INACTIVE状态,表示不可交互状态(灭屏);
  • 2.重置LightDoze相关的工作和值;
  • 3.发送一个5mins的定时Alarm。

在DIC启动时,将mLightState设置为了LIGHT_STATE_ACTIVE,所以这个值是一个默认值。先来看第二点,调用了resetLightIdleManagementLocked(),该方法如下:

void resetLightIdleManagementLocked() {
   
    //取消mLightAlarmListener要接受的Alarm
    cancelLightAlarmLocked();
}
void cancelLightAlarmLocked() {
   
    if (mNextLightAlarmTime != 0) {
   
        mNextLightAlarmTime = 0;
        mAlarmManager.cancel(mLightAlarmListener);
    }
}

如果设有用于LightDoze的定时Alarm,则进行取消。
再来看看第三点,在scheduleLightAlarmLocked()方法中:

void scheduleLightAlarmLocked(long delay) {
   
    mNextLightAlarmTime = SystemClock.elapsedRealtime() + delay;
    //到达时间后,回调mLightAlarmListener.onAlarm()
    mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
            mNextLightAlarmTime, "DeviceIdleController.light", 
            mLightAlarmListener, mHandler);
}

结合第二点和第三点,可以认为重置了一个用于LightDoze的Alarm定时器。mLightAlarmListener用来接受Alarm的回调,定时器到达指定时间后,会触发mLightAlarmListener接口的onAlarm()方法,从而在onAlarm()中完成接下来的工作࿰

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值