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

Commit 8eec2687 authored by Lucas Dupin's avatar Lucas Dupin
Browse files

Show bouncer after rebooting

When bypass is active, show bouncer after rebooting, if bouncer
is not visible.

Test: atest BiometricsUnlockControllerTest
Test: atest KeyguardUpdateMonitorTest
Test: without bypass, reboot, observe no scanning animation
Test: without bypass, unlock on lock screen
Test: with bypass, reboot, observe scanning animation, look at bouncer
Test: with bypass, bypass lock screen
Fixes: 135773409
Change-Id: Ic2f0bb137b645e132dc9aae282206c3e84895ce1
parent 4befb749
Loading
Loading
Loading
Loading
+27 −10
Original line number Diff line number Diff line
@@ -30,6 +30,12 @@ import static android.os.BatteryManager.EXTRA_PLUGGED;
import static android.os.BatteryManager.EXTRA_STATUS;
import static android.telephony.PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE;

import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_TIMEOUT;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;

import android.annotation.AnyThread;
import android.annotation.MainThread;
import android.app.ActivityManager;
@@ -672,8 +678,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
        }

        if (msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT) {
            mLockPatternUtils.requireStrongAuth(
                    LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT,
            mLockPatternUtils.requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_LOCKOUT,
                    getCurrentUser());
        }

@@ -833,8 +838,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
        }

        if (msgId == FaceManager.FACE_ERROR_LOCKOUT_PERMANENT) {
            mLockPatternUtils.requireStrongAuth(
                    LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT,
            mLockPatternUtils.requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_LOCKOUT,
                    getCurrentUser());
        }

@@ -953,8 +957,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
    }

    public boolean isUserInLockdown(int userId) {
        return mStrongAuthTracker.getStrongAuthForUser(userId)
                == LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
        return containsFlag(mStrongAuthTracker.getStrongAuthForUser(userId),
                STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
    }

    public boolean userNeedsStrongAuth() {
@@ -962,6 +966,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
                != LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED;
    }

    private boolean containsFlag(int haystack, int needle) {
        return (haystack & needle) != 0;
    }

    public boolean needsSlowUnlockTransition() {
        return mNeedsSlowUnlockTransition;
    }
@@ -1680,8 +1688,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
        final int user = getCurrentUser();
        final int strongAuth = mStrongAuthTracker.getStrongAuthForUser(user);
        final boolean isLockOutOrLockDown =
                strongAuth == StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT
                        || strongAuth == StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
                containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_LOCKOUT)
                        || containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW)
                        || containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
        final boolean isEncryptedOrTimedOut =
                containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_BOOT)
                        || containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_TIMEOUT);

        boolean canBypass = mKeyguardBypassController != null
                && mKeyguardBypassController.canBypass();
@@ -1690,13 +1702,18 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
        // TrustAgents or biometrics are keeping the device unlocked.
        boolean becauseCannotSkipBouncer = !getUserCanSkipBouncer(user) || canBypass;

        // Scan even when encrypted or timeout to show a preemptive bouncer when bypassing.
        // Lockout/lockdown modes shouldn't scan, since they are more explicit.
        boolean strongAuthAllowsScanning = (!isEncryptedOrTimedOut || canBypass && !mBouncer)
                && !isLockOutOrLockDown;

        // Only listen if this KeyguardUpdateMonitor belongs to the primary user. There is an
        // instance of KeyguardUpdateMonitor for each user but KeyguardUpdateMonitor is user-aware.
        return (mBouncer || mAuthInterruptActive || awakeKeyguard || shouldListenForFaceAssistant())
                && !mSwitchingUser && !isFaceDisabled(user) && becauseCannotSkipBouncer
                && !mKeyguardGoingAway && mFaceSettingEnabledForUser && !mLockIconPressed
                && mUserManager.isUserUnlocked(user) && mIsPrimaryUser
                && !mSecureCameraLaunched && !isLockOutOrLockDown;
                && strongAuthAllowsScanning && mIsPrimaryUser
                && !mSecureCameraLaunched;
    }

    /**
+1 −1
Original line number Diff line number Diff line
@@ -410,7 +410,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback {
            } else if (unlockingAllowed) {
                return faceStayingOnKeyguard ? MODE_ONLY_WAKE : MODE_UNLOCK;
            } else if (face) {
                return MODE_NONE;
                return faceStayingOnKeyguard ? MODE_NONE : MODE_SHOW_BOUNCER;
            } else if (!mStatusBarKeyguardViewManager.isBouncerShowing()) {
                return MODE_SHOW_BOUNCER;
            }
+57 −3
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
@@ -317,13 +318,44 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {

    @Test
    public void skipsAuthentication_whenEncryptedKeyguard() {
        reset(mUserManager);
        when(mUserManager.isUserUnlocked(anyInt())).thenReturn(false);
        when(mStrongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn(
                KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT);
        mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController);

        mKeyguardUpdateMonitor.dispatchStartedWakingUp();
        mTestableLooper.processAllMessages();
        mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
        verify(mFaceManager, never()).authenticate(any(), any(), anyInt(), any(), any());
        verify(mFaceManager, never()).authenticate(any(), any(), anyInt(), any(), any(), anyInt());
    }

    @Test
    public void requiresAuthentication_whenEncryptedKeyguard_andBypass() {
        testStrongAuthExceptOnBouncer(
                KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT);
    }

    @Test
    public void requiresAuthentication_whenTimeoutKeyguard_andBypass() {
        testStrongAuthExceptOnBouncer(
                KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_TIMEOUT);
    }

    private void testStrongAuthExceptOnBouncer(int strongAuth) {
        when(mKeyguardBypassController.canBypass()).thenReturn(true);
        mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController);
        when(mStrongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn(strongAuth);

        mKeyguardUpdateMonitor.dispatchStartedWakingUp();
        mTestableLooper.processAllMessages();
        mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
        verify(mFaceManager).authenticate(any(), any(), anyInt(), any(), any(), anyInt());

        // Stop scanning when bouncer becomes visible
        mKeyguardUpdateMonitor.sendKeyguardBouncerChanged(true /* showingBouncer */);
        mTestableLooper.processAllMessages();
        clearInvocations(mFaceManager);
        mKeyguardUpdateMonitor.requestFaceAuth();
        verify(mFaceManager, never()).authenticate(any(), any(), anyInt(), any(), any(), anyInt());
    }

    @Test
@@ -356,6 +388,28 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
        verify(mFaceManager, never()).authenticate(any(), any(), anyInt(), any(), any(), anyInt());
    }

    @Test
    public void testIgnoresAuth_whenLockdown() {
        mKeyguardUpdateMonitor.dispatchStartedWakingUp();
        mTestableLooper.processAllMessages();
        when(mStrongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn(
                KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);

        mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
        verify(mFaceManager, never()).authenticate(any(), any(), anyInt(), any(), any(), anyInt());
    }

    @Test
    public void testIgnoresAuth_whenLockout() {
        mKeyguardUpdateMonitor.dispatchStartedWakingUp();
        mTestableLooper.processAllMessages();
        when(mStrongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn(
                KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT);

        mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
        verify(mFaceManager, never()).authenticate(any(), any(), anyInt(), any(), any(), anyInt());
    }

    @Test
    public void testOnFaceAuthenticated_skipsFaceWhenAuthenticated() {
        mKeyguardUpdateMonitor.onFaceAuthenticated(KeyguardUpdateMonitor.getCurrentUser());
+24 −0
Original line number Diff line number Diff line
@@ -154,6 +154,30 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase {
        verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(eq(false));
    }

    @Test
    public void onBiometricAuthenticated_whenFace_andBypass_encrypted_showBouncer() {
        when(mKeyguardBypassController.getBypassEnabled()).thenReturn(true);
        mBiometricUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);

        when(mUpdateMonitor.isUnlockingWithBiometricAllowed()).thenReturn(false);
        mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT,
                BiometricSourceType.FACE);

        verify(mStatusBarKeyguardViewManager).showBouncer(eq(false));
    }

    @Test
    public void onBiometricAuthenticated_whenFace_noBypass_encrypted_doNothing() {
        mBiometricUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);

        when(mUpdateMonitor.isUnlockingWithBiometricAllowed()).thenReturn(false);
        mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT,
                BiometricSourceType.FACE);

        verify(mStatusBarKeyguardViewManager, never()).showBouncer(anyBoolean());
        verify(mStatusBarKeyguardViewManager, never()).animateCollapsePanels(anyFloat());
    }

    @Test
    public void onBiometricAuthenticated_whenFaceOnBouncer_dismissBouncer() {
        when(mUpdateMonitor.isUnlockingWithBiometricAllowed()).thenReturn(true);