diff options
5 files changed, 137 insertions, 1 deletions
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index a46868e93ab8..68e1acb374d2 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -523,6 +523,13 @@ public final class PowerManager { public static final int GO_TO_SLEEP_FLAG_NO_DOZE = 1 << 0; /** + * Go to sleep flag: Sleep softly, go to sleep only if there's no wakelock explicitly keeping + * the device awake. + * @hide + */ + public static final int GO_TO_SLEEP_FLAG_SOFT_SLEEP = 1 << 1; + + /** * @hide */ @IntDef(prefix = { "BRIGHTNESS_CONSTRAINT_TYPE" }, value = { diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java index 778e41820433..098f7f62ee8c 100644 --- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java +++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java @@ -426,7 +426,8 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { // Send the device to sleep when required. mHandler.post(() -> { mPowerManager.goToSleep(SystemClock.uptimeMillis(), - PowerManager.GO_TO_SLEEP_REASON_DEVICE_FOLD, 0); + PowerManager.GO_TO_SLEEP_REASON_DEVICE_FOLD, + PowerManager.GO_TO_SLEEP_FLAG_SOFT_SLEEP); }); } } diff --git a/services/core/java/com/android/server/power/PowerGroup.java b/services/core/java/com/android/server/power/PowerGroup.java index 431cf3861804..fe24faf1bc75 100644 --- a/services/core/java/com/android/server/power/PowerGroup.java +++ b/services/core/java/com/android/server/power/PowerGroup.java @@ -28,6 +28,8 @@ import static com.android.server.power.PowerManagerService.USER_ACTIVITY_SCREEN_ import static com.android.server.power.PowerManagerService.WAKE_LOCK_DOZE; import static com.android.server.power.PowerManagerService.WAKE_LOCK_DRAW; import static com.android.server.power.PowerManagerService.WAKE_LOCK_SCREEN_BRIGHT; +import static com.android.server.power.PowerManagerService.WAKE_LOCK_SCREEN_DIM; +import static com.android.server.power.PowerManagerService.WAKE_LOCK_STAY_AWAKE; import android.hardware.display.DisplayManagerInternal; import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest; @@ -341,6 +343,22 @@ public class PowerGroup { return mWakeLockSummary; } + /** + * Query whether a wake lock is at least partially responsible for keeping the device awake. + * + * This does not necessarily mean the wake lock is the sole reason the device is awake; there + * could also be user activity keeping the device awake, for example. It just means a wake lock + * is being held that would keep the device awake even if nothing else was. + * + * @return whether the PowerGroup is being kept awake at least in part because a wake lock is + * being held. + */ + public boolean hasWakeLockKeepingScreenOnLocked() { + final int screenOnWakeLockMask = + WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM | WAKE_LOCK_STAY_AWAKE; + return (mWakeLockSummary & (screenOnWakeLockMask)) != 0; + } + public void setWakeLockSummaryLocked(int summary) { mWakeLockSummary = summary; } diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index b1c986e6558a..e5c856aba6f1 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -5778,6 +5778,11 @@ public final class PowerManagerService extends SystemService try { synchronized (mLock) { PowerGroup defaultPowerGroup = mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP); + if ((flags & PowerManager.GO_TO_SLEEP_FLAG_SOFT_SLEEP) != 0) { + if (defaultPowerGroup.hasWakeLockKeepingScreenOnLocked()) { + return; + } + } if ((flags & PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE) != 0) { sleepPowerGroupLocked(defaultPowerGroup, eventTime, reason, uid); } else { 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 6325008dc1e0..cbe8e668d7bd 100644 --- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java @@ -492,6 +492,111 @@ public class PowerManagerServiceTest { } @Test + public void testWakefulnessSleep_SoftSleepFlag_NoWakelocks() { + createService(); + // Start with AWAKE state + startSystem(); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + + // Take a nap and verify we go to sleep. + mService.getBinderServiceInstance().goToSleep(mClock.now(), + PowerManager.GO_TO_SLEEP_REASON_APPLICATION, + PowerManager.GO_TO_SLEEP_FLAG_SOFT_SLEEP); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING); + } + + @Test + public void testWakefulnessSleep_SoftSleepFlag_WithPartialWakelock() { + createService(); + // Start with AWAKE state + startSystem(); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + + // Grab a wakelock + final String tag = "wakelock1"; + final String packageName = "pkg.name"; + final IBinder token = new Binder(); + final int flags = PowerManager.PARTIAL_WAKE_LOCK; + mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName, + null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY, + null /* callback */); + + // Take a nap and verify we stay awake. + mService.getBinderServiceInstance().goToSleep(mClock.now(), + PowerManager.GO_TO_SLEEP_REASON_APPLICATION, + PowerManager.GO_TO_SLEEP_FLAG_SOFT_SLEEP); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING); + } + + @Test + public void testWakefulnessSleep_SoftSleepFlag_WithFullWakelock() { + createService(); + // Start with AWAKE state + startSystem(); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + + // Grab a wakelock + final String tag = "wakelock1"; + final String packageName = "pkg.name"; + final IBinder token = new Binder(); + final int flags = PowerManager.FULL_WAKE_LOCK; + mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName, + null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY, + null /* callback */); + + // Take a nap and verify we stay awake. + mService.getBinderServiceInstance().goToSleep(mClock.now(), + PowerManager.GO_TO_SLEEP_REASON_APPLICATION, + PowerManager.GO_TO_SLEEP_FLAG_SOFT_SLEEP); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + } + + @Test + public void testWakefulnessSleep_SoftSleepFlag_WithScreenBrightWakelock() { + createService(); + // Start with AWAKE state + startSystem(); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + + // Grab a wakelock + final String tag = "wakelock1"; + final String packageName = "pkg.name"; + final IBinder token = new Binder(); + final int flags = PowerManager.SCREEN_BRIGHT_WAKE_LOCK; + mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName, + null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY, + null /* callback */); + + // Take a nap and verify we stay awake. + mService.getBinderServiceInstance().goToSleep(mClock.now(), + PowerManager.GO_TO_SLEEP_REASON_APPLICATION, + PowerManager.GO_TO_SLEEP_FLAG_SOFT_SLEEP); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + } + @Test + public void testWakefulnessSleep_SoftSleepFlag_WithScreenDimWakelock() { + createService(); + // Start with AWAKE state + startSystem(); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + + // Grab a wakelock + final String tag = "wakelock1"; + final String packageName = "pkg.name"; + final IBinder token = new Binder(); + final int flags = PowerManager.SCREEN_DIM_WAKE_LOCK; + mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName, + null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY, + null /* callback */); + + // Take a nap and verify we stay awake. + mService.getBinderServiceInstance().goToSleep(mClock.now(), + PowerManager.GO_TO_SLEEP_REASON_APPLICATION, + PowerManager.GO_TO_SLEEP_FLAG_SOFT_SLEEP); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + } + + @Test public void testWakefulnessAwake_AcquireCausesWakeup_turnScreenOnAllowed() { createService(); startSystem(); |