Merge "Disable screen wake locks for cached apps" into udc-dev am: c339d55d32

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/24107346

Change-Id: I3c59ab11890986335cba901ee4c5fc3266990855
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Philip Junker
2023-07-25 13:04:17 +00:00
committed by Automerger Merge Worker
4 changed files with 308 additions and 6 deletions

View File

@@ -1762,6 +1762,15 @@ public final class DisplayManager {
* 123,1,critical,0.8,default;123,1,moderate,0.6,id_2;456,2,moderate,0.9,critical,0.7
*/
String KEY_BRIGHTNESS_THROTTLING_DATA = "brightness_throttling_data";
/**
* 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

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.display.feature;
import android.hardware.display.DisplayManager;
import android.provider.DeviceConfig;
import android.provider.DeviceConfigInterface;
import java.util.concurrent.Executor;
/**
* Helper class to access all DeviceConfig features for display_manager namespace
*
**/
public class DeviceConfigParameterProvider {
private static final String TAG = "DisplayFeatureProvider";
private final DeviceConfigInterface mDeviceConfig;
public DeviceConfigParameterProvider(DeviceConfigInterface deviceConfig) {
mDeviceConfig = deviceConfig;
}
public boolean isDisableScreenWakeLocksWhileCachedFeatureEnabled() {
return mDeviceConfig.getBoolean(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
DisplayManager.DeviceConfig.KEY_DISABLE_SCREEN_WAKE_LOCKS_WHILE_CACHED, true);
}
/** add property change listener to DeviceConfig */
public void addOnPropertiesChangedListener(Executor executor,
DeviceConfig.OnPropertiesChangedListener listener) {
mDeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
executor, listener);
}
}

View File

@@ -92,6 +92,7 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.os.WorkSource;
import android.os.WorkSource.WorkChain;
import android.provider.DeviceConfigInterface;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.service.dreams.DreamManagerInternal;
@@ -128,6 +129,7 @@ import com.android.server.UiThread;
import com.android.server.UserspaceRebootLogger;
import com.android.server.Watchdog;
import com.android.server.am.BatteryStatsService;
import com.android.server.display.feature.DeviceConfigParameterProvider;
import com.android.server.lights.LightsManager;
import com.android.server.lights.LogicalLight;
import com.android.server.policy.WindowManagerPolicy;
@@ -323,6 +325,9 @@ public final class PowerManagerService extends SystemService
private final Injector mInjector;
private final PermissionCheckerWrapper mPermissionCheckerWrapper;
private final PowerPropertiesWrapper mPowerPropertiesWrapper;
private final DeviceConfigParameterProvider mDeviceConfigProvider;
private boolean mDisableScreenWakeLocksWhileCached;
private LightsManager mLightsManager;
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 */
@@ -1161,6 +1170,7 @@ public final class PowerManagerService extends SystemService
mInjector.createInattentiveSleepWarningController();
mPermissionCheckerWrapper = mInjector.createPermissionCheckerWrapper();
mPowerPropertiesWrapper = mInjector.createPowerPropertiesWrapper();
mDeviceConfigProvider = mInjector.createDeviceConfigParameterProvider();
mPowerGroupWakefulnessChangeListener = new PowerGroupWakefulnessChangeListener();
@@ -1346,6 +1356,14 @@ public final class PowerManagerService extends SystemService
mLightsManager = getLocalService(LightsManager.class);
mAttentionLight = mLightsManager.getLight(LightsManager.LIGHT_ID_ATTENTION);
updateDeviceConfigLocked();
mDeviceConfigProvider.addOnPropertiesChangedListener(BackgroundThread.getExecutor(),
properties -> {
synchronized (mLock) {
updateDeviceConfigLocked();
updateWakeLockDisabledStatesLocked();
}
});
// Initialize display power management.
mDisplayManagerInternal.initPowerManagement(
@@ -1545,6 +1563,12 @@ public final class PowerManagerService extends SystemService
updatePowerStateLocked();
}
@GuardedBy("mLock")
private void updateDeviceConfigLocked() {
mDisableScreenWakeLocksWhileCached = mDeviceConfigProvider
.isDisableScreenWakeLocksWhileCachedFeatureEnabled();
}
@RequiresPermission(value = android.Manifest.permission.TURN_SCREEN_ON, conditional = true)
private void acquireWakeLockInternal(IBinder lock, int displayId, int flags, String tag,
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. */
@SuppressWarnings("deprecation")
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) {
case PowerManager.PARTIAL_WAKE_LOCK:
if (!wakeLock.mDisabled) {
// We only respect this if the wake lock is not disabled.
return WAKE_LOCK_CPU;
}
break;
return WAKE_LOCK_CPU;
case PowerManager.FULL_WAKE_LOCK:
return WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_BUTTON_BRIGHT;
case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
@@ -4151,7 +4175,7 @@ public final class PowerManagerService extends SystemService
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) {
== PowerManager.PARTIAL_WAKE_LOCK || isScreenLock(wakeLock)) {
if (setWakeLockDisabledStateLocked(wakeLock)) {
changed = true;
if (wakeLock.mDisabled) {
@@ -4205,6 +4229,22 @@ public final class PowerManagerService extends SystemService
}
}
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;
}

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_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.PowerManagerInternal.WAKEFULNESS_ASLEEP;
import static android.os.PowerManagerInternal.WAKEFULNESS_AWAKE;
@@ -78,6 +80,7 @@ import android.os.PowerManagerInternal;
import android.os.PowerSaveState;
import android.os.UserHandle;
import android.os.test.TestLooper;
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.service.dreams.DreamManagerInternal;
import android.sysprop.PowerProperties;
@@ -91,6 +94,7 @@ import com.android.internal.app.IBatteryStats;
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.display.feature.DeviceConfigParameterProvider;
import com.android.server.lights.LightsManager;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.power.PowerManagerService.BatteryReceiver;
@@ -159,6 +163,7 @@ public class PowerManagerServiceTest {
@Mock private InattentiveSleepWarningController mInattentiveSleepWarningControllerMock;
@Mock private PowerManagerService.PermissionCheckerWrapper mPermissionCheckerWrapperMock;
@Mock private PowerManagerService.PowerPropertiesWrapper mPowerPropertiesWrapper;
@Mock private DeviceConfigParameterProvider mDeviceParameterProvider;
@Rule public TestRule compatChangeRule = new PlatformCompatChangeRule();
@@ -340,6 +345,11 @@ public class PowerManagerServiceTest {
PowerManagerService.PowerPropertiesWrapper createPowerPropertiesWrapper() {
return mPowerPropertiesWrapper;
}
@Override
DeviceConfigParameterProvider createDeviceConfigParameterProvider() {
return mDeviceParameterProvider;
}
});
return mService;
}
@@ -2680,4 +2690,197 @@ public class PowerManagerServiceTest {
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);
}
}