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

Commit b84dc186 authored by Adrian Roos's avatar Adrian Roos
Browse files

DozeMachine: Improve resilience against out-of-order pulse requests

Fixes a class of bugs that arise from requesting to pulse at
inopportune times. Also improves logging such that we know what
state transition failed to validate.

Test: runtest -x frameworks/base/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
Change-Id: If0bbe003c4805fd180d013dadbc28addc5bb0dd4
Fixes: 32869355
parent e8ac4110
Loading
Loading
Loading
Loading
+69 −51
Original line number Diff line number Diff line
@@ -56,7 +56,41 @@ public class DozeMachine {
        /** Pulse is done showing. Followed by transition to DOZE or DOZE_AOD. */
        DOZE_PULSE_DONE,
        /** Doze is done. DozeService is finished. */
        FINISH,
        FINISH;

        boolean canPulse() {
            switch (this) {
                case DOZE:
                case DOZE_AOD:
                    return true;
                default:
                    return false;
            }
        }

        boolean staysAwake() {
            switch (this) {
                case DOZE_REQUEST_PULSE:
                case DOZE_PULSING:
                    return true;
                default:
                    return false;
            }
        }

        int screenState() {
            switch (this) {
                case UNINITIALIZED:
                case INITIALIZED:
                case DOZE:
                    return Display.STATE_OFF;
                case DOZE_PULSING:
                case DOZE_AOD:
                    return Display.STATE_DOZE; // TODO: use STATE_ON if appropriate.
                default:
                    return Display.STATE_UNKNOWN;
            }
        }
    }

    private final Service mDozeService;
@@ -165,6 +199,7 @@ public class DozeMachine {
    }

    private void validateTransition(State newState) {
        try {
            switch (mState) {
                case FINISH:
                    Preconditions.checkState(newState == State.FINISH);
@@ -175,7 +210,7 @@ public class DozeMachine {
            }
            switch (newState) {
                case UNINITIALIZED:
                throw new IllegalArgumentException("can't go to UNINITIALIZED");
                    throw new IllegalArgumentException("can't transition to UNINITIALIZED");
                case INITIALIZED:
                    Preconditions.checkState(mState == State.UNINITIALIZED);
                    break;
@@ -188,29 +223,8 @@ public class DozeMachine {
                default:
                    break;
            }
    }

    private int screenPolicy(State newState) {
        switch (newState) {
            case UNINITIALIZED:
            case INITIALIZED:
            case DOZE:
                return Display.STATE_OFF;
            case DOZE_PULSING:
            case DOZE_AOD:
                return Display.STATE_DOZE; // TODO: use STATE_ON if appropriate.
            default:
                return Display.STATE_UNKNOWN;
        }
    }

    private boolean wakeLockPolicy(State newState) {
        switch (newState) {
            case DOZE_REQUEST_PULSE:
            case DOZE_PULSING:
                return true;
            default:
                return false;
        } catch (RuntimeException e) {
            throw new IllegalStateException("Illegal Transition: " + mState + " -> " + newState, e);
        }
    }

@@ -218,22 +232,26 @@ public class DozeMachine {
        if (mState == State.FINISH) {
            return State.FINISH;
        }
        if (requestedState == State.DOZE_REQUEST_PULSE && !mState.canPulse()) {
            Log.i(TAG, "Dropping pulse request because current state can't pulse: " + mState);
            return mState;
        }
        return requestedState;
    }

    private void updateWakeLockState(State newState) {
        boolean newPolicy = wakeLockPolicy(newState);
        if (mWakeLockHeldForCurrentState && !newPolicy) {
        boolean staysAwake = newState.staysAwake();
        if (mWakeLockHeldForCurrentState && !staysAwake) {
            mWakeLock.release();
            mWakeLockHeldForCurrentState = false;
        } else if (!mWakeLockHeldForCurrentState && newPolicy) {
        } else if (!mWakeLockHeldForCurrentState && staysAwake) {
            mWakeLock.acquire();
            mWakeLockHeldForCurrentState = true;
        }
    }

    private void updateScreenState(State newState) {
        int state = screenPolicy(newState);
        int state = newState.screenState();
        if (state != Display.STATE_UNKNOWN) {
            mDozeService.setDozeScreenState(state);
        }
+12 −0
Original line number Diff line number Diff line
@@ -200,6 +200,18 @@ public class DozeMachineTest {
        assertFalse(mWakeLockFake.isHeld());
    }

    @Test
    @UiThreadTest
    public void testPulseDuringPulse_doesntCrash() {
        mMachine.requestState(INITIALIZED);

        mMachine.requestState(DOZE);
        mMachine.requestState(DOZE_REQUEST_PULSE);
        mMachine.requestState(DOZE_PULSING);
        mMachine.requestState(DOZE_REQUEST_PULSE);
        mMachine.requestState(DOZE_PULSE_DONE);
    }

    @Test
    @UiThreadTest
    public void testScreen_offInDoze() {