summaryrefslogtreecommitdiff
path: root/services
diff options
context:
space:
mode:
author Michael Wright <michaelwr@google.com> 2022-12-07 00:16:25 +0000
committer Rupesh Bansal <brup@google.com> 2022-12-14 19:22:59 +0000
commitd7367c39c48b5a05482b49dbc5c67f8920f9aff6 (patch)
tree88597d6aa051ee7b0c5e87e5fda44cd789e155fa /services
parent4ee9f703bbc2800b8cefdbaba2adfd845f791509 (diff)
Sleep softly on device close.
Add a new flag GO_TO_SLEEP_FLAG_SOFT_SLEEP. When set, this sleeps the device only if its user activity keeping it awake. If its otherwise staying awake because an application is holding a wakelock, then the device continues to stay awake. Bug: 260705307 Test: atest PowerManagerServiceTest Test: manual Change-Id: I08b6dacf418d927b4f86816b1b6d19965e68556a
Diffstat (limited to 'services')
-rw-r--r--services/core/java/com/android/server/display/LogicalDisplayMapper.java3
-rw-r--r--services/core/java/com/android/server/power/PowerGroup.java18
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java5
-rw-r--r--services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java105
4 files changed, 130 insertions, 1 deletions
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();