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

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

Merge "Update face strong auth strongAuth message" into tm-qpr-dev

parents c694f8b4 e8da39df
Loading
Loading
Loading
Loading
+21 −3
Original line number Diff line number Diff line
@@ -260,6 +260,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
    @VisibleForTesting
    public static final int BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED = -1;
    public static final int BIOMETRIC_HELP_FACE_NOT_RECOGNIZED = -2;
    public static final int BIOMETRIC_HELP_FACE_NOT_AVAILABLE = -3;

    /**
     * If no cancel signal has been received after this amount of time, set the biometric running
@@ -2948,9 +2949,26 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
            // This would need to be updated for multi-sensor devices
            final boolean supportsFaceDetection = !mFaceSensorProperties.isEmpty()
                    && mFaceSensorProperties.get(0).supportsFaceDetection;
            if (!isUnlockingWithBiometricAllowed(FACE) && supportsFaceDetection) {
            if (!isUnlockingWithBiometricAllowed(FACE)) {
                final boolean udfpsFingerprintAuthRunning = isUdfpsSupported()
                        && isFingerprintDetectionRunning();
                if (supportsFaceDetection && !udfpsFingerprintAuthRunning) {
                    // Run face detection. (If a face is detected, show the bouncer.)
                    mLogger.v("startListeningForFace - detect");
                    mFaceManager.detectFace(mFaceCancelSignal, mFaceDetectionCallback, userId);
                } else {
                    // Don't run face detection. Instead, inform the user
                    // face auth is unavailable and how to proceed.
                    // (ie: "Use fingerprint instead" or "Swipe up to open")
                    mLogger.v("Ignoring \"startListeningForFace - detect\". "
                            + "Informing user face isn't available.");
                    mFaceAuthenticationCallback.onAuthenticationHelp(
                            BIOMETRIC_HELP_FACE_NOT_AVAILABLE,
                            mContext.getResources().getString(
                                    R.string.keyguard_face_unlock_unavailable)
                    );
                    return;
                }
            } else {
                mLogger.v("startListeningForFace - authenticate");
                final boolean isBypassEnabled = mKeyguardBypassController != null
+15 −2
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import static android.hardware.biometrics.BiometricSourceType.FINGERPRINT;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;

import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_AVAILABLE;
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;
@@ -1084,18 +1085,23 @@ public class KeyguardIndicationController {
                }
            }

            final boolean faceAuthUnavailable = biometricSourceType == FACE
                    && msgId == BIOMETRIC_HELP_FACE_NOT_AVAILABLE;

            // TODO(b/141025588): refactor to reduce repetition of code/comments
            // Only checking if unlocking with Biometric is allowed (no matter strong or non-strong
            // as long as primary auth, i.e. PIN/pattern/password, is not required), so it's ok to
            // pass true for isStrongBiometric to isUnlockingWithBiometricAllowed() to bypass the
            // check of whether non-strong biometric is allowed
            if (!mKeyguardUpdateMonitor
                    .isUnlockingWithBiometricAllowed(true /* isStrongBiometric */)) {
                    .isUnlockingWithBiometricAllowed(true /* isStrongBiometric */)
                    && !faceAuthUnavailable) {
                return;
            }

            final boolean faceAuthSoftError = biometricSourceType == FACE
                    && msgId != BIOMETRIC_HELP_FACE_NOT_RECOGNIZED;
                    && msgId != BIOMETRIC_HELP_FACE_NOT_RECOGNIZED
                    && msgId != BIOMETRIC_HELP_FACE_NOT_AVAILABLE;
            final boolean faceAuthFailed = biometricSourceType == FACE
                    && msgId == BIOMETRIC_HELP_FACE_NOT_RECOGNIZED; // ran through matcher & failed
            final boolean fpAuthFailed = biometricSourceType == FINGERPRINT
@@ -1138,6 +1144,13 @@ public class KeyguardIndicationController {
                            getTrustGrantedIndication(),
                            mContext.getString(R.string.keyguard_unlock)
                    );
                } else if (faceAuthUnavailable) {
                    showBiometricMessage(
                            helpString,
                            isUnlockWithFingerprintPossible
                                    ? mContext.getString(R.string.keyguard_suggest_fingerprint)
                                    : mContext.getString(R.string.keyguard_unlock)
                    );
                } else {
                    showBiometricMessage(helpString);
                }
+50 −5
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOM
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_USER_LOCKDOWN;
import static com.android.keyguard.FaceAuthApiRequestReason.NOTIFICATION_PANEL_CLICKED;
import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_AVAILABLE;
import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_STATE_CANCELLING_RESTARTING;
import static com.android.keyguard.KeyguardUpdateMonitor.DEFAULT_CANCEL_SIGNAL_TIMEOUT;
import static com.android.keyguard.KeyguardUpdateMonitor.HAL_POWER_PRESS_TIMEOUT;
@@ -240,7 +241,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
    @Mock
    private FingerprintInteractiveToAuthProvider mInteractiveToAuthProvider;


    private List<FingerprintSensorPropertiesInternal> mFingerprintSensorProperties;
    private final int mCurrentUserId = 100;
    private final UserInfo mCurrentUserInfo = new UserInfo(mCurrentUserId, "Test user", 0);

@@ -280,9 +281,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
        when(mFaceSensorProperties.get(anyInt())).thenReturn(
                createFaceSensorProperties(/* supportsFaceDetection = */ false));

        when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
        when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
        when(mFingerprintManager.getSensorPropertiesInternal()).thenReturn(List.of(
        mFingerprintSensorProperties = List.of(
                new FingerprintSensorPropertiesInternal(1 /* sensorId */,
                        FingerprintSensorProperties.STRENGTH_STRONG,
                        1 /* maxEnrollmentsPerUser */,
@@ -291,7 +290,11 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
                                "1.01" /* firmwareVersion */,
                                "00000001" /* serialNumber */, "" /* softwareVersion */)),
                        FingerprintSensorProperties.TYPE_UDFPS_OPTICAL,
                        false /* resetLockoutRequiresHAT */)));
                        false /* resetLockoutRequiresHAT */));
        when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
        when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
        when(mFingerprintManager.getSensorPropertiesInternal()).thenReturn(
                mFingerprintSensorProperties);
        when(mUserManager.isUserUnlocked(anyInt())).thenReturn(true);
        when(mUserManager.isPrimaryUser()).thenReturn(true);
        when(mStrongAuthTracker.getStub()).thenReturn(mock(IStrongAuthTracker.Stub.class));
@@ -769,6 +772,36 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
                anyBoolean());
    }

    @Test
    public void nofaceDetect_whenStrongAuthRequiredAndBypassUdfpsSupportedAndFpRunning() {
        // GIVEN mocked keyguardUpdateMonitorCallback
        KeyguardUpdateMonitorCallback keyguardUpdateMonitorCallback =
                mock(KeyguardUpdateMonitorCallback.class);
        mKeyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback);

        // GIVEN bypass is enabled, face detection is supported
        lockscreenBypassIsAllowed();
        supportsFaceDetection();
        keyguardIsVisible();

        // GIVEN udfps is supported and strong auth required for weak biometrics (face) only
        givenUdfpsSupported();
        strongAuthRequiredForWeakBiometricOnly(); // this allows fingerprint to run but not face

        // WHEN the device wakes up
        mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
        mTestableLooper.processAllMessages();

        // THEN face detect and authenticate are NOT triggered
        verify(mFaceManager, never()).detectFace(any(), any(), anyInt());
        verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
                anyBoolean());

        // THEN biometric help message sent to callback
        verify(keyguardUpdateMonitorCallback).onBiometricHelp(
                eq(BIOMETRIC_HELP_FACE_NOT_AVAILABLE), anyString(), eq(BiometricSourceType.FACE));
    }

    @Test
    public void faceDetect_whenStrongAuthRequiredAndBypass() {
        // GIVEN bypass is enabled, face detection is supported and strong auth is required
@@ -776,6 +809,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
        supportsFaceDetection();
        strongAuthRequiredEncrypted();
        keyguardIsVisible();
        // fingerprint is NOT running, UDFPS is NOT supported

        // WHEN the device wakes up
        mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
@@ -2466,6 +2500,11 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
        when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
    }

    private void strongAuthRequiredForWeakBiometricOnly() {
        when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(eq(true))).thenReturn(true);
        when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(eq(false))).thenReturn(false);
    }

    private void strongAuthNotRequired() {
        when(mStrongAuthTracker.getStrongAuthForUser(KeyguardUpdateMonitor.getCurrentUser()))
                .thenReturn(0);
@@ -2520,6 +2559,12 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
        mTestableLooper.processAllMessages();
    }

    private void givenUdfpsSupported() {
        Assert.assertFalse(mFingerprintSensorProperties.isEmpty());
        when(mAuthController.getUdfpsProps()).thenReturn(mFingerprintSensorProperties);
        Assert.assertTrue(mKeyguardUpdateMonitor.isUdfpsSupported());
    }

    private void setBroadcastReceiverPendingResult(BroadcastReceiver receiver) {
        BroadcastReceiver.PendingResult pendingResult =
                new BroadcastReceiver.PendingResult(Activity.RESULT_OK,
+28 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_T
import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT;
import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_TIMEOUT;

import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_AVAILABLE;
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.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_ALIGNMENT;
@@ -619,6 +620,33 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
                mContext.getString(R.string.keyguard_suggest_fingerprint));
    }

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

        // GIVEN unlocking with fingerprint is possible
        when(mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible(anyInt()))
                .thenReturn(true);

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

        // WHEN there's a face unavailable message
        mController.getKeyguardCallback().onBiometricHelp(
                BIOMETRIC_HELP_FACE_NOT_AVAILABLE,
                message,
                BiometricSourceType.FACE);

        // THEN show sequential messages such as: 'face unlock unavailable' and
        // 'try fingerprint instead'
        verifyIndicationMessage(
                INDICATION_TYPE_BIOMETRIC_MESSAGE,
                message);
        verifyIndicationMessage(
                INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP,
                mContext.getString(R.string.keyguard_suggest_fingerprint));
    }

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