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

Commit a858b620 authored by Beverly Tai's avatar Beverly Tai Committed by Android (Google) Code Review
Browse files

Merge "Update FP failure logic when device is unlocked" into tm-qpr-dev

parents f9957304 c733abde
Loading
Loading
Loading
Loading
+16 −4
Original line number Diff line number Diff line
@@ -1311,7 +1311,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
    }

    public boolean getUserHasTrust(int userId) {
        return !isTrustDisabled() && mUserHasTrust.get(userId);
        return !isTrustDisabled() && mUserHasTrust.get(userId)
                && isUnlockingWithTrustAgentAllowed();
    }

    /**
@@ -1319,12 +1320,19 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
     */
    public boolean getUserUnlockedWithBiometric(int userId) {
        BiometricAuthenticated fingerprint = mUserFingerprintAuthenticated.get(userId);
        BiometricAuthenticated face = mUserFaceAuthenticated.get(userId);
        boolean fingerprintAllowed = fingerprint != null && fingerprint.mAuthenticated
                && isUnlockingWithBiometricAllowed(fingerprint.mIsStrongBiometric);
        boolean faceAllowed = face != null && face.mAuthenticated
        return fingerprintAllowed || getUserUnlockedWithFace(userId);
    }


    /**
     * Returns whether the user is unlocked with face.
     */
    public boolean getUserUnlockedWithFace(int userId) {
        BiometricAuthenticated face = mUserFaceAuthenticated.get(userId);
        return face != null && face.mAuthenticated
                && isUnlockingWithBiometricAllowed(face.mIsStrongBiometric);
        return fingerprintAllowed || faceAllowed;
    }

    /**
@@ -1399,6 +1407,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
        return mUserTrustIsUsuallyManaged.get(userId);
    }

    private boolean isUnlockingWithTrustAgentAllowed() {
        return isUnlockingWithBiometricAllowed(true);
    }

    public boolean isUnlockingWithBiometricAllowed(boolean isStrongBiometric) {
        // StrongAuthTracker#isUnlockingWithBiometricAllowed includes
        // STRONG_AUTH_REQUIRED_AFTER_LOCKOUT which is the same as mFingerprintLockedOutPermanent;
+39 −18
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import static android.view.View.GONE;
import static android.view.View.VISIBLE;

import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_RECOGNIZED;
import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED;
import static com.android.keyguard.KeyguardUpdateMonitor.getCurrentUser;
import static com.android.systemui.DejankUtils.whitelistIpcs;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.IMPORTANT_MSG_MIN_DURATION;
@@ -539,6 +540,10 @@ public class KeyguardIndicationController {
                            .build(),
                    true
            );
        } else {
            mRotateTextViewController.hideIndication(
                    INDICATION_TYPE_BIOMETRIC_MESSAGE);
        }
        if (!TextUtils.isEmpty(mBiometricMessageFollowUp)) {
            mRotateTextViewController.updateIndication(
                    INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP,
@@ -553,10 +558,6 @@ public class KeyguardIndicationController {
            mRotateTextViewController.hideIndication(
                    INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP);
        }
        } else {
            mRotateTextViewController.hideIndication(INDICATION_TYPE_BIOMETRIC_MESSAGE);
            mRotateTextViewController.hideIndication(INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP);
        }
    }

    private void updateTransient() {
@@ -784,7 +785,8 @@ public class KeyguardIndicationController {
     */
    private void showBiometricMessage(CharSequence biometricMessage,
            @Nullable CharSequence biometricMessageFollowUp) {
        if (TextUtils.equals(biometricMessage, mBiometricMessage)) {
        if (TextUtils.equals(biometricMessage, mBiometricMessage)
                && TextUtils.equals(biometricMessageFollowUp, mBiometricMessageFollowUp)) {
            return;
        }

@@ -793,7 +795,8 @@ public class KeyguardIndicationController {

        mHandler.removeMessages(MSG_SHOW_ACTION_TO_UNLOCK);
        hideBiometricMessageDelayed(
                mBiometricMessageFollowUp != null
                !TextUtils.isEmpty(mBiometricMessage)
                        && !TextUtils.isEmpty(mBiometricMessageFollowUp)
                        ? IMPORTANT_MSG_MIN_DURATION * 2
                        : DEFAULT_HIDE_DELAY_MS
        );
@@ -1091,6 +1094,8 @@ public class KeyguardIndicationController {
                    && msgId != BIOMETRIC_HELP_FACE_NOT_RECOGNIZED;
            final boolean faceAuthFailed = biometricSourceType == FACE
                    && msgId == BIOMETRIC_HELP_FACE_NOT_RECOGNIZED; // ran through matcher & failed
            final boolean fpAuthFailed = biometricSourceType == FINGERPRINT
                    && msgId == BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED; // ran matcher & failed
            final boolean isUnlockWithFingerprintPossible = canUnlockWithFingerprint();
            final boolean isCoExFaceAcquisitionMessage =
                    faceAuthSoftError && isUnlockWithFingerprintPossible;
@@ -1113,6 +1118,22 @@ public class KeyguardIndicationController {
                            mContext.getString(R.string.keyguard_face_failed),
                            mContext.getString(R.string.keyguard_suggest_fingerprint)
                    );
                } else if (fpAuthFailed
                        && mKeyguardUpdateMonitor.getUserUnlockedWithFace(getCurrentUser())) {
                    // face had already previously unlocked the device, so instead of showing a
                    // fingerprint error, tell them they have already unlocked with face auth
                    // and how to enter their device
                    showBiometricMessage(
                            mContext.getString(R.string.keyguard_face_successful_unlock),
                            mContext.getString(R.string.keyguard_unlock)
                    );
                } else if (fpAuthFailed
                        && mKeyguardUpdateMonitor.getUserHasTrust(
                                KeyguardUpdateMonitor.getCurrentUser())) {
                    showBiometricMessage(
                            getTrustGrantedIndication(),
                            mContext.getString(R.string.keyguard_unlock)
                    );
                } else {
                    showBiometricMessage(helpString);
                }
+5 −0
Original line number Diff line number Diff line
@@ -437,6 +437,11 @@ public class KeyguardStateControllerImpl implements KeyguardStateController, Dum
            update(false /* updateAlways */);
        }

        @Override
        public void onLockedOutStateChanged(BiometricSourceType biometricSourceType) {
            update(false /* updateAlways */);
        }

        @Override
        public void onKeyguardVisibilityChanged(boolean visible) {
            update(false /* updateAlways */);
+25 −1
Original line number Diff line number Diff line
@@ -685,11 +685,35 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
        // WHEN fingerprint is locked out
        fingerprintErrorLockedOut();

        // THEN unlocking with fingeprint is not allowed
        // THEN unlocking with fingerprint is not allowed
        Assert.assertFalse(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
                BiometricSourceType.FINGERPRINT));
    }

    @Test
    public void trustAgentHasTrust() {
        // WHEN user has trust
        mKeyguardUpdateMonitor.onTrustChanged(true, true, getCurrentUser(), 0, null);

        // THEN user is considered as "having trust" and bouncer can be skipped
        Assert.assertTrue(mKeyguardUpdateMonitor.getUserHasTrust(getCurrentUser()));
        Assert.assertTrue(mKeyguardUpdateMonitor.getUserCanSkipBouncer(getCurrentUser()));
    }

    @Test
    public void trustAgentHasTrust_fingerprintLockout() {
        // GIVEN user has trust
        mKeyguardUpdateMonitor.onTrustChanged(true, true, getCurrentUser(), 0, null);
        Assert.assertTrue(mKeyguardUpdateMonitor.getUserHasTrust(getCurrentUser()));

        // WHEN fingerprint is locked out
        fingerprintErrorLockedOut();

        // THEN user is NOT considered as "having trust" and bouncer cannot be skipped
        Assert.assertFalse(mKeyguardUpdateMonitor.getUserHasTrust(getCurrentUser()));
        Assert.assertFalse(mKeyguardUpdateMonitor.getUserCanSkipBouncer(getCurrentUser()));
    }

    @Test
    public void testTriesToAuthenticate_whenBouncer() {
        setKeyguardBouncerVisibility(true);
+76 −0
Original line number Diff line number Diff line
@@ -619,6 +619,82 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
                mContext.getString(R.string.keyguard_suggest_fingerprint));
    }

    @Test
    public void onBiometricHelp_coEx_fpFailure_faceAlreadyUnlocked() {
        createController();

        // GIVEN face has already unlocked the device
        when(mKeyguardUpdateMonitor.getUserUnlockedWithFace(anyInt())).thenReturn(true);

        String message = "A message";
        mController.setVisible(true);

        // WHEN there's a fingerprint not recognized message
        mController.getKeyguardCallback().onBiometricHelp(
                BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED,
                message,
                BiometricSourceType.FINGERPRINT);

        // THEN show sequential messages such as: 'Unlocked by face' and
        // 'Swipe up to open'
        verifyIndicationMessage(
                INDICATION_TYPE_BIOMETRIC_MESSAGE,
                mContext.getString(R.string.keyguard_face_successful_unlock));
        verifyIndicationMessage(
                INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP,
                mContext.getString(R.string.keyguard_unlock));
    }

    @Test
    public void onBiometricHelp_coEx_fpFailure_trustAgentAlreadyUnlocked() {
        createController();

        // GIVEN trust agent has already unlocked the device
        when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(true);

        String message = "A message";
        mController.setVisible(true);

        // WHEN there's a fingerprint not recognized message
        mController.getKeyguardCallback().onBiometricHelp(
                BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED,
                message,
                BiometricSourceType.FINGERPRINT);

        // THEN show sequential messages such as: 'Kept unlocked by TrustAgent' and
        // 'Swipe up to open'
        verifyIndicationMessage(
                INDICATION_TYPE_BIOMETRIC_MESSAGE,
                mContext.getString(R.string.keyguard_indication_trust_unlocked));
        verifyIndicationMessage(
                INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP,
                mContext.getString(R.string.keyguard_unlock));
    }

    @Test
    public void onBiometricHelp_coEx_fpFailure_trustAgentUnlocked_emptyTrustGrantedMessage() {
        createController();

        // GIVEN trust agent has already unlocked the device & trust granted message is empty
        when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(true);
        mController.showTrustGrantedMessage(false, "");

        String message = "A message";
        mController.setVisible(true);

        // WHEN there's a fingerprint not recognized message
        mController.getKeyguardCallback().onBiometricHelp(
                BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED,
                message,
                BiometricSourceType.FINGERPRINT);

        // THEN show action to unlock (ie: 'Swipe up to open')
        verifyNoMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE);
        verifyIndicationMessage(
                INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP,
                mContext.getString(R.string.keyguard_unlock));
    }

    @Test
    public void transientIndication_visibleWhenDozing_unlessSwipeUp_fromError() {
        createController();