Disable screen wake locks for cached apps

Bug: 289464589
Test: atest PowerManagerServiceTest
Change-Id: I1cf38ada2456c1cc1f367fad58ce95948d1b3a81
Merged-In: I1cf38ada2456c1cc1f367fad58ce95948d1b3a81
This commit is contained in:
Philip Junker
2023-07-12 16:36:43 +02:00
parent 7283fc8be6
commit d47577971d
4 changed files with 263 additions and 6 deletions

View File

@@ -1780,6 +1780,15 @@ public final class DisplayManager {
* @hide * @hide
*/ */
String KEY_USE_NORMAL_BRIGHTNESS_MODE_CONTROLLER = "use_normal_brightness_mode_controller"; String KEY_USE_NORMAL_BRIGHTNESS_MODE_CONTROLLER = "use_normal_brightness_mode_controller";
/**
* Key for disabling screen wake locks while apps are in cached state.
* Read value via {@link android.provider.DeviceConfig#getBoolean(String, String, boolean)}
* with {@link android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER} as the namespace.
* @hide
*/
String KEY_DISABLE_SCREEN_WAKE_LOCKS_WHILE_CACHED =
"disable_screen_wake_locks_while_cached";
} }
/** /**

View File

@@ -60,6 +60,11 @@ public class DeviceConfigParameterProvider {
DisplayManager.DeviceConfig.KEY_USE_NORMAL_BRIGHTNESS_MODE_CONTROLLER, false); DisplayManager.DeviceConfig.KEY_USE_NORMAL_BRIGHTNESS_MODE_CONTROLLER, false);
} }
public boolean isDisableScreenWakeLocksWhileCachedFeatureEnabled() {
return mDeviceConfig.getBoolean(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
DisplayManager.DeviceConfig.KEY_DISABLE_SCREEN_WAKE_LOCKS_WHILE_CACHED, true);
}
// feature: smooth_display_feature // feature: smooth_display_feature
// parameter: peak_refresh_rate_default // parameter: peak_refresh_rate_default
public float getPeakRefreshRateDefault() { public float getPeakRefreshRateDefault() {

View File

@@ -92,6 +92,7 @@ import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
import android.os.WorkSource; import android.os.WorkSource;
import android.os.WorkSource.WorkChain; import android.os.WorkSource.WorkChain;
import android.provider.DeviceConfigInterface;
import android.provider.Settings; import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException; import android.provider.Settings.SettingNotFoundException;
import android.service.dreams.DreamManagerInternal; import android.service.dreams.DreamManagerInternal;
@@ -128,6 +129,7 @@ import com.android.server.UiThread;
import com.android.server.UserspaceRebootLogger; import com.android.server.UserspaceRebootLogger;
import com.android.server.Watchdog; import com.android.server.Watchdog;
import com.android.server.am.BatteryStatsService; import com.android.server.am.BatteryStatsService;
import com.android.server.display.feature.DeviceConfigParameterProvider;
import com.android.server.lights.LightsManager; import com.android.server.lights.LightsManager;
import com.android.server.lights.LogicalLight; import com.android.server.lights.LogicalLight;
import com.android.server.policy.WindowManagerPolicy; import com.android.server.policy.WindowManagerPolicy;
@@ -323,6 +325,9 @@ public final class PowerManagerService extends SystemService
private final Injector mInjector; private final Injector mInjector;
private final PermissionCheckerWrapper mPermissionCheckerWrapper; private final PermissionCheckerWrapper mPermissionCheckerWrapper;
private final PowerPropertiesWrapper mPowerPropertiesWrapper; private final PowerPropertiesWrapper mPowerPropertiesWrapper;
private final DeviceConfigParameterProvider mDeviceConfigProvider;
private boolean mDisableScreenWakeLocksWhileCached;
private LightsManager mLightsManager; private LightsManager mLightsManager;
private BatteryManagerInternal mBatteryManagerInternal; private BatteryManagerInternal mBatteryManagerInternal;
@@ -1065,6 +1070,10 @@ public final class PowerManagerService extends SystemService
} }
}; };
} }
DeviceConfigParameterProvider createDeviceConfigParameterProvider() {
return new DeviceConfigParameterProvider(DeviceConfigInterface.REAL);
}
} }
/** Interface for checking an app op permission */ /** Interface for checking an app op permission */
@@ -1161,6 +1170,7 @@ public final class PowerManagerService extends SystemService
mInjector.createInattentiveSleepWarningController(); mInjector.createInattentiveSleepWarningController();
mPermissionCheckerWrapper = mInjector.createPermissionCheckerWrapper(); mPermissionCheckerWrapper = mInjector.createPermissionCheckerWrapper();
mPowerPropertiesWrapper = mInjector.createPowerPropertiesWrapper(); mPowerPropertiesWrapper = mInjector.createPowerPropertiesWrapper();
mDeviceConfigProvider = mInjector.createDeviceConfigParameterProvider();
mPowerGroupWakefulnessChangeListener = new PowerGroupWakefulnessChangeListener(); mPowerGroupWakefulnessChangeListener = new PowerGroupWakefulnessChangeListener();
@@ -1346,6 +1356,14 @@ public final class PowerManagerService extends SystemService
mLightsManager = getLocalService(LightsManager.class); mLightsManager = getLocalService(LightsManager.class);
mAttentionLight = mLightsManager.getLight(LightsManager.LIGHT_ID_ATTENTION); mAttentionLight = mLightsManager.getLight(LightsManager.LIGHT_ID_ATTENTION);
updateDeviceConfigLocked();
mDeviceConfigProvider.addOnPropertiesChangedListener(BackgroundThread.getExecutor(),
properties -> {
synchronized (mLock) {
updateDeviceConfigLocked();
updateWakeLockDisabledStatesLocked();
}
});
// Initialize display power management. // Initialize display power management.
mDisplayManagerInternal.initPowerManagement( mDisplayManagerInternal.initPowerManagement(
@@ -1545,6 +1563,12 @@ public final class PowerManagerService extends SystemService
updatePowerStateLocked(); updatePowerStateLocked();
} }
@GuardedBy("mLock")
private void updateDeviceConfigLocked() {
mDisableScreenWakeLocksWhileCached = mDeviceConfigProvider
.isDisableScreenWakeLocksWhileCachedFeatureEnabled();
}
@RequiresPermission(value = android.Manifest.permission.TURN_SCREEN_ON, conditional = true) @RequiresPermission(value = android.Manifest.permission.TURN_SCREEN_ON, conditional = true)
private void acquireWakeLockInternal(IBinder lock, int displayId, int flags, String tag, private void acquireWakeLockInternal(IBinder lock, int displayId, int flags, String tag,
String packageName, WorkSource ws, String historyTag, int uid, int pid, String packageName, WorkSource ws, String historyTag, int uid, int pid,
@@ -2760,13 +2784,13 @@ public final class PowerManagerService extends SystemService
/** Get wake lock summary flags that correspond to the given wake lock. */ /** Get wake lock summary flags that correspond to the given wake lock. */
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
private int getWakeLockSummaryFlags(WakeLock wakeLock) { private int getWakeLockSummaryFlags(WakeLock wakeLock) {
if (wakeLock.mDisabled) {
// We only respect this if the wake lock is not disabled.
return 0;
}
switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) { switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
case PowerManager.PARTIAL_WAKE_LOCK: case PowerManager.PARTIAL_WAKE_LOCK:
if (!wakeLock.mDisabled) {
// We only respect this if the wake lock is not disabled.
return WAKE_LOCK_CPU; return WAKE_LOCK_CPU;
}
break;
case PowerManager.FULL_WAKE_LOCK: case PowerManager.FULL_WAKE_LOCK:
return WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_BUTTON_BRIGHT; return WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_BUTTON_BRIGHT;
case PowerManager.SCREEN_BRIGHT_WAKE_LOCK: case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
@@ -4151,7 +4175,7 @@ public final class PowerManagerService extends SystemService
for (int i = 0; i < numWakeLocks; i++) { for (int i = 0; i < numWakeLocks; i++) {
final WakeLock wakeLock = mWakeLocks.get(i); final WakeLock wakeLock = mWakeLocks.get(i);
if ((wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) if ((wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK)
== PowerManager.PARTIAL_WAKE_LOCK) { == PowerManager.PARTIAL_WAKE_LOCK || isScreenLock(wakeLock)) {
if (setWakeLockDisabledStateLocked(wakeLock)) { if (setWakeLockDisabledStateLocked(wakeLock)) {
changed = true; changed = true;
if (wakeLock.mDisabled) { if (wakeLock.mDisabled) {
@@ -4205,6 +4229,22 @@ public final class PowerManagerService extends SystemService
} }
} }
return wakeLock.setDisabled(disabled); return wakeLock.setDisabled(disabled);
} else if (mDisableScreenWakeLocksWhileCached && isScreenLock(wakeLock)) {
boolean disabled = false;
final int appid = UserHandle.getAppId(wakeLock.mOwnerUid);
final UidState state = wakeLock.mUidState;
// Cached inactive processes are never allowed to hold wake locks.
if (mConstants.NO_CACHED_WAKE_LOCKS
&& appid >= Process.FIRST_APPLICATION_UID
&& !state.mActive
&& state.mProcState != ActivityManager.PROCESS_STATE_NONEXISTENT
&& state.mProcState >= ActivityManager.PROCESS_STATE_TOP_SLEEPING) {
if (DEBUG_SPEW) {
Slog.d(TAG, "disabling full wakelock " + wakeLock);
}
disabled = true;
}
return wakeLock.setDisabled(disabled);
} }
return false; return false;
} }

View File

@@ -18,6 +18,8 @@ package com.android.server.power;
import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP; import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE; import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_RECEIVER;
import static android.app.ActivityManager.PROCESS_STATE_TOP_SLEEPING;
import static android.os.PowerManager.USER_ACTIVITY_EVENT_BUTTON; import static android.os.PowerManager.USER_ACTIVITY_EVENT_BUTTON;
import static android.os.PowerManagerInternal.WAKEFULNESS_ASLEEP; import static android.os.PowerManagerInternal.WAKEFULNESS_ASLEEP;
import static android.os.PowerManagerInternal.WAKEFULNESS_AWAKE; import static android.os.PowerManagerInternal.WAKEFULNESS_AWAKE;
@@ -78,6 +80,7 @@ import android.os.PowerManagerInternal;
import android.os.PowerSaveState; import android.os.PowerSaveState;
import android.os.UserHandle; import android.os.UserHandle;
import android.os.test.TestLooper; import android.os.test.TestLooper;
import android.provider.DeviceConfig;
import android.provider.Settings; import android.provider.Settings;
import android.service.dreams.DreamManagerInternal; import android.service.dreams.DreamManagerInternal;
import android.sysprop.PowerProperties; import android.sysprop.PowerProperties;
@@ -91,6 +94,7 @@ import com.android.internal.app.IBatteryStats;
import com.android.internal.util.test.FakeSettingsProvider; import com.android.internal.util.test.FakeSettingsProvider;
import com.android.server.LocalServices; import com.android.server.LocalServices;
import com.android.server.SystemService; import com.android.server.SystemService;
import com.android.server.display.feature.DeviceConfigParameterProvider;
import com.android.server.lights.LightsManager; import com.android.server.lights.LightsManager;
import com.android.server.policy.WindowManagerPolicy; import com.android.server.policy.WindowManagerPolicy;
import com.android.server.power.PowerManagerService.BatteryReceiver; import com.android.server.power.PowerManagerService.BatteryReceiver;
@@ -159,6 +163,7 @@ public class PowerManagerServiceTest {
@Mock private InattentiveSleepWarningController mInattentiveSleepWarningControllerMock; @Mock private InattentiveSleepWarningController mInattentiveSleepWarningControllerMock;
@Mock private PowerManagerService.PermissionCheckerWrapper mPermissionCheckerWrapperMock; @Mock private PowerManagerService.PermissionCheckerWrapper mPermissionCheckerWrapperMock;
@Mock private PowerManagerService.PowerPropertiesWrapper mPowerPropertiesWrapper; @Mock private PowerManagerService.PowerPropertiesWrapper mPowerPropertiesWrapper;
@Mock private DeviceConfigParameterProvider mDeviceParameterProvider;
@Rule public TestRule compatChangeRule = new PlatformCompatChangeRule(); @Rule public TestRule compatChangeRule = new PlatformCompatChangeRule();
@@ -340,6 +345,11 @@ public class PowerManagerServiceTest {
PowerManagerService.PowerPropertiesWrapper createPowerPropertiesWrapper() { PowerManagerService.PowerPropertiesWrapper createPowerPropertiesWrapper() {
return mPowerPropertiesWrapper; return mPowerPropertiesWrapper;
} }
@Override
DeviceConfigParameterProvider createDeviceConfigParameterProvider() {
return mDeviceParameterProvider;
}
}); });
return mService; return mService;
} }
@@ -2680,4 +2690,197 @@ public class PowerManagerServiceTest {
verify(mNotifierMock, never()).onUserActivity(anyInt(), anyInt(), anyInt()); verify(mNotifierMock, never()).onUserActivity(anyInt(), anyInt(), anyInt());
} }
@Test
public void testFeatureEnabledProcStateUncachedToCached_fullWakeLockDisabled() {
doReturn(true).when(mDeviceParameterProvider)
.isDisableScreenWakeLocksWhileCachedFeatureEnabled();
createService();
startSystem();
WakeLock wakeLock = acquireWakeLock("fullWakeLock", PowerManager.FULL_WAKE_LOCK);
setUncachedUidProcState(wakeLock.mOwnerUid);
setCachedUidProcState(wakeLock.mOwnerUid);
assertThat(wakeLock.mDisabled).isTrue();
}
@Test
public void testFeatureDisabledProcStateUncachedToCached_fullWakeLockEnabled() {
doReturn(false).when(mDeviceParameterProvider)
.isDisableScreenWakeLocksWhileCachedFeatureEnabled();
createService();
startSystem();
WakeLock wakeLock = acquireWakeLock("fullWakeLock", PowerManager.FULL_WAKE_LOCK);
setUncachedUidProcState(wakeLock.mOwnerUid);
setCachedUidProcState(wakeLock.mOwnerUid);
assertThat(wakeLock.mDisabled).isFalse();
}
@Test
public void testFeatureEnabledProcStateUncachedToCached_screenBrightWakeLockDisabled() {
doReturn(true).when(mDeviceParameterProvider)
.isDisableScreenWakeLocksWhileCachedFeatureEnabled();
createService();
startSystem();
WakeLock wakeLock = acquireWakeLock("screenBrightWakeLock",
PowerManager.SCREEN_BRIGHT_WAKE_LOCK);
setUncachedUidProcState(wakeLock.mOwnerUid);
setCachedUidProcState(wakeLock.mOwnerUid);
assertThat(wakeLock.mDisabled).isTrue();
}
@Test
public void testFeatureDisabledProcStateUncachedToCached_screenBrightWakeLockEnabled() {
doReturn(false).when(mDeviceParameterProvider)
.isDisableScreenWakeLocksWhileCachedFeatureEnabled();
createService();
startSystem();
WakeLock wakeLock = acquireWakeLock("screenBrightWakeLock",
PowerManager.SCREEN_BRIGHT_WAKE_LOCK);
setUncachedUidProcState(wakeLock.mOwnerUid);
setCachedUidProcState(wakeLock.mOwnerUid);
assertThat(wakeLock.mDisabled).isFalse();
}
@Test
public void testFeatureEnabledProcStateUncachedToCached_screenDimWakeLockDisabled() {
doReturn(true).when(mDeviceParameterProvider)
.isDisableScreenWakeLocksWhileCachedFeatureEnabled();
createService();
startSystem();
WakeLock wakeLock = acquireWakeLock("screenDimWakeLock",
PowerManager.SCREEN_DIM_WAKE_LOCK);
setUncachedUidProcState(wakeLock.mOwnerUid);
setCachedUidProcState(wakeLock.mOwnerUid);
assertThat(wakeLock.mDisabled).isTrue();
}
@Test
public void testFeatureDisabledProcStateUncachedToCached_screenDimWakeLockEnabled() {
doReturn(false).when(mDeviceParameterProvider)
.isDisableScreenWakeLocksWhileCachedFeatureEnabled();
createService();
startSystem();
WakeLock wakeLock = acquireWakeLock("screenDimWakeLock",
PowerManager.SCREEN_DIM_WAKE_LOCK);
setUncachedUidProcState(wakeLock.mOwnerUid);
setCachedUidProcState(wakeLock.mOwnerUid);
assertThat(wakeLock.mDisabled).isFalse();
}
@Test
public void testFeatureEnabledProcStateCachedToUncached_fullWakeLockEnabled() {
doReturn(true).when(mDeviceParameterProvider)
.isDisableScreenWakeLocksWhileCachedFeatureEnabled();
createService();
startSystem();
WakeLock wakeLock = acquireWakeLock("fullWakeLock", PowerManager.FULL_WAKE_LOCK);
setCachedUidProcState(wakeLock.mOwnerUid);
setUncachedUidProcState(wakeLock.mOwnerUid);
assertThat(wakeLock.mDisabled).isFalse();
}
@Test
public void testFeatureDisabledProcStateCachedToUncached_fullWakeLockEnabled() {
doReturn(false).when(mDeviceParameterProvider)
.isDisableScreenWakeLocksWhileCachedFeatureEnabled();
createService();
startSystem();
WakeLock wakeLock = acquireWakeLock("fullWakeLock", PowerManager.FULL_WAKE_LOCK);
setCachedUidProcState(wakeLock.mOwnerUid);
setUncachedUidProcState(wakeLock.mOwnerUid);
assertThat(wakeLock.mDisabled).isFalse();
}
@Test
public void testFeatureEnabledProcStateCachedToUncached_screenBrightWakeLockEnabled() {
doReturn(true).when(mDeviceParameterProvider)
.isDisableScreenWakeLocksWhileCachedFeatureEnabled();
createService();
startSystem();
WakeLock wakeLock = acquireWakeLock("screenBrightWakeLock",
PowerManager.SCREEN_BRIGHT_WAKE_LOCK);
setCachedUidProcState(wakeLock.mOwnerUid);
setUncachedUidProcState(wakeLock.mOwnerUid);
assertThat(wakeLock.mDisabled).isFalse();
}
@Test
public void testFeatureDisabledProcStateCachedToUncached_screenBrightWakeLockEnabled() {
doReturn(false).when(mDeviceParameterProvider)
.isDisableScreenWakeLocksWhileCachedFeatureEnabled();
createService();
startSystem();
WakeLock wakeLock = acquireWakeLock("screenBrightWakeLock",
PowerManager.SCREEN_BRIGHT_WAKE_LOCK);
setCachedUidProcState(wakeLock.mOwnerUid);
setUncachedUidProcState(wakeLock.mOwnerUid);
assertThat(wakeLock.mDisabled).isFalse();
}
@Test
public void testFeatureEnabledProcStateCachedToUncached_screenDimWakeLockEnabled() {
doReturn(true).when(mDeviceParameterProvider)
.isDisableScreenWakeLocksWhileCachedFeatureEnabled();
createService();
startSystem();
WakeLock wakeLock = acquireWakeLock("screenDimWakeLock",
PowerManager.SCREEN_DIM_WAKE_LOCK);
setCachedUidProcState(wakeLock.mOwnerUid);
setUncachedUidProcState(wakeLock.mOwnerUid);
assertThat(wakeLock.mDisabled).isFalse();
}
@Test
public void testFeatureDisabledProcStateCachedToUncached_screenDimWakeLockEnabled() {
doReturn(false).when(mDeviceParameterProvider)
.isDisableScreenWakeLocksWhileCachedFeatureEnabled();
createService();
startSystem();
WakeLock wakeLock = acquireWakeLock("screenDimWakeLock",
PowerManager.SCREEN_DIM_WAKE_LOCK);
setCachedUidProcState(wakeLock.mOwnerUid);
setUncachedUidProcState(wakeLock.mOwnerUid);
assertThat(wakeLock.mDisabled).isFalse();
}
@Test
public void testFeatureDynamicallyDisabledProcStateUncachedToCached_fullWakeLockEnabled() {
doReturn(true).when(mDeviceParameterProvider)
.isDisableScreenWakeLocksWhileCachedFeatureEnabled();
ArgumentCaptor<DeviceConfig.OnPropertiesChangedListener> listenerCaptor =
ArgumentCaptor.forClass(DeviceConfig.OnPropertiesChangedListener.class);
createService();
startSystem();
verify(mDeviceParameterProvider, times(1))
.addOnPropertiesChangedListener(any(), listenerCaptor.capture());
WakeLock wakeLock = acquireWakeLock("fullWakeLock", PowerManager.FULL_WAKE_LOCK);
setUncachedUidProcState(wakeLock.mOwnerUid);
// dynamically disable the feature
doReturn(false).when(mDeviceParameterProvider)
.isDisableScreenWakeLocksWhileCachedFeatureEnabled();
listenerCaptor.getValue().onPropertiesChanged(
new DeviceConfig.Properties("ignored_namespace", null));
setUncachedUidProcState(wakeLock.mOwnerUid);
assertThat(wakeLock.mDisabled).isFalse();
}
private void setCachedUidProcState(int uid) {
mService.updateUidProcStateInternal(uid, PROCESS_STATE_TOP_SLEEPING);
}
private void setUncachedUidProcState(int uid) {
mService.updateUidProcStateInternal(uid, PROCESS_STATE_RECEIVER);
}
} }