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

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

On quiescent boot, report screenTurningOff, skip screenTurningOn

Fixes an issue where ActivityStacks were resumed while the screen was
off and PowerManager wakefulness was asleep after a quiescent boot.

To keep ActivityStacks paused, PhoneWindowManager acquires a "sleep
token". In #screenTurningOff, this token is acquired, and
in #screenTurningOn it is released.

Before, PhoneWindowManager#systemBooted always called #screenTurningOn.
In a quiescent boot, this led to the sleep token being released and
ActivityStacks being resumed, even though the screen did not actually
turn on.

With this change, DisplayPowerController calls #screenTurningOff during
a quiescent boot, acquiring the sleep token, and #systemBooted skips
calling #screenTurningOn, preventing the sleep token from being released
again.
To finish up boot, #enableScreen is called (last part
of #finishScreenTurningOn), which stops the boot animation process,
signals SurfaceFlinger and ActivityManager that boot has completed.

Bug: 171827143
Test: atest QuiescentBootTests#testQuiescentBoot_activitiesNotResumedAfterBoot
Test: adb reboot quiescent
      adb shell dumpsys power: Verify wakefulness asleep
      adb shell dumpsys activity activities:
        Verify stack is sleeping (isSleeping=true),
        state is STOPPED (state=STOPPED)
Change-Id: Ieb0b805c33b3da4261856b724f32412c2660f4c9
parent 397cb14b
Loading
Loading
Loading
Loading
+11 −6
Original line number Diff line number Diff line
@@ -140,6 +140,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
    private static final int RAMP_STATE_SKIP_INITIAL = 1;
    private static final int RAMP_STATE_SKIP_AUTOBRIGHT = 2;

    private static final int REPORTED_TO_POLICY_UNREPORTED = -1;
    private static final int REPORTED_TO_POLICY_SCREEN_OFF = 0;
    private static final int REPORTED_TO_POLICY_SCREEN_TURNING_ON = 1;
    private static final int REPORTED_TO_POLICY_SCREEN_ON = 2;
@@ -311,8 +312,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
    private long mScreenOnBlockStartRealTime;
    private long mScreenOffBlockStartRealTime;

    // Screen state we reported to policy. Must be one of REPORTED_TO_POLICY_SCREEN_* fields.
    private int mReportedScreenStateToPolicy;
    // Screen state we reported to policy. Must be one of REPORTED_TO_POLICY_* fields.
    private int mReportedScreenStateToPolicy = REPORTED_TO_POLICY_UNREPORTED;

    // If the last recorded screen state was dozing or not.
    private boolean mDozing;
@@ -1440,12 +1441,14 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call

    private boolean setScreenState(int state, boolean reportOnly) {
        final boolean isOff = (state == Display.STATE_OFF);
        if (mPowerState.getScreenState() != state) {

        if (mPowerState.getScreenState() != state
                || mReportedScreenStateToPolicy == REPORTED_TO_POLICY_UNREPORTED) {
            // If we are trying to turn screen off, give policy a chance to do something before we
            // actually turn the screen off.
            if (isOff && !mScreenOffBecauseOfProximity) {
                if (mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_ON) {
                if (mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_ON
                        || mReportedScreenStateToPolicy == REPORTED_TO_POLICY_UNREPORTED) {
                    setReportedScreenState(REPORTED_TO_POLICY_SCREEN_TURNING_OFF);
                    blockScreenOff();
                    mWindowManagerPolicy.screenTurningOff(mDisplayId, mPendingScreenOffUnblocker);
@@ -1456,7 +1459,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
                }
            }

            if (!reportOnly) {
            if (!reportOnly && mPowerState.getScreenState() != state) {
                Trace.traceCounter(Trace.TRACE_TAG_POWER, "ScreenState", state);
                // TODO(b/153319140) remove when we can get this from the above trace invocation
                SystemProperties.set("debug.tracing.screen_state", String.valueOf(state));
@@ -1486,7 +1489,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
            mWindowManagerPolicy.screenTurnedOff(mDisplayId);
            setReportedScreenState(REPORTED_TO_POLICY_SCREEN_OFF);
        }
        if (!isOff && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_OFF) {
        if (!isOff
                && (mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_OFF
                        || mReportedScreenStateToPolicy == REPORTED_TO_POLICY_UNREPORTED)) {
            setReportedScreenState(REPORTED_TO_POLICY_SCREEN_TURNING_ON);
            if (mPowerState.getColorFadeLevel() == 0.0f) {
                blockScreenOn();
+34 −11
Original line number Diff line number Diff line
@@ -405,6 +405,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
    private boolean mEnableCarDockHomeCapture = true;

    boolean mBootMessageNeedsHiding;
    volatile boolean mBootAnimationDismissable;
    private KeyguardServiceDelegate mKeyguardDelegate;
    private boolean mKeyguardBound;
    final Runnable mWindowManagerDrawCallback = new Runnable() {
@@ -4305,6 +4306,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                    0 /* cookie */);
            updateScreenOffSleepToken(false);
            mDefaultDisplayPolicy.screenTurnedOn(screenOnListener);
            mBootAnimationDismissable = false;

            synchronized (mLock) {
                if (mKeyguardDelegate != null && mKeyguardDelegate.hasKeyguard()) {
@@ -4379,6 +4381,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        }
        Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, "screenTurningOn", 0 /* cookie */);

        enableScreen(listener, true /* report */);
    }

    private void enableScreen(ScreenOnListener listener, boolean report) {
        final boolean enableScreen;
        final boolean awake = mDefaultDisplayPolicy.isAwake();
        synchronized (mLock) {
@@ -4396,6 +4402,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
            }
        }

        if (report) {
            if (listener != null) {
                listener.onScreenOn();
            }
@@ -4407,6 +4414,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                }
            }
            mScreenOnListeners.clear();
        }

        if (enableScreen) {
            try {
@@ -4614,13 +4622,28 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        }
        startedWakingUp(PowerManager.WAKE_REASON_UNKNOWN);
        finishedWakingUp(PowerManager.WAKE_REASON_UNKNOWN);

        int defaultDisplayState = mDisplayManager.getDisplay(DEFAULT_DISPLAY).getState();
        boolean defaultDisplayOn = defaultDisplayState == Display.STATE_ON;
        boolean defaultScreenTurningOn = mDefaultDisplayPolicy.getScreenOnListener() != null;
        if (defaultDisplayOn || defaultScreenTurningOn) {
            // Now that system is booted, wait for keyguard and windows to be drawn before
            // updating the orientation listener, stopping the boot animation and enabling screen.
            screenTurningOn(DEFAULT_DISPLAY, mDefaultDisplayPolicy.getScreenOnListener());
            screenTurnedOn(DEFAULT_DISPLAY);
        } else {
            // We're not turning the screen on, so don't wait for keyguard to be drawn
            // to dismiss the boot animation and finish booting
            mBootAnimationDismissable = true;
            enableScreen(null, false /* report */);
        }
    }

    @Override
    public boolean canDismissBootAnimation() {
        return mDefaultDisplayPolicy.isKeyguardDrawComplete();
        // Allow to dismiss the boot animation if the keyguard has finished drawing,
        // or mBootAnimationDismissable has been set
        return mDefaultDisplayPolicy.isKeyguardDrawComplete() || mBootAnimationDismissable;
    }

    ProgressDialog mBootMsgDialog = null;