diff options
| author | 2020-09-07 13:51:14 +0200 | |
|---|---|---|
| committer | 2021-01-28 08:23:12 +0000 | |
| commit | d553b33250261cf09fe0486427d59e0101fa4232 (patch) | |
| tree | 49dc54f7b757fbca478740f02361c2c929be5ee9 | |
| parent | 258ae119c939fba262d17eb00aaf3aa05e87060b (diff) | |
Allow wake from quiescent during boot
In quiescent boots, the display is off during boot and after boot
completes when the device goes to sleep. The display can only be woken
up after the device finishes booting and goes to sleep.
With this change, pressing a power or wake key during a quiescent boot
exits the 'quiescent mode' early, turning on the screen again even
before boot completes, and prevents the device from going to sleep once
boot finishes. Other sources calling PowerManager#wakeUp before boot
completes will exit quiescent mode as well.
- Propagate initial display state to DisplayPowerController
- This prevents attempt to run fade out animation when screen is set
to be off when already off, which can block mDisplayReady
- Forward power and wake key presses from PhoneWindowManager to
PowerManagerService even if system is not yet fully booted.
- Needed so that PowerManager knows to exit quiescent mode
- Pass in current listener to PhoneWindowManager#screenTurningOn in
#systemBooted
- If a display state transition happens before boot completes, this
line would drop the existing listener,
and the display would never become ready again.
- Only unset sQuiescent when mDisplayReady
- The initial-off state needs to be fully applied before we can
request the display to come on again, otherwise the screen might
stay in quiescent mode.
Bug: 157494508
Test: atest PowerManagerServiceTest#testQuiescentBoot_WakeKeyBeforeBootCompleted_AwakeAfterBootCompleted
Change-Id: Idb05c4e85b32406bcdfc97d73e91083e4219230a
5 files changed, 62 insertions, 24 deletions
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index d9ee9a306f07..13dc0b9be21f 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -710,9 +710,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } } - private void initialize() { + private void initialize(int displayState) { mPowerState = new DisplayPowerState(mBlanker, - mColorFadeEnabled ? new ColorFade(mDisplayId) : null, mDisplayId); + mColorFadeEnabled ? new ColorFade(mDisplayId) : null, mDisplayId, displayState); if (mColorFadeEnabled) { mColorFadeOnAnimator = ObjectAnimator.ofFloat( @@ -812,11 +812,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mustNotify = !mDisplayReadyLocked; } - // Initialize things the first time the power state is changed. - if (mustInitialize) { - initialize(); - } - // Compute the basic display state using the policy. // We might override this below based on other factors. // Initialise brightness as invalid. @@ -850,6 +845,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } assert(state != Display.STATE_UNKNOWN); + // Initialize things the first time the power state is changed. + if (mustInitialize) { + initialize(state); + } + // Apply the proximity sensor. if (mProximitySensor != null) { if (mPowerRequest.useProximitySensor && state != Display.STATE_OFF) { diff --git a/services/core/java/com/android/server/display/DisplayPowerState.java b/services/core/java/com/android/server/display/DisplayPowerState.java index 54f30a954c33..173adce00cd9 100644 --- a/services/core/java/com/android/server/display/DisplayPowerState.java +++ b/services/core/java/com/android/server/display/DisplayPowerState.java @@ -72,7 +72,8 @@ final class DisplayPowerState { private Runnable mCleanListener; - public DisplayPowerState(DisplayBlanker blanker, ColorFade colorFade, int displayId) { + DisplayPowerState( + DisplayBlanker blanker, ColorFade colorFade, int displayId, int displayState) { mHandler = new Handler(true /*async*/); mChoreographer = Choreographer.getInstance(); mBlanker = blanker; @@ -81,14 +82,14 @@ final class DisplayPowerState { mPhotonicModulator.start(); mDisplayId = displayId; - // At boot time, we know that the screen is on and the electron beam - // animation is not playing. We don't know the screen's brightness though, + // At boot time, we don't know the screen's brightness, // so prepare to set it to a known state when the state is next applied. - // Although we set the brightness to full on here, the display power controller + // Although we set the brightness here, the display power controller // will reset the brightness to a new level immediately before the changes // actually have a chance to be applied. - mScreenState = Display.STATE_ON; - mScreenBrightness = PowerManager.BRIGHTNESS_MAX; + mScreenState = displayState; + mScreenBrightness = (displayState != Display.STATE_OFF) ? PowerManager.BRIGHTNESS_MAX + : PowerManager.BRIGHTNESS_OFF_FLOAT; scheduleScreenUpdate(); mColorFadePrepared = false; diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index c073b430c8df..89e7986fc4bc 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -3491,15 +3491,27 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** {@inheritDoc} */ @Override public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) { + final int keyCode = event.getKeyCode(); + final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; + boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0 + || event.isWakeKey(); + if (!mSystemBooted) { // If we have not yet booted, don't let key events do anything. + // Exception: Wake and power key events are forwarded to PowerManager to allow it to + // wake from quiescent mode during boot. + if (down && (keyCode == KeyEvent.KEYCODE_POWER + || keyCode == KeyEvent.KEYCODE_TV_POWER)) { + wakeUpFromPowerKey(event.getDownTime()); + } else if (down && (isWakeKey || keyCode == KeyEvent.KEYCODE_WAKEUP) + && isWakeKeyWhenScreenOff(keyCode)) { + wakeUpFromWakeKey(event); + } return 0; } final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0; - final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; final boolean canceled = event.isCanceled(); - final int keyCode = event.getKeyCode(); final int displayId = event.getDisplayId(); final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0; @@ -3518,8 +3530,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Basic policy based on interactive state. int result; - boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0 - || event.isWakeKey(); if (interactive || (isInjected && !isWakeKey)) { // When the device is interactive or the key is injected pass the // key to the application. @@ -4740,7 +4750,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } startedWakingUp(PowerManager.WAKE_REASON_UNKNOWN); finishedWakingUp(PowerManager.WAKE_REASON_UNKNOWN); - screenTurningOn(DEFAULT_DISPLAY, null); + screenTurningOn(DEFAULT_DISPLAY, mDefaultDisplayPolicy.getScreenOnListener()); screenTurnedOn(DEFAULT_DISPLAY); } diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 54d05124c114..db4b6d0a3005 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -1036,12 +1036,12 @@ public final class PowerManagerService extends SystemService userActivityNoUpdateLocked( now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID); + updatePowerStateLocked(); if (sQuiescent) { goToSleepNoUpdateLocked(mClock.uptimeMillis(), PowerManager.GO_TO_SLEEP_REASON_QUIESCENT, PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE, Process.SYSTEM_UID); } - updatePowerStateLocked(); } } } @@ -1679,8 +1679,15 @@ public final class PowerManagerService extends SystemService Slog.d(TAG, "wakeUpNoUpdateLocked: eventTime=" + eventTime + ", uid=" + reasonUid); } - if (eventTime < mLastSleepTime || getWakefulnessLocked() == WAKEFULNESS_AWAKE - || mForceSuspendActive || !mSystemReady) { + if (eventTime < mLastSleepTime || mForceSuspendActive || !mSystemReady) { + return false; + } + + if (getWakefulnessLocked() == WAKEFULNESS_AWAKE) { + if (!mBootCompleted && sQuiescent) { + mDirty |= DIRTY_QUIESCENT; + return true; + } return false; } @@ -2821,7 +2828,7 @@ public final class PowerManagerService extends SystemService * * This function recalculates the display power state each time. * - * @return True if the display became ready. + * @return true if the display became ready. */ private boolean updateDisplayPowerStateLocked(int dirty) { final boolean oldDisplayReady = mDisplayReady; @@ -2830,7 +2837,11 @@ public final class PowerManagerService extends SystemService | DIRTY_SETTINGS | DIRTY_SCREEN_BRIGHTNESS_BOOST | DIRTY_VR_MODE_CHANGED | DIRTY_QUIESCENT)) != 0) { if ((dirty & DIRTY_QUIESCENT) != 0) { - sQuiescent = false; + if (mDisplayReady) { + sQuiescent = false; + } else { + mDirty |= DIRTY_QUIESCENT; + } } final DisplayPowerRequest displayPowerRequest = mDisplayPowerRequestMapper.get( @@ -5605,7 +5616,7 @@ public final class PowerManagerService extends SystemService * ignore the proximity sensor. We don't turn off the proximity sensor because * we still want it to be reenabled if it's state changes. * - * @return True if the proximity sensor was successfully ignored and we should + * @return true if the proximity sensor was successfully ignored and we should * consume the key event. */ private boolean interceptPowerKeyDownInternal(KeyEvent event) { 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 533dc1708896..1d0b595d8fc1 100644 --- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java @@ -877,6 +877,22 @@ public class PowerManagerServiceTest { } @Test + public void testQuiescentBoot_WakeKeyBeforeBootCompleted_AwakeAfterBootCompleted() + throws Exception { + when(mSystemPropertiesMock.get(eq(SYSTEM_PROPERTY_QUIESCENT), any())).thenReturn("1"); + createService(); + mService.systemReady(null); + + mService.getBinderServiceInstance().wakeUp(mClock.now(), + PowerManager.WAKE_REASON_UNKNOWN, "testing IPowerManager.wakeUp()", "pkg.name"); + + mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); + assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo( + DisplayPowerRequest.POLICY_BRIGHT); + } + + @Test public void testIsAmbientDisplayAvailable_available() throws Exception { createService(); when(mAmbientDisplayConfigurationMock.ambientDisplayAvailable()).thenReturn(true); |