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

Commit 125efca6 authored by Beverly Tai's avatar Beverly Tai Committed by Automerger Merge Worker
Browse files

Merge "Update face strong auth strongAuth message" into tm-qpr-dev am: 72ee972d am: 4e40afb1

parents d040a3d7 4e40afb1
Loading
Loading
Loading
Loading
+21 −3
Original line number Diff line number Diff line
@@ -261,6 +261,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
@@ -2949,9 +2950,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;
@@ -1096,18 +1097,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
@@ -1150,6 +1156,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
@@ -28,6 +28,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;
@@ -241,7 +242,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));
@@ -768,6 +771,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
@@ -775,6 +808,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);
@@ -2465,6 +2499,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);
@@ -2519,6 +2558,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;
@@ -630,6 +631,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();