前面我们介绍Doze模式的时候介绍过WakeLock白名单,WakeLock进入Doze接口等。这篇博客我们详细分析下,WakeLock在Doze模式下如何生效。
设置白名单
在DeviceIdleController中我们调用PowerManagerService的如下接口,来设置WakeLock的白名单。注意这里设置的appid就是uid。
@Override
public void setDeviceIdleWhitelist(int[] appids) {
setDeviceIdleWhitelistInternal(appids);
}
setDeviceIdleWhitelistInternal接口,就是把白名单放到mDeviceIdleWhitelist中。如果当前在Doze模式下,调用updateWakeLockDisabledStatesLocked函数
void setDeviceIdleWhitelistInternal(int[] appids) {
synchronized (mLock) {
mDeviceIdleWhitelist = appids;
if (mDeviceIdleMode) {//Doze模式下
updateWakeLockDisabledStatesLocked();
}
}
}
updateWakeLockDisabledStatesLocked函数就是遍历所有的WakeLock,然后又持cpu锁的(这才是阻止设备睡眠的根本),调用setWakeLockDisabledStateLocked函数,这个函数就是是否要把这个WakeLock给disable。如果有改变调用updatePowerStateLocked更新状态
private void updateWakeLockDisabledStatesLocked() {
boolean changed = false;
final int numWakeLocks = mWakeLocks.size();
for (int i = 0; i < numWakeLocks; i++) {
final WakeLock wakeLock = mWakeLocks.get(i);
if ((wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK)
== PowerManager.PARTIAL_WAKE_LOCK) {//持cpu锁
if (setWakeLockDisabledStateLocked(wakeLock)) {//是否将WakeLock disable
changed = true;
if (wakeLock.mDisabled) {
// This wake lock is no longer being respected.
notifyWakeLockReleasedLocked(wakeLock);
} else {
notifyWakeLockAcquiredLocked(wakeLock);
}
}
}
}
if (changed) {
mDirty |= DIRTY_WAKE_LOCKS;
updatePowerStateLocked();//有改变要更新power状态
}
}
下面我们再来看下setWakeLockDisabledStateLocked函数,这个函数就是是否要将这个WakeLock置为disable。我们看下面的注释。
private boolean setWakeLockDisabledStateLocked(WakeLock wakeLock) {
if ((wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK)
== PowerManager.PARTIAL_WAKE_LOCK) {
boolean disabled = false;
if (mDeviceIdleMode) {//当前在Doze模式
final int appid = UserHandle.getAppId(wakeLock.mOwnerUid);
// If we are in idle mode, we will ignore all partial wake locks that are
// for application uids that are not whitelisted.
if (appid >= Process.FIRST_APPLICATION_UID &&//是一个应用,而且在白名单和临时白名单中都没有这个应用
Arrays.binarySearch(mDeviceIdleWhitelist, appid) < 0 &&
Arrays.binarySearch(mDeviceIdleTempWhitelist, appid) < 0 &&
mUidState.get(wakeLock.mOwnerUid,
ActivityManager.PROCESS_STATE_CACHED_EMPTY)
> ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
disabled = true;//将这个WakeLock disable
}
}
if (wakeLock.mDisabled != disabled) {
wakeLock.mDisabled = disabled;
return true;
}
}
return false;
}
设置Doze模式
设置Doze模式是通过PowerManagerService的如下接口
@Override
public boolean setDeviceIdleMode(boolean enabled) {
return setDeviceIdleModeInternal(enabled);
}
setDeviceIdleModeInternal逻辑也很简单,设置mDeviceIdleMode然后调用updateWakeLockDisabledStatesLocked函数更新WakeLock。
boolean setDeviceIdleModeInternal(boolean enabled) {
synchronized (mLock) {
if (mDeviceIdleMode != enabled) {
mDeviceIdleMode = enabled;
updateWakeLockDisabledStatesLocked();
if (enabled) {
EventLogTags.writeDeviceIdleOnPhase("power");
} else {
EventLogTags.writeDeviceIdleOffPhase("power");
}
return true;
}
return false;
}
}
Power管理Disable的WakeLock
在PowerManagerService中更新power的状态都是调用updatePowerStateLocked的,其中会调用updateWakeLockSummaryLocked来统计WakeLock,我们来看下这个函数
private void updateWakeLockSummaryLocked(int dirty) {
if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_WAKEFULNESS)) != 0) {
mWakeLockSummary = 0;
final int numWakeLocks = mWakeLocks.size();
for (int i = 0; i < numWakeLocks; i++) {
final WakeLock wakeLock = mWakeLocks.get(i);
switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
case PowerManager.PARTIAL_WAKE_LOCK://当时持cpu锁
if (!wakeLock.mDisabled) {//只有其mDisabled为false时,才会让其持cpu锁。
// We only respect this if the wake lock is not disabled.
mWakeLockSummary |= WAKE_LOCK_CPU;
}
break;
WakeLock的管理逻辑很简单,会在DeviceIdleController设置白名单,然后进入Doze模式也会主动调用PowerManagerService接口设置状态,并且将相应的WakeLock的mDisabled置为true,让其无法持cpu锁。