From 16d6ddde58aac06f8665590887ac883a534e75dd Mon Sep 17 00:00:00 2001 From: Lucas Silva Date: Tue, 11 Oct 2022 11:57:06 -0400 Subject: [PATCH] Add internal API to PowerManager which allows napping when device is asleep. This allows us to enter the dream directly while the device is off, instead of needing to wake the device before entering dream. Bug: 246472225 Test: adb shell cmd dreams start-dreaming (while device asleep) Test: atest PowerGroupTest Change-Id: Id4634f3d5f7c3ae324f85f11a6991f0cab068a7d --- .../java/android/os/PowerManagerInternal.java | 6 +++++ .../server/dreams/DreamManagerService.java | 6 ++--- .../server/dreams/DreamShellCommand.java | 8 +----- .../com/android/server/power/PowerGroup.java | 4 +-- .../server/power/PowerManagerService.java | 25 +++++++++++++------ .../android/server/power/PowerGroupTest.java | 22 +++++++++++++--- 6 files changed, 49 insertions(+), 22 deletions(-) diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java index 5ca0da2d3f975..f62cc879cce36 100644 --- a/core/java/android/os/PowerManagerInternal.java +++ b/core/java/android/os/PowerManagerInternal.java @@ -335,4 +335,10 @@ public abstract class PowerManagerInternal { /** Allows power button to intercept a power key button press. */ public abstract boolean interceptPowerKeyDown(KeyEvent event); + + /** + * Internal version of {@link android.os.PowerManager#nap} which allows for napping while the + * device is not awake. + */ + public abstract void nap(long eventTime, boolean allowWake); } diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java index 7964fd550266f..c9557d60c8b7f 100644 --- a/services/core/java/com/android/server/dreams/DreamManagerService.java +++ b/services/core/java/com/android/server/dreams/DreamManagerService.java @@ -246,8 +246,8 @@ public final class DreamManagerService extends SystemService { // Because napping could cause the screen to turn off immediately if the dream // cannot be started, we keep one eye open and gently poke user activity. long time = SystemClock.uptimeMillis(); - mPowerManager.userActivity(time, true /*noChangeLights*/); - mPowerManager.nap(time); + mPowerManager.userActivity(time, /* noChangeLights= */ true); + mPowerManagerInternal.nap(time, /* allowWake= */ true); } private void requestAwakenInternal(String reason) { @@ -637,7 +637,7 @@ public final class DreamManagerService extends SystemService { @Nullable FileDescriptor err, @NonNull String[] args, @Nullable ShellCallback callback, @NonNull ResultReceiver resultReceiver) throws RemoteException { - new DreamShellCommand(DreamManagerService.this, mPowerManager) + new DreamShellCommand(DreamManagerService.this) .exec(this, in, out, err, args, callback, resultReceiver); } diff --git a/services/core/java/com/android/server/dreams/DreamShellCommand.java b/services/core/java/com/android/server/dreams/DreamShellCommand.java index eae7e80a89f1d..ab84ae4c08a22 100644 --- a/services/core/java/com/android/server/dreams/DreamShellCommand.java +++ b/services/core/java/com/android/server/dreams/DreamShellCommand.java @@ -18,10 +18,8 @@ package com.android.server.dreams; import android.annotation.NonNull; import android.os.Binder; -import android.os.PowerManager; import android.os.Process; import android.os.ShellCommand; -import android.os.SystemClock; import android.text.TextUtils; import android.util.Slog; @@ -34,11 +32,9 @@ public class DreamShellCommand extends ShellCommand { private static final boolean DEBUG = true; private static final String TAG = "DreamShellCommand"; private final @NonNull DreamManagerService mService; - private final @NonNull PowerManager mPowerManager; - DreamShellCommand(@NonNull DreamManagerService service, @NonNull PowerManager powerManager) { + DreamShellCommand(@NonNull DreamManagerService service) { mService = service; - mPowerManager = powerManager; } @Override @@ -67,8 +63,6 @@ public class DreamShellCommand extends ShellCommand { } private int startDreaming() { - mPowerManager.wakeUp(SystemClock.uptimeMillis(), - PowerManager.WAKE_REASON_PLUGGED_IN, "shell:cmd:android.service.dreams:DREAM"); mService.requestStartDreamFromShell(); return 0; } diff --git a/services/core/java/com/android/server/power/PowerGroup.java b/services/core/java/com/android/server/power/PowerGroup.java index 9fe53fbfaf255..431cf3861804d 100644 --- a/services/core/java/com/android/server/power/PowerGroup.java +++ b/services/core/java/com/android/server/power/PowerGroup.java @@ -229,8 +229,8 @@ public class PowerGroup { } } - boolean dreamLocked(long eventTime, int uid) { - if (eventTime < mLastWakeTime || mWakefulness != WAKEFULNESS_AWAKE) { + boolean dreamLocked(long eventTime, int uid, boolean allowWake) { + if (eventTime < mLastWakeTime || (!allowWake && mWakefulness != WAKEFULNESS_AWAKE)) { return false; } diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index f200564a90077..619b29d333611 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -1919,6 +1919,13 @@ public final class PowerManagerService extends SystemService } } + private void napInternal(long eventTime, int uid, boolean allowWake) { + synchronized (mLock) { + dreamPowerGroupLocked(mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP), + eventTime, uid, allowWake); + } + } + private void onUserAttention() { synchronized (mLock) { if (userActivityNoUpdateLocked(mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP), @@ -2034,7 +2041,8 @@ public final class PowerManagerService extends SystemService } @GuardedBy("mLock") - private boolean dreamPowerGroupLocked(PowerGroup powerGroup, long eventTime, int uid) { + private boolean dreamPowerGroupLocked(PowerGroup powerGroup, long eventTime, int uid, + boolean allowWake) { if (DEBUG_SPEW) { Slog.d(TAG, "dreamPowerGroup: groupId=" + powerGroup.getGroupId() + ", eventTime=" + eventTime + ", uid=" + uid); @@ -2042,7 +2050,7 @@ public final class PowerManagerService extends SystemService if (!mBootCompleted || !mSystemReady) { return false; } - return powerGroup.dreamLocked(eventTime, uid); + return powerGroup.dreamLocked(eventTime, uid, allowWake); } @GuardedBy("mLock") @@ -3086,7 +3094,8 @@ public final class PowerManagerService extends SystemService changed = sleepPowerGroupLocked(powerGroup, time, PowerManager.GO_TO_SLEEP_REASON_INATTENTIVE, Process.SYSTEM_UID); } else if (shouldNapAtBedTimeLocked()) { - changed = dreamPowerGroupLocked(powerGroup, time, Process.SYSTEM_UID); + changed = dreamPowerGroupLocked(powerGroup, time, + Process.SYSTEM_UID, /* allowWake= */ false); } else { changed = dozePowerGroupLocked(powerGroup, time, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, Process.SYSTEM_UID); @@ -5701,10 +5710,7 @@ public final class PowerManagerService extends SystemService final int uid = Binder.getCallingUid(); final long ident = Binder.clearCallingIdentity(); try { - synchronized (mLock) { - dreamPowerGroupLocked(mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP), - eventTime, uid); - } + napInternal(eventTime, uid, /* allowWake= */ false); } finally { Binder.restoreCallingIdentity(ident); } @@ -6632,6 +6638,11 @@ public final class PowerManagerService extends SystemService public boolean interceptPowerKeyDown(KeyEvent event) { return interceptPowerKeyDownInternal(event); } + + @Override + public void nap(long eventTime, boolean allowWake) { + napInternal(eventTime, Process.SYSTEM_UID, allowWake); + } } /** diff --git a/services/tests/servicestests/src/com/android/server/power/PowerGroupTest.java b/services/tests/servicestests/src/com/android/server/power/PowerGroupTest.java index d8c9c34333138..e3ca1707ae0c8 100644 --- a/services/tests/servicestests/src/com/android/server/power/PowerGroupTest.java +++ b/services/tests/servicestests/src/com/android/server/power/PowerGroupTest.java @@ -116,7 +116,7 @@ public class PowerGroupTest { @Test public void testDreamPowerGroup() { assertThat(mPowerGroup.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); - mPowerGroup.dreamLocked(TIMESTAMP1, UID); + mPowerGroup.dreamLocked(TIMESTAMP1, UID, /* allowWake= */ false); assertThat(mPowerGroup.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING); assertThat(mPowerGroup.isSandmanSummonedLocked()).isTrue(); verify(mWakefulnessCallbackMock).onWakefulnessChangedLocked(eq(GROUP_ID), @@ -172,7 +172,7 @@ public class PowerGroupTest { eq(UID), /* opUid= */ anyInt(), /* opPackageName= */ isNull(), /* details= */ isNull()); assertThat(mPowerGroup.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING); - assertThat(mPowerGroup.dreamLocked(TIMESTAMP2, UID)).isFalse(); + assertThat(mPowerGroup.dreamLocked(TIMESTAMP2, UID, /* allowWake= */ false)).isFalse(); assertThat(mPowerGroup.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING); verify(mWakefulnessCallbackMock, never()).onWakefulnessChangedLocked( eq(GROUP_ID), /* wakefulness= */ eq(WAKEFULNESS_DREAMING), eq(TIMESTAMP2), @@ -180,6 +180,22 @@ public class PowerGroupTest { /* details= */ any()); } + @Test + public void testDreamPowerGroupWhenNotAwakeShouldWake() { + mPowerGroup.dozeLocked(TIMESTAMP1, UID, GO_TO_SLEEP_REASON_TIMEOUT); + verify(mWakefulnessCallbackMock).onWakefulnessChangedLocked(eq(GROUP_ID), + eq(WAKEFULNESS_DOZING), eq(TIMESTAMP1), eq(GO_TO_SLEEP_REASON_TIMEOUT), + eq(UID), /* opUid= */ anyInt(), /* opPackageName= */ isNull(), + /* details= */ isNull()); + assertThat(mPowerGroup.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING); + assertThat(mPowerGroup.dreamLocked(TIMESTAMP2, UID, /* allowWake= */ true)).isTrue(); + assertThat(mPowerGroup.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING); + verify(mWakefulnessCallbackMock).onWakefulnessChangedLocked( + eq(GROUP_ID), /* wakefulness= */ eq(WAKEFULNESS_DREAMING), eq(TIMESTAMP2), + /* reason= */ anyInt(), eq(UID), /* opUid= */ anyInt(), /* opPackageName= */ any(), + /* details= */ any()); + } + @Test public void testLastWakeAndSleepTimeIsUpdated() { assertThat(mPowerGroup.getLastWakeTimeLocked()).isEqualTo(TIMESTAMP_CREATE); @@ -514,7 +530,7 @@ public class PowerGroupTest { .setBatterySaverEnabled(batterySaverEnabled) .setBrightnessFactor(brightnessFactor) .build(); - mPowerGroup.dreamLocked(TIMESTAMP1, UID); + mPowerGroup.dreamLocked(TIMESTAMP1, UID, /* allowWake= */ false); assertThat(mPowerGroup.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING); mPowerGroup.setWakeLockSummaryLocked(WAKE_LOCK_SCREEN_BRIGHT); mPowerGroup.updateLocked(/* screenBrightnessOverride= */ BRIGHTNESS,