概述
Deep Doze,也就是Android的Doze模式了,表示深度Doze,比起LightDoze,它将进行更多的限制:无法进行网络访问和 GPS/WLAN 扫描、唤醒被忽略、闹钟和作业/同步被延迟。当然,它的触发条件也将更加苛刻:灭屏、未充电、静止。
因此,如果要支持DeepDoze,则相应设备还必须具有大幅度动作检测器 (SMD),否则,无法探测到到底是静止还是移动。
原理
DIC中也定义了七个用来表示Deep Doze模式的值:
//表示doze模式
private int mState;
//mState值,表示设备处于活动状态
private static final int STATE_ACTIVE = 0;
//mState值,表示设备处于不交互状态,灭屏、静止
private static final int STATE_INACTIVE = 1;
//mState值,表示设备刚结束不交互状态,等待进入IDLE状态
private static final int STATE_IDLE_PENDING = 2;
//mState值,表示设备正在感应动作
private static final int STATE_SENSING = 3;
//mState值,表示设备正在定位
private static final int STATE_LOCATING = 4;
//mState值,表示设备处于空闲状态,也即Doze模式
private static final int STATE_IDLE = 5;
//mState值,表示设备正处于Doze模式,紧接着退出Doze进入维护状态
private static final int STATE_IDLE_MAINTENANCE = 6;
和Light Doze一样,DeepDoze模式也从becomeInactiveIfAppropriateLocked()
方法开始,这点已经在分析LightDoze时分析了,这里再来看一遍,该方法中涉及到Doze模式的代码如下:
void becomeInactiveIfAppropriateLocked() {
if ((!mScreenOn && !mCharging) || mForceIdle) {
if (mState == STATE_ACTIVE && mDeepEnabled) {
//Doze模式状态由ACTIVE变为INACTIVE
mState = STATE_INACTIVE;
//重置Doze模式相关标记值、定时器
resetIdleManagementLocked();
//设置一个30mins的定时
scheduleAlarmLocked(mInactiveTimeout, false);//30mins
}
.......................
}
当DeepDoze处于活动状态,并且Doze模式可用时,会通过Alarm一步步进入IDLE状态。首先会由交互状态变为不交互状态时,会重置所有数据后发送一个定时Alarm操作,重置操作如下:
void resetIdleManagementLocked() {
mNextIdlePendingDelay = 0;
mNextIdleDelay = 0;
//下次LightDoze的定时时间
mNextLightIdleDelay = 0;
//取消DeepDoze发送的定时Alarm
cancelAlarmLocked();
//取消用于STATE_SENSING状态时长的Alarm
cancelSensingTimeoutAlarmLocked();
//取消GPS定位和Generic定位的更新
cancelLocatingLocked();
//取消、解绑接收传感器的触发事件
stopMonitoringMotionLocked();
//停止检测器检测
mAnyMotionDetector.stop();
}
重置后会重新设置一个定时Alarm,时长为15分钟,代码如下:
void scheduleAlarmLocked(long delay, boolean idleUntil) {
if (mMotionSensor == null) {
//如果没有运动传感器,则返回,因为无法判断设备是否保持静止
if (mMotionSensor == nullr) {
return;
}
//设置DeepDoze的定时Alarm
mNextAlarmTime = SystemClock.elapsedRealtime() + delay;
if (idleUntil) {
mAlarmManager.setIdleUntil(AlarmManager.ELAPSED_REALTIME_WAKEUP,
mNextAlarmTime, "DeviceIdleController.deep",
mDeepAlarmListener, mHandler);
} else {
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
mNextAlarmTime, "DeviceIdleController.deep",
mDeepAlarmListener, mHandler