首页 > 编程知识 正文

Android 81 Doze模式分析四Doze模式的退出

时间:2023-05-06 04:08:23 阅读:256027 作者:4908

概述

Doze的退出,说的更严格一点,就是当Doze模式的状态由其他状态变为ACTIVE状态。简而言之,退出Doze模式有三种情况:屏幕亮屏、插入充电器、设备有移动。下面就这三种情况进行下分析。

在前面的分析中我们有见到过becomeActiveLocked()方法,这个方法当时没有进行分析,这个方法就是用来退出Doze的,严格来说,是将Doze状态置为了ACTIVE状态,从而退出IDLE状态或MAINTENANCE状态。因此,不管是何种方式退出Doze,都会调用这个方法。该方法如下:

void becomeActiveLocked(String activeReason, int activeUid) { if (mState != STATE_ACTIVE || mLightState != STATE_ACTIVE) { //设置一个Handler,在Handler中通知PMS、发送idle changed 广播 scheduleReportActiveLocked(activeReason, activeUid); //将DeepDoze状态值置为STATE_ACTIVE mState = STATE_ACTIVE; //将LightDoze状态值置为LIGHT_STATE_ACTIVE mLightState = LIGHT_STATE_ACTIVE; //多久后进入INACTIVE状态 mInactiveTimeout = mConstants.INACTIVE_TIMEOUT; mCurIdleBudget = 0; mMaintenanceStartTime = 0; //重置DeepDoze相关属性值、alarm、listener等 resetIdleManagementLocked(); //重置LightDoze相关属性值、alarm、listener等 resetLightIdleManagementLocked(); }} 1.屏幕亮灭屏

当亮屏或灭屏时,PMS发送亮灭屏广播,DIC中监听了亮灭屏的广播,负责接受该广播并进行屏幕状态改变后的操作:
注册广播:

filter = new IntentFilter();filter.addAction(Intent.ACTION_SCREEN_OFF);filter.addAction(Intent.ACTION_SCREEN_ON);getContext().registerReceiver(mInteractivityReceiver, filter);

接收到广播后进行处理:

private final BroadcastReceiver mInteractivityReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { synchronized (DeviceIdleController.this) { updateInteractivityLocked(); } }};

在updateInteractivityLocked()方法中更新LightDoze和DeepDoze的状态,这个方法在第一篇文章中分析过了。

2.充电状态改变

当电池状态时,在BatteryService中会发送广播,DIC也对该广播进行了监听:

IntentFilter filter = new IntentFilter();filter.addAction(Intent.ACTION_BATTERY_CHANGED);getContext().registerReceiver(mReceiver, filter);

接收到广播后进行处理:

private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { switch (intent.getAction()) { ............ case Intent.ACTION_BATTERY_CHANGED: { synchronized (DeviceIdleController.this) { int plugged = intent.getIntExtra("plugged", 0); updateChargingLocked(plugged != 0); } } break; .................... } }};

当接收到该广播后,调用updateChargingLocked(plugged != 0)来更新状态,参数表示是否插有充电线,该方法如下:

void updateChargingLocked(boolean charging) { //由充电转变为放电 if (!charging && mCharging) { mCharging = false; if (!mForceIdle) { //进入INACTIVE状态,开始Doze模式 becomeInactiveIfAppropriateLocked(); } } else if (charging) {//由放电转变为充电 mCharging = charging; if (!mForceIdle) { //Doze状态退出ACTIVE状态,退出Doze模式 becomeActiveLocked("charging", Process.myUid()); } }}

最终,也会调用becomeActiveLocked()退出Doze模式。

3.其他服务通过Binder调用

DeviceIdleController内部Binder也提供了用于退出Doze的接口:

@Override public void exitIdle(String reason) { getContext().enforceCallingOrSelfPermission(Manifest.permission.DEVICE_POWER, null); long ident = Binder.clearCallingIdentity(); try { exitIdleInternal(reason); } finally { Binder.restoreCallingIdentity(ident); }}

其内部也是通过调用becomeActiveLocked()方法退出Doze的:

public void exitIdleInternal(String reason) { synchronized (this) { becomeActiveLocked(reason, Binder.getCallingUid()); }} 4.MotionSensor检测状态发生

这种情况和以上几种情况略不同,这种情况下Doze的退出是瞬时的,会将两个状态值都转换为STATE_ACTIVE后,又会立即调用becomeInactiveIfAppropriateLocked()方法进入INACTIVE状态,可以说是个“瞬时”退出。当MotionSensor检测到有移动时,则会退出Doze,处理逻辑在handleMotionDetectedLocked()中:

void handleMotionDetectedLocked(long timeout, String type) { boolean becomeInactive = false; if (mState != STATE_ACTIVE) { //通过Handler通知PMS、NetworkPolicy、发送IDLE_CHANGED广播等 scheduleReportActiveLocked(type, Process.myUid()); mState = STATE_ACTIVE;//将DeepDoze状态变为ACTIVE状态 mInactiveTimeout = timeout; mCurIdleBudget = 0; mMaintenanceStartTime = 0; becomeInactive = true; } if (mLightState == LIGHT_STATE_OVERRIDE) { mLightState = STATE_ACTIVE;//将LightDoze状态变为ACTIVE状态 becomeInactive = true; } if (becomeInactive) { //进入INACTIVE状态 becomeInactiveIfAppropriateLocked(); }}

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。