diff options
| author | 2023-07-25 13:04:17 +0000 | |
|---|---|---|
| committer | 2023-07-25 13:04:17 +0000 | |
| commit | 5fa79c2e30926f9ce552d5b541f4d624b04026d9 (patch) | |
| tree | 78ba2dfd9fcf68ea5cec5513f4e581b1c10b02ab | |
| parent | cae927961875a5c4de7a1318dc234c367b6ffca9 (diff) | |
| parent | c339d55d329e6c5b0dedd7c21e93e26d9cce43fc (diff) | |
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>
4 files changed, 308 insertions, 6 deletions
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java index 76efce56dcf0..21e4ab195f28 100644 --- a/core/java/android/hardware/display/DisplayManager.java +++ b/core/java/android/hardware/display/DisplayManager.java @@ -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"; } /** diff --git a/services/core/java/com/android/server/display/feature/DeviceConfigParameterProvider.java b/services/core/java/com/android/server/display/feature/DeviceConfigParameterProvider.java new file mode 100644 index 000000000000..03103834f325 --- /dev/null +++ b/services/core/java/com/android/server/display/feature/DeviceConfigParameterProvider.java @@ -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); + } +} diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index a53b831d55c1..d82f7a56a830 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -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; } diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java index 5c6164efb3b6..431d3a61de51 100644 --- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java @@ -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); + } } |