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

Commit a78bab4e authored by Bryce Lee's avatar Bryce Lee Committed by Android (Google) Code Review
Browse files

Merge "Handle waking from unlock in KeyguardViewMediator." into udc-qpr-dev

parents 3175375d 772d0ed0
Loading
Loading
Loading
Loading
+28 −8
Original line number Diff line number Diff line
@@ -444,6 +444,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
    private final LockPatternUtils mLockPatternUtils;
    private final BroadcastDispatcher mBroadcastDispatcher;
    private boolean mKeyguardDonePending = false;
    private boolean mUnlockingAndWakingFromDream = false;
    private boolean mHideAnimationRun = false;
    private boolean mHideAnimationRunning = false;

@@ -802,6 +803,25 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
            mKeyguardViewControllerLazy.get().setKeyguardGoingAwayState(false);
            mKeyguardDisplayManager.hide();
            mUpdateMonitor.startBiometricWatchdog();

            // It's possible that the device was unlocked (via BOUNCER or Fingerprint) while
            // dreaming. It's time to wake up.
            if (mUnlockingAndWakingFromDream) {
                Log.d(TAG, "waking from dream after unlock");
                mUnlockingAndWakingFromDream = false;

                if (mKeyguardStateController.isShowing()) {
                    Log.d(TAG, "keyguard showing after keyguardGone, dismiss");
                    mKeyguardViewControllerLazy.get()
                            .notifyKeyguardAuthenticated(!mWakeAndUnlocking);
                } else {
                    Log.d(TAG, "keyguard gone, waking up from dream");
                    mPM.wakeUp(mSystemClock.uptimeMillis(),
                            mWakeAndUnlocking ? PowerManager.WAKE_REASON_BIOMETRIC
                            : PowerManager.WAKE_REASON_GESTURE,
                            "com.android.systemui:UNLOCK_DREAMING");
                }
            }
            Trace.endSection();
        }

@@ -2665,6 +2685,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,

            mKeyguardExitAnimationRunner = null;
            mWakeAndUnlocking = false;
            mUnlockingAndWakingFromDream = false;
            setPendingLock(false);

            // Force if we we're showing in the middle of hiding, to ensure we end up in the correct
@@ -2789,7 +2810,13 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,

            mHiding = true;

            if (mShowing && !mOccluded) {
            mUnlockingAndWakingFromDream = mStatusBarStateController.isDreaming()
                    && !mStatusBarStateController.isDozing();

            if ((mShowing && !mOccluded) || mUnlockingAndWakingFromDream) {
                if (mUnlockingAndWakingFromDream) {
                    Log.d(TAG, "hiding keyguard before waking from dream");
                }
                mKeyguardGoingAwayRunnable.run();
            } else {
                // TODO(bc-unlock): Fill parameters
@@ -2800,13 +2827,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
                            null /* nonApps */, null /* finishedCallback */);
                });
            }

            // It's possible that the device was unlocked (via BOUNCER or Fingerprint) while
            // dreaming. It's time to wake up.
            if (mDreamOverlayShowing || mUpdateMonitor.isDreaming()) {
                mPM.wakeUp(mSystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
                        "com.android.systemui:UNLOCK_DREAMING");
            }
        }
        Trace.endSection();
    }
+6 −21
Original line number Diff line number Diff line
@@ -160,7 +160,6 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
    private KeyguardViewController mKeyguardViewController;
    private DozeScrimController mDozeScrimController;
    private KeyguardViewMediator mKeyguardViewMediator;
    private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
    private PendingAuthenticated mPendingAuthenticated = null;
    private boolean mHasScreenTurnedOnSinceAuthenticating;
    private boolean mFadedAwayAfterWakeAndUnlock;
@@ -281,8 +280,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
            LatencyTracker latencyTracker,
            ScreenOffAnimationController screenOffAnimationController,
            VibratorHelper vibrator,
            SystemClock systemClock,
            StatusBarKeyguardViewManager statusBarKeyguardViewManager
            SystemClock systemClock
    ) {
        mPowerManager = powerManager;
        mUpdateMonitor = keyguardUpdateMonitor;
@@ -310,7 +308,6 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
        mVibratorHelper = vibrator;
        mLogger = biometricUnlockLogger;
        mSystemClock = systemClock;
        mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;

        dumpManager.registerDumpable(getClass().getName(), this);
    }
@@ -452,19 +449,8 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
        // During wake and unlock, we need to draw black before waking up to avoid abrupt
        // brightness changes due to display state transitions.
        Runnable wakeUp = ()-> {
            // Check to see if we are still locked when we are waking and unlocking from dream.
            // This runnable should be executed after unlock. If that's true, we could be not
            // dreaming, but still locked. In this case, we should attempt to authenticate instead
            // of waking up.
            if (mode == MODE_WAKE_AND_UNLOCK_FROM_DREAM
                    && !mKeyguardStateController.isUnlocked()
                    && !mUpdateMonitor.isDreaming()) {
                // Post wakeUp runnable is called from a callback in keyguard.
                mHandler.post(() -> mKeyguardViewController.notifyKeyguardAuthenticated(
                        false /* primaryAuth */));
            } else if (!wasDeviceInteractive || mUpdateMonitor.isDreaming()) {
            if (!wasDeviceInteractive || mUpdateMonitor.isDreaming()) {
                mLogger.i("bio wakelock: Authenticated, waking up...");

                mPowerManager.wakeUp(
                        mSystemClock.uptimeMillis(),
                        PowerManager.WAKE_REASON_BIOMETRIC,
@@ -476,7 +462,10 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
            Trace.endSection();
        };

        if (mMode != MODE_NONE && mMode != MODE_WAKE_AND_UNLOCK_FROM_DREAM) {
        final boolean wakingFromDream = mMode == MODE_WAKE_AND_UNLOCK_FROM_DREAM
                && !mStatusBarStateController.isDozing();

        if (mMode != MODE_NONE && !wakingFromDream) {
            wakeUp.run();
        }
        switch (mMode) {
@@ -498,10 +487,6 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
                Trace.endSection();
                break;
            case MODE_WAKE_AND_UNLOCK_FROM_DREAM:
                // In the case of waking and unlocking from dream, waking up is delayed until after
                // unlock is complete to avoid conflicts during each sequence's transitions.
                mStatusBarKeyguardViewManager.addAfterKeyguardGoneRunnable(wakeUp);
                // Execution falls through here to proceed unlocking.
            case MODE_WAKE_AND_UNLOCK_PULSING:
            case MODE_WAKE_AND_UNLOCK:
                if (mMode == MODE_WAKE_AND_UNLOCK_PULSING) {
+78 −0
Original line number Diff line number Diff line
@@ -37,7 +37,9 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -345,6 +347,21 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
        mViewMediator.setKeyguardEnabled(false);
        TestableLooper.get(this).processAllMessages();

        mViewMediator.mViewMediatorCallback.keyguardDonePending(true,
                mUpdateMonitor.getCurrentUser());
        mViewMediator.mViewMediatorCallback.readyForKeyguardDone();
        final ArgumentCaptor<Runnable> animationRunnableCaptor =
                ArgumentCaptor.forClass(Runnable.class);
        verify(mStatusBarKeyguardViewManager).startPreHideAnimation(
                animationRunnableCaptor.capture());

        when(mStatusBarStateController.isDreaming()).thenReturn(true);
        when(mStatusBarStateController.isDozing()).thenReturn(false);
        animationRunnableCaptor.getValue().run();

        when(mKeyguardStateController.isShowing()).thenReturn(false);
        mViewMediator.mViewMediatorCallback.keyguardGone();

        // Then dream should wake up
        verify(mPowerManager).wakeUp(anyLong(), anyInt(),
                eq("com.android.systemui:UNLOCK_DREAMING"));
@@ -694,6 +711,67 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
        verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(anyBoolean());
    }

    @Test
    public void testWakeAndUnlockingOverDream() {
        // Send signal to wake
        mViewMediator.onWakeAndUnlocking();

        // Ensure not woken up yet
        verify(mPowerManager, never()).wakeUp(anyLong(), anyInt(), anyString());

        // Verify keyguard told of authentication
        verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(anyBoolean());
        mViewMediator.mViewMediatorCallback.keyguardDonePending(true,
                mUpdateMonitor.getCurrentUser());
        mViewMediator.mViewMediatorCallback.readyForKeyguardDone();
        final ArgumentCaptor<Runnable> animationRunnableCaptor =
                ArgumentCaptor.forClass(Runnable.class);
        verify(mStatusBarKeyguardViewManager).startPreHideAnimation(
                animationRunnableCaptor.capture());

        when(mStatusBarStateController.isDreaming()).thenReturn(true);
        when(mStatusBarStateController.isDozing()).thenReturn(false);
        animationRunnableCaptor.getValue().run();

        when(mKeyguardStateController.isShowing()).thenReturn(false);
        mViewMediator.mViewMediatorCallback.keyguardGone();

        // Verify woken up now.
        verify(mPowerManager).wakeUp(anyLong(), anyInt(), anyString());
    }

    @Test
    public void testWakeAndUnlockingOverDream_signalAuthenticateIfStillShowing() {
        // Send signal to wake
        mViewMediator.onWakeAndUnlocking();

        // Ensure not woken up yet
        verify(mPowerManager, never()).wakeUp(anyLong(), anyInt(), anyString());

        // Verify keyguard told of authentication
        verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(anyBoolean());
        clearInvocations(mStatusBarKeyguardViewManager);
        mViewMediator.mViewMediatorCallback.keyguardDonePending(true,
                mUpdateMonitor.getCurrentUser());
        mViewMediator.mViewMediatorCallback.readyForKeyguardDone();
        final ArgumentCaptor<Runnable> animationRunnableCaptor =
                ArgumentCaptor.forClass(Runnable.class);
        verify(mStatusBarKeyguardViewManager).startPreHideAnimation(
                animationRunnableCaptor.capture());

        when(mStatusBarStateController.isDreaming()).thenReturn(true);
        when(mStatusBarStateController.isDozing()).thenReturn(false);
        animationRunnableCaptor.getValue().run();

        when(mKeyguardStateController.isShowing()).thenReturn(true);

        mViewMediator.mViewMediatorCallback.keyguardGone();


        // Verify keyguard view controller informed of authentication again
        verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(anyBoolean());
    }

    @Test
    @TestableLooper.RunWithLooper(setAsMainLooper = true)
    public void testDoKeyguardWhileInteractive_resets() {
+17 −70
Original line number Diff line number Diff line
@@ -142,8 +142,7 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase {
                mNotificationMediaManager, mWakefulnessLifecycle, mScreenLifecycle,
                mAuthController, mStatusBarStateController,
                mSessionTracker, mLatencyTracker, mScreenOffAnimationController, mVibratorHelper,
                mSystemClock,
                mStatusBarKeyguardViewManager
                mSystemClock
        );
        mBiometricUnlockController.setKeyguardViewController(mStatusBarKeyguardViewManager);
        mBiometricUnlockController.addListener(mBiometricUnlockEventsListener);
@@ -464,69 +463,6 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase {
        verify(mVibratorHelper, never()).vibrateAuthSuccess(anyString());
    }

    @Test
    public void onSideFingerprintSuccess_dreaming_unlockThenWake() {
        when(mAuthController.isSfpsEnrolled(anyInt())).thenReturn(true);
        when(mWakefulnessLifecycle.getLastWakeReason())
                .thenReturn(PowerManager.WAKE_REASON_POWER_BUTTON);
        final ArgumentCaptor<Runnable> afterKeyguardGoneRunnableCaptor =
                ArgumentCaptor.forClass(Runnable.class);
        givenDreamingLocked();
        mBiometricUnlockController.startWakeAndUnlock(BiometricSourceType.FINGERPRINT, true);

        // Make sure the BiometricUnlockController has registered a callback for when the keyguard
        // is gone
        verify(mStatusBarKeyguardViewManager).addAfterKeyguardGoneRunnable(
                afterKeyguardGoneRunnableCaptor.capture());
        // Ensure that the power hasn't been told to wake up yet.
        verify(mPowerManager, never()).wakeUp(anyLong(), anyInt(), anyString());
        // Check that the keyguard has been told to unlock.
        verify(mKeyguardViewMediator).onWakeAndUnlocking();

        // Simulate the keyguard disappearing.
        afterKeyguardGoneRunnableCaptor.getValue().run();
        // Verify that the power manager has been told to wake up now.
        verify(mPowerManager).wakeUp(anyLong(), anyInt(), anyString());
    }

    @Test
    public void onSideFingerprintSuccess_dreaming_unlockIfStillLockedNotDreaming() {
        when(mAuthController.isSfpsEnrolled(anyInt())).thenReturn(true);
        when(mWakefulnessLifecycle.getLastWakeReason())
                .thenReturn(PowerManager.WAKE_REASON_POWER_BUTTON);
        final ArgumentCaptor<Runnable> afterKeyguardGoneRunnableCaptor =
                ArgumentCaptor.forClass(Runnable.class);
        givenDreamingLocked();
        mBiometricUnlockController.startWakeAndUnlock(BiometricSourceType.FINGERPRINT, true);

        // Make sure the BiometricUnlockController has registered a callback for when the keyguard
        // is gone
        verify(mStatusBarKeyguardViewManager).addAfterKeyguardGoneRunnable(
                afterKeyguardGoneRunnableCaptor.capture());
        // Ensure that the power hasn't been told to wake up yet.
        verify(mPowerManager, never()).wakeUp(anyLong(), anyInt(), anyString());
        // Check that the keyguard has been told to unlock.
        verify(mKeyguardViewMediator).onWakeAndUnlocking();

        when(mUpdateMonitor.isDreaming()).thenReturn(false);
        when(mKeyguardStateController.isUnlocked()).thenReturn(false);

        // Simulate the keyguard disappearing.
        afterKeyguardGoneRunnableCaptor.getValue().run();

        final ArgumentCaptor<Runnable> dismissKeyguardRunnableCaptor =
                ArgumentCaptor.forClass(Runnable.class);
        verify(mHandler).post(dismissKeyguardRunnableCaptor.capture());

        // Verify that the power manager was not told to wake up.
        verify(mPowerManager, never()).wakeUp(anyLong(), anyInt(), anyString());

        dismissKeyguardRunnableCaptor.getValue().run();
        // Verify that the keyguard controller is told to unlock.
        verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(eq(false));
    }


    @Test
    public void onSideFingerprintSuccess_oldPowerButtonPress_playHaptic() {
        // GIVEN side fingerprint enrolled, last wake reason was power button
@@ -601,14 +537,25 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase {
        verify(mStatusBarKeyguardViewManager).showPrimaryBouncer(anyBoolean());
    }

    private void givenDreamingLocked() {
        when(mUpdateMonitor.isDreaming()).thenReturn(true);
        when(mUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
    }

    private void givenFingerprintModeUnlockCollapsing() {
        when(mUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
        when(mUpdateMonitor.isDeviceInteractive()).thenReturn(true);
        when(mKeyguardStateController.isShowing()).thenReturn(true);
    }

    private void givenDreamingLocked() {
        when(mUpdateMonitor.isDreaming()).thenReturn(true);
        when(mUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
    }
    @Test
    public void onSideFingerprintSuccess_dreaming_unlockNoWake() {
        when(mAuthController.isSfpsEnrolled(anyInt())).thenReturn(true);
        when(mWakefulnessLifecycle.getLastWakeReason())
                .thenReturn(PowerManager.WAKE_REASON_POWER_BUTTON);
        givenDreamingLocked();
        mBiometricUnlockController.startWakeAndUnlock(BiometricSourceType.FINGERPRINT, true);
        verify(mKeyguardViewMediator).onWakeAndUnlocking();
        // Ensure that the power hasn't been told to wake up yet.
        verify(mPowerManager, never()).wakeUp(anyLong(), anyInt(), anyString());
    }
}