新增的Idle状态感觉在PowerManagerService的代码变动不大,但是其功能其实还有很大的变化,我们先看下持锁这个函数新加的地方。
private void acquireWakeLockInternal(IBinder lock, int flags, String tag, String packageName, WorkSource ws, String historyTag, int uid, int pid) { synchronized (mLock) { if (DEBUG_SPEW) { Slog.d(TAG, "acquireWakeLockInternal: lock=" + Objects.hashCode(lock) + ", flags=0x" + Integer.toHexString(flags) + ", tag=\"" + tag + "\", ws=" + ws + ", uid=" + uid + ", pid=" + pid); } WakeLock wakeLock; int index = findWakeLockIndexLocked(lock); boolean notifyAcquire; if (index >= 0) { wakeLock = mWakeLocks.get(index); if (!wakeLock.hasSameProperties(flags, tag, ws, uid, pid)) { // Update existing wake lock. This shouldn't happen but is harmless. notifyWakeLockChangingLocked(wakeLock, flags, tag, packageName, uid, pid, ws, historyTag); wakeLock.updateProperties(flags, tag, packageName, ws, historyTag, uid, pid); } notifyAcquire = false; } else { wakeLock = new WakeLock(lock, flags, tag, packageName, ws, historyTag, uid, pid); try { lock.linkToDeath(wakeLock, 0); } catch (RemoteException ex) { throw new IllegalArgumentException("Wake lock is already dead."); } mWakeLocks.add(wakeLock); setWakeLockDisabledStateLocked(wakeLock);//新增 notifyAcquire = true; } applyWakeLockFlagsOnAcquireLocked(wakeLock, uid); mDirty |= DIRTY_WAKE_LOCKS; updatePowerStateLocked(); if (notifyAcquire) { // This needs to be done last so we are sure we have acquired the // kernel wake lock. Otherwise we have a race where the system may // go to sleep between the time we start the accounting in battery // stats and when we actually get around to telling the kernel to // stay awake. notifyWakeLockAcquiredLocked(wakeLock); } } }
在新建一个wakelock的时候,会调用setWakeLockDisabledStateLocked这个函数,我们来看下。
private boolean setWakeLockDisabledStateLocked(WakeLock wakeLock) { if ((wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) == PowerManager.PARTIAL_WAKE_LOCK) { boolean disabled = false; if (mDeviceIdleMode) { 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; } } if (wakeLock.mDisabled != disabled) { wakeLock.mDisabled = disabled; return true; } } return false; }如果mDeviceIdleMode为true,满足条件判断,wakelock的mDisabled为true
这里PowerManagerService的流程就不讲了,前面分析PowerManagerService的博客都分析过。
再最后调用updateWakeLockSummaryLocked的时候会统计所有的waklock锁
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);//遍历所有的wakelock switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) { case PowerManager.PARTIAL_WAKE_LOCK: if (!wakeLock.mDisabled) {//mDisabled为false,才能持cpu锁 // We only respect this if the wake lock is not disabled. mWakeLockSummary |= WAKE_LOCK_CPU; } break; case PowerManager.FULL_WAKE_LOCK: mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_BUTTON_BRIGHT; break; case PowerManager.SCREEN_BRIGHT_WAKE_LOCK: mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT; break; case PowerManager.SCREEN_DIM_WAKE_LOCK: mWakeLockSummary |= WAKE_LOCK_SCREEN_DIM; break; case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK: mWakeLockSummary |= WAKE_LOCK_PROXIMITY_SCREEN_OFF; break; case PowerManager.DOZE_WAKE_LOCK: mWakeLockSummary |= WAKE_LOCK_DOZE; break; case PowerManager.DRAW_WAKE_LOCK: mWakeLockSummary |= WAKE_LOCK_DRAW; break; } } // Cancel wake locks that make no sense based on the current state. if (mWakefulness != WAKEFULNESS_DOZING) { mWakeLockSummary &= ~(WAKE_LOCK_DOZE | WAKE_LOCK_DRAW); } if (mWakefulness == WAKEFULNESS_ASLEEP || (mWakeLockSummary & WAKE_LOCK_DOZE) != 0) { mWakeLockSummary &= ~(WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM | WAKE_LOCK_BUTTON_BRIGHT); if (mWakefulness == WAKEFULNESS_ASLEEP) { mWakeLockSummary &= ~WAKE_LOCK_PROXIMITY_SCREEN_OFF; } } // Infer implied wake locks where necessary based on the current state. if ((mWakeLockSummary & (WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM)) != 0) { if (mWakefulness == WAKEFULNESS_AWAKE) { mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_STAY_AWAKE; } else if (mWakefulness == WAKEFULNESS_DREAMING) { mWakeLockSummary |= WAKE_LOCK_CPU; } } if ((mWakeLockSummary & WAKE_LOCK_DRAW) != 0) {//这个好像是给WMS绘制用的 mWakeLockSummary |= WAKE_LOCK_CPU; } if (DEBUG_SPEW) { Slog.d(TAG, "updateWakeLockSummaryLocked: mWakefulness=" + PowerManagerInternal.wakefulnessToString(mWakefulness) + ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary)); } } }
这样的话当系统处于idle状态,而且不是在白名单里的应用持的cpu锁是无效的。
我们再来看下PowerManagerService中的设置设备Idle的接口:
@Override public void setDeviceIdleMode(boolean enabled) { setDeviceIdleModeInternal(enabled); }这个接口是LocalService的,所以只能在SystemServer中的service调用。
再看下setDeviceIdleModeInternal函数:
void setDeviceIdleModeInternal(boolean enabled) { synchronized (mLock) { if (mDeviceIdleMode != enabled) { mDeviceIdleMode = enabled;//设置状态 updateWakeLockDisabledStatesLocked();//更新wakelock if (enabled) { EventLogTags.writeDeviceIdleOnPhase("power"); } else { EventLogTags.writeDeviceIdleOffPhase("power"); } } } }然后就是遍历每个wakelock,重新去设置其mDisabled。
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) { if (setWakeLockDisabledStateLocked(wakeLock)) {//重新设置mDisabled 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(); } } private boolean setWakeLockDisabledStateLocked(WakeLock wakeLock) { if ((wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) == PowerManager.PARTIAL_WAKE_LOCK) { boolean disabled = false; if (mDeviceIdleMode) { 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; } } if (wakeLock.mDisabled != disabled) { wakeLock.mDisabled = disabled; return true; } } return false; }
设置白名单的接口
@Override public void setDeviceIdleWhitelist(int[] appids) { setDeviceIdleWhitelistInternal(appids); }setDeviceIdleWhitelistInternal函数也是调用了updateWakeLockDisabledStatesLocked函数
void setDeviceIdleWhitelistInternal(int[] appids) { synchronized (mLock) { mDeviceIdleWhitelist = appids; if (mDeviceIdleMode) { updateWakeLockDisabledStatesLocked(); } } }
updateWakeLockDisabledStatesLocked和之前一样,最后我们再主要分析下setWakeLockDisabledStateLocked函数
private boolean setWakeLockDisabledStateLocked(WakeLock wakeLock) { if ((wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) == PowerManager.PARTIAL_WAKE_LOCK) { boolean disabled = false; if (mDeviceIdleMode) { 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;//所有条件都满足 } } if (wakeLock.mDisabled != disabled) { wakeLock.mDisabled = disabled; return true; } } return false; }上面所有条件都满足disabled为true。