Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d553b332 authored by Robert Horvath's avatar Robert Horvath
Browse files

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
parent 258ae119
Loading
Loading
Loading
Loading
+7 −7
Original line number Diff line number Diff line
@@ -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) {
+7 −6
Original line number Diff line number Diff line
@@ -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;
+15 −5
Original line number Diff line number Diff line
@@ -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);
    }

+17 −6
Original line number Diff line number Diff line
@@ -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) {
                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) {
+16 −0
Original line number Diff line number Diff line
@@ -876,6 +876,22 @@ public class PowerManagerServiceTest {
                DisplayPowerRequest.POLICY_BRIGHT);
    }

    @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();