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

Commit 8853b2c7 authored by Matt Pietal's avatar Matt Pietal
Browse files

Remove all pending keyguard exits on SHOW

Noticed during rapid requests to enabled/disable keyguard,
prevent any preexisting requests to hide or dismiss keyguard
from running when a SHOW message is handled. Reset goingAway,
and also make sure to prevent any WM callbacks in flight from
continuing.

Test: atest KeyguardViewMediatorTest
Bug: 395640609
Bug: 419095873
Flag: EXEMPT bugfix
Change-Id: I732fb7d577a5f4c65c8d84cc66a61f5006ed8d53
parent 48827157
Loading
Loading
Loading
Loading
+37 −10
Original line number Diff line number Diff line
@@ -484,6 +484,13 @@ public class KeyguardViewMediator implements CoreStartable,
     */
    private boolean mHiding;

    /**
     * Tracks SHOW/HIDE requests, in order to determine if a HIDE request show be completed after a
     * series of binder calls returns from WM.
     */
    private int mLastShowRequest = 0;
    private int mLastHideRequest = 0;

    /**
     * we send this intent when the keyguard is dismissed.
     */
@@ -2203,6 +2210,8 @@ public class KeyguardViewMediator implements CoreStartable,
                mNeedToReshowWhenReenabled = false;
                updateInputRestrictedLocked();

                mHandler.removeMessages(HIDE);
                mHandler.removeMessages(START_KEYGUARD_EXIT_ANIM);
                showKeyguard(null);

                // block until we know the keyguard is done drawing (and post a message
@@ -2646,6 +2655,7 @@ public class KeyguardViewMediator implements CoreStartable,
        if (DEBUG) Log.d(TAG, "showKeyguard");
        // ensure we stay awake until we are finished displaying the keyguard
        mShowKeyguardWakeLock.acquire();
        mLastShowRequest++;
        Message msg = mHandler.obtainMessage(SHOW, options);
        // Treat these messages with priority - This call can originate from #doKeyguardTimeout,
        // meaning the device may lock, so it shouldn't wait for other messages on the thread to
@@ -2658,7 +2668,8 @@ public class KeyguardViewMediator implements CoreStartable,
     * Send message to keyguard telling it to hide itself
     * @see #handleHide()
     */
    private void hideLocked() {
    @VisibleForTesting
    void hideLocked() {
        Trace.beginSection("KeyguardViewMediator#hideLocked");
        if (DEBUG) Log.d(TAG, "hideLocked");
        Message msg = mHandler.obtainMessage(HIDE);
@@ -3103,6 +3114,15 @@ public class KeyguardViewMediator implements CoreStartable,
            setShowingLocked(true, hidingOrGoingAway /* force */, "handleShowInner");
            mHiding = false;

            // Any valid exit animation will set this to false before proceeding
            mIsKeyguardExitAnimationCanceled = true;
            // Make sure to remove any pending exit animation requests that would override a SHOW
            mHandler.removeMessages(START_KEYGUARD_EXIT_ANIM);
            mHandler.removeMessages(HIDE);
            mKeyguardInteractor.showKeyguard();
            mShadeController.get().instantCollapseShade();
            mKeyguardStateController.notifyKeyguardGoingAway(false);

            if (!KeyguardWmStateRefactor.isEnabled()) {
                // Handled directly in StatusBarKeyguardViewManager if enabled.
                mKeyguardViewControllerLazy.get().show(options);
@@ -3286,6 +3306,7 @@ public class KeyguardViewMediator implements CoreStartable,
                    Log.d(TAG, "hiding keyguard before waking from dream");
                }
                mHiding = true;
                mLastHideRequest = mLastShowRequest;
                mKeyguardGoingAwayRunnable.run();
            } else {
                if (!KeyguardWmStateRefactor.isEnabled()) {
@@ -3326,10 +3347,16 @@ public class KeyguardViewMediator implements CoreStartable,
        Log.d(TAG, "handleStartKeyguardExitAnimation startTime=" + startTime
                + " fadeoutDuration=" + fadeoutDuration);
        int currentUserId = mSelectedUserInteractor.getSelectedUserId();
        if (!KeyguardWmStateRefactor.isEnabled() && mGoingAwayRequestedForUserId != currentUserId) {
            Log.e(TAG, "Not executing handleStartKeyguardExitAnimationInner() due to userId "
        String error = null;
        if (mGoingAwayRequestedForUserId != currentUserId) {
            error = "Not executing handleStartKeyguardExitAnimationInner() due to userId "
                    + "mismatch. Requested: " + mGoingAwayRequestedForUserId + ", current: "
                    + currentUserId);
                    + currentUserId;
        } else if (mLastHideRequest != mLastShowRequest) {
            error = "Show requested after hide, cancel animation";
        }
        if (!KeyguardWmStateRefactor.isEnabled() && error != null) {
            Log.e(TAG, error);
            if (finishedCallback != null) {
                // There will not execute animation, send a finish callback to ensure the remote
                // animation won't hang there.
@@ -3342,12 +3369,10 @@ public class KeyguardViewMediator implements CoreStartable,
            mHiding = false;
            if (mLockPatternUtils.isSecure(currentUserId)) {
                doKeyguardLocked(null);
                if (!KeyguardWmStateRefactor.isEnabled()) {
                mKeyguardInteractor.showKeyguard();
                mShadeController.get().instantCollapseShade();
                setShowingLocked(true /* showing */, true /* force */,
                            "handleStartKeyguardExitAnimation - mismatch");
                }
                        "handleStartKeyguardExitAnimation - error");
            } else {
                resetStateLocked();
                dismiss(null, null);
@@ -3720,6 +3745,8 @@ public class KeyguardViewMediator implements CoreStartable,
        if (mKeyguardUnlockAnimationControllerLazy.get().isSupportedLauncherUnderneath()) {
            flags |= KEYGUARD_GOING_AWAY_FLAG_TO_LAUNCHER_CLEAR_SNAPSHOT;
        }
        mLastHideRequest = mLastShowRequest;
        mIsKeyguardExitAnimationCanceled = false;

        mKeyguardStateController.notifyKeyguardGoingAway(true);

+24 −1
Original line number Diff line number Diff line
@@ -307,6 +307,7 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
     */
    @After
    public void assertATMSAndKeyguardViewMediatorStatesMatch() {
        android.util.Log.i("CLJ", "7");
        try {
            if (mKeyguardGoingAway) {
                assertATMSKeyguardGoingAway();
@@ -1262,7 +1263,9 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
        IRemoteAnimationFinishedCallback callback = mock(IRemoteAnimationFinishedCallback.class);

        when(mKeyguardStateController.isKeyguardGoingAway()).thenReturn(true);
        mViewMediator.mKeyguardGoingAwayRunnable.run();
        mViewMediator.hideLocked();
        processAllMessagesAndBgExecutorMessages();

        mViewMediator.startKeyguardExitAnimation(TRANSIT_OLD_KEYGUARD_GOING_AWAY, apps, wallpapers,
                null, callback);
        processAllMessagesAndBgExecutorMessages();
@@ -1477,6 +1480,26 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
        mViewMediator.getViewMediatorCallback().onBouncerSwipeDown();
        verify(mStatusBarKeyguardViewManager).reset(true);
    }

    @Test
    @TestableLooper.RunWithLooper(setAsMainLooper = true)
    public void testKeyguardExitAnimationCanceledIfShowIsRequested() {
        // Mock a secure user
        setCurrentUser(55, true);

        // Setup keyguard
        mViewMediator.onSystemReady();
        processAllMessagesAndBgExecutorMessages();
        mViewMediator.setShowingLocked(true, "");

        // This will create a SHOW message, followed by a request to start the exit animation
        mViewMediator.showDismissibleKeyguard();
        startMockKeyguardExitAnimation();

        assertTrue(mViewMediator.isShowingAndNotOccluded());
        verify(mStatusBarKeyguardViewManager, never()).hide(anyLong(), anyLong());
    }

    private void createAndStartViewMediator() {
        createAndStartViewMediator(false);
    }