待机休眠优化,会减少应用阻止系统睡眠的时间,从而降低待机功耗。针对的是应用 wakelock持锁的一项的优化,会限制应用最长持锁时间。
在Android Sprd省电管理(五)app 待机网络管理讲到当进入idle模式以后,会调用PowerController.java的notifyChanged()方法
private void notifyChanged() {
if (DEBUG) Slog.d(TAG, "- notifyChanged() E -");
for (int i = 0; i < mHelpers.size(); i++) {
PowerSaveHelper helper = mHelpers.get(i);
helper.applyConstrain();
}
}
WakelockConstraintHelper继承PowerSaveHelper
WakelockConstraintHelper.java-->applyConstrain()
@Override
void applyConstrain() {
for (int index=mNewWakeLockAppListForUsers.size()-1; index>=0; index--) {
ArrayMap<String, Integer> mNewWakeLockAppList = mNewWakeLockAppListForUsers.valueAt(index);
for (int i=0;i<mNewWakeLockAppList.size();i++) {
try {
if (DEBUG) Slog.d(TAG, "packageName:" + mNewWakeLockAppList.keyAt(i)
+ " uid:" + mNewWakeLockAppList.valueAt(i) + " constrained Wake Lock");
// Notify PowerManager to disable the wake lock of this app
notifyAppWakeLockConstrainedStateChanged(mNewWakeLockAppList.valueAt(i), true);
updateAppWakeLockConstrainedState(mNewWakeLockAppList.keyAt(i), true, mNewWakeLockAppList.valueAt(i));
} catch (Exception e) {
// fall through
}
}
mNewWakeLockAppList.clear();
}
}
WakelockConstraintHelper.java-->notifyAppWakeLockConstrainedStateChanged()
// wrap API for PowerManagerInternal
private void notifyAppWakeLockConstrainedStateChanged(int uid, boolean constrained) {
if (DEBUG) Slog.d(TAG, "notifyAppWakeLockConstrainedStateChanged() E uid:" + uid + " constrained:" + constrained);
if (mLocalPowerManager != null) {
mLocalPowerManager.updateUidProcWakeLockDisabledState(uid, constrained);
}
}
PowerManagerInternal是一个抽象类,PowerManagerService的内部类LocalService继承了PowerManagerInternal
PowerManagerService.java-->LocalService-->updateUidProcWakeLockDisabledState()
@Override
public void updateUidProcWakeLockDisabledState(int uid, boolean disabled) {
mPowerControllerHelper.updateUidProcWakeLockDisabledState(uid, disabled);
}
PowerManagerService.java-->updateUidProcWakeLockDisabledState()
public void updateUidProcWakeLockDisabledState(int uid, boolean disabled) {
synchronized (mLock) {
int index = mWakeLockDisabledApplist.indexOf(uid);
if (disabled) {
if (index < 0)
mWakeLockDisabledApplist.add(uid);
} else {
if (index >= 0)
mWakeLockDisabledApplist.remove(index);
}
updateWakeLockDisabledStatesLocked();
}
}
PowerManagerService.java-->updateWakeLockDisabledStatesLocked()
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)) {
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();
}
}
PowerManagerService.java-->setWakeLockDisabledStateLocked()
private boolean setWakeLockDisabledStateLocked(WakeLock wakeLock) {
if ((wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK)
== PowerManager.PARTIAL_WAKE_LOCK) {
boolean disabled = false;
final int appid = UserHandle.getAppId(wakeLock.mOwnerUid);
if (appid >= Process.FIRST_APPLICATION_UID) {
// Cached inactive processes are never allowed to hold wake locks.
if (mConstants.NO_CACHED_WAKE_LOCKS) {
disabled = !wakeLock.mUidState.mActive &&
wakeLock.mUidState.mProcState
!= ActivityManager.PROCESS_STATE_NONEXISTENT &&
wakeLock.mUidState.mProcState > ActivityManager.PROCESS_STATE_RECEIVER;
}
if (mDeviceIdleMode) {
// If we are in idle mode, we will also ignore all partial wake locks that are
// for application uids that are not whitelisted.
final UidState state = wakeLock.mUidState;
if (Arrays.binarySearch(mDeviceIdleWhitelist, appid) < 0 &&
Arrays.binarySearch(mDeviceIdleTempWhitelist, appid) < 0 &&
state.mProcState != ActivityManager.PROCESS_STATE_NONEXISTENT &&
state.mProcState > ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
disabled = true;
}
}
}
// NOTE: Bug #627645 low power Feature BEG-->
// if wake lock is not disable by DeviceIdle
// check if is disabled by mWakeLockDisablelist
if (!disabled) {
disabled = mPowerControllerHelper.shouldWakeLockDisabledLocked(wakeLock);
}
// <-- NOTE: Bug #627645 low power Feature END
if (wakeLock.mDisabled != disabled) {
wakeLock.mDisabled = disabled;
return true;
}
}
return false;
}
将wakeLock mDisabled 设置为true,然后再调用notifyWakeLockReleasedLocked通知电量统计服务做相关统计
PowerManagerService.java-->notifyWakeLockReleasedLocked()
private void notifyWakeLockReleasedLocked(WakeLock wakeLock) {
if (mSystemReady && wakeLock.mNotifiedAcquired) {
wakeLock.mNotifiedAcquired = false;
wakeLock.mAcquireTime = 0;
mNotifier.onWakeLockReleased(wakeLock.mFlags, wakeLock.mTag,
wakeLock.mPackageName, wakeLock.mOwnerUid, wakeLock.mOwnerPid,
wakeLock.mWorkSource, wakeLock.mHistoryTag);
notifyWakeLockLongFinishedLocked(wakeLock);
// NOTE: Bug #627645 low power Feature BEG-->
// notify listeners
mPowerControllerHelper.notifyWakeLockReleasedLocked(wakeLock);
// <-- NOTE: Bug #627645 low power Feature END
}
}
PowerManagerService.java-->notifyWakeLockReleasedLocked()
public void notifyWakeLockReleasedLocked(WakeLock wakeLock) {
// if Audio release a wakelock notify listeners
if ((wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) == PowerManager.PARTIAL_WAKE_LOCK
&& Process.AUDIOSERVER_UID == wakeLock.mOwnerUid) {
if (mPowerControllerInternalCallback != null) {
mPowerControllerInternalCallback.onWakeLockReleased(wakeLock.mTag, wakeLock.mPackageName,
wakeLock.mOwnerUid, wakeLock.mOwnerPid, wakeLock.mWorkSource);
}
}
}
onWakeLockReleased()是PowerManagerInternal.java的一个内部接口PowerControllerInternalCallback里的方法
WakelockConstraintHelper的内部类WakeLockObserver implements PowerManagerInternal.PowerControllerInternalCallback
@Override
public void onWakeLockReleased(String tag, String packageName,
int ownerUid, int ownerPid, WorkSource workSource) {
noteAudioWakeLockReleased(tag, packageName, ownerUid, ownerPid, workSource);
}
WakelockConstraintHelper.java-->noteAudioWakeLockReleased()
private void noteAudioWakeLockReleased(String tag, String packageName,
int ownerUid, int ownerPid, WorkSource workSource) {
// only care about the workSource
if (!AUDIO_PACKAGE_NAME.equals(packageName) || Process.AUDIOSERVER_UID != ownerUid) return;
if (DEBUG) Slog.d(TAG, "noteAudioWakeLockReleased: tag: " + tag);
if (isAudioIn(tag)) {
mHandler.sendMessage(mHandler.obtainMessage(MSG_AUDIOIN_WAKELOCK_RELEASED));
} else if (isAudioOut(tag)) {
WakeLockInfo wakeLockInfo = new WakeLockInfo(tag, packageName, ownerUid, workSource);
mHandler.sendMessage(mHandler.obtainMessage(MSG_AUDIOOUT_WAKELOCK_RELEASED, wakeLockInfo));
}
}