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

Commit 35403612 authored by Matt Pietal's avatar Matt Pietal Committed by Android Build Coastguard Worker
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
(cherry picked from commit 8853b2c7)
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:31d93f9896ee0fde5f3ee82346c2a9d2f2069cd3
Merged-In: I732fb7d577a5f4c65c8d84cc66a61f5006ed8d53
Change-Id: I732fb7d577a5f4c65c8d84cc66a61f5006ed8d53
parent e7824e85
Loading
Loading
Loading
Loading
+53 −8
Original line number Diff line number Diff line
@@ -469,6 +469,13 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
     */
    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.
     */
@@ -494,6 +501,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
    private boolean mUnlockingAndWakingFromDream = false;
    private boolean mHideAnimationRun = false;
    private boolean mHideAnimationRunning = false;
    private boolean mIsKeyguardExitAnimationCanceled = false;

    private SoundPool mLockSounds;
    private int mLockSoundId;
@@ -2151,6 +2159,8 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
                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
@@ -2555,6 +2565,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
        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
@@ -2567,7 +2578,8 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
     * 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);
@@ -2996,6 +3008,15 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
            setShowingLocked(true, hidingOrGoingAway /* force */);
            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);
@@ -3171,6 +3192,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
                    Log.d(TAG, "hiding keyguard before waking from dream");
                }
                mHiding = true;
                mLastHideRequest = mLastShowRequest;
                mKeyguardGoingAwayRunnable.run();
            } else {
                Log.d(TAG, "Hiding keyguard while occluded. Just hide the keyguard view and exit.");
@@ -3201,10 +3223,22 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
        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 "

        // Requests to exit directly from WM are valid if the lockscreen can be dismissed
        if (mKeyguardStateController.canDismissLockScreen()) {
            mLastHideRequest = mLastShowRequest;
        }

        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.
@@ -3228,6 +3262,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
        }

        synchronized (KeyguardViewMediator.this) {
            mIsKeyguardExitAnimationCanceled = false;
            // Tell ActivityManager that we canceled the keyguard animation if
            // handleStartKeyguardExitAnimation was called, but we're not hiding the keyguard,
            // unless we're animating the surface behind the keyguard and will be hiding the
@@ -3271,9 +3306,11 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
                                        Slog.w(TAG, "Failed to call onAnimationFinished", e);
                                    }
                                }
                                if (!mIsKeyguardExitAnimationCanceled) {
                                    onKeyguardExitFinished();
                                    mKeyguardViewControllerLazy.get().hide(0 /* startTime */,
                                            0 /* fadeoutDuration */);
                                }
                                mInteractionJankMonitor.end(CUJ_LOCKSCREEN_UNLOCK_ANIMATION);
                            }

@@ -3476,6 +3513,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
            // A lock is pending, meaning the keyguard exit animation was cancelled because we're
            // re-locking. We should just end the surface-behind animation without exiting the
            // keyguard. The pending lock will be handled by onFinishedGoingToSleep().
            mIsKeyguardExitAnimationCanceled = true;
            finishSurfaceBehindRemoteAnimation(true /* showKeyguard */);
            maybeHandlePendingLock();
        } else {
@@ -3508,6 +3546,12 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
            return;
        }

        if (mIsKeyguardExitAnimationCanceled) {
            Log.d(TAG, "Ignoring exitKeyguardAndFinishSurfaceBehindRemoteAnimation. "
                    + "mIsKeyguardExitAnimationCanceled==true");
            return;
        }

        // Block the panel from expanding, in case we were doing a swipe to dismiss gesture.
        mKeyguardViewControllerLazy.get().blockPanelExpansionFromCurrentTouch();
        final boolean wasShowing = mShowing;
@@ -3567,7 +3611,8 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
            if (mKeyguardUnlockAnimationControllerLazy.get().isSupportedLauncherUnderneath()) {
                flags |= KEYGUARD_GOING_AWAY_FLAG_TO_LAUNCHER_CLEAR_SNAPSHOT;
            }

            mLastHideRequest = mLastShowRequest;
            mIsKeyguardExitAnimationCanceled = false;
            mKeyguardStateController.notifyKeyguardGoingAway(true);

            if (!KeyguardWmStateRefactor.isEnabled()) {
+23 −1
Original line number Diff line number Diff line
@@ -1217,7 +1217,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();
@@ -1395,6 +1397,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);
    }