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

Commit 70d2be9d authored by Milton Wu's avatar Milton Wu
Browse files

[FRR] Support fp frr when both fp face enrolled

Supports showing frr dialog for fingerprint failed when both fingerprint
and face unlock enrolled on the same device

Bug: 409424098
Flag: com.android.server.biometrics.frr_dialog_improvement
Test: atest AuthenticationStatsCollectorTest
Change-Id: Ibf6905bbc473ee43402ac6541ebbe34b3858b0fb
parent 2c90268f
Loading
Loading
Loading
Loading
+17 −3
Original line number Diff line number Diff line
@@ -149,11 +149,25 @@ public class AuthenticationStatsCollector {
            return;
        }

        // Don't collect data for single-modality devices or user has both biometrics enrolled.
        if (isSingleModalityDevice()
                || (hasEnrolledFace(userId) && hasEnrolledFingerprint(userId))) {
        // Don't collect data for single-modality devices
        if (isSingleModalityDevice()) {
            return;
        }
        if (Flags.frrDialogImprovement()) {
            // Don't collect data for users who have fingerprint enrolled when the current modality
            // is not fingerprint. Because the customized FRR notification is for fingerprint only,
            // and we don't want to send the default notification for face when the user has
            // fingerprint enrolled.
            if (mModality != BiometricsProtoEnums.MODALITY_FINGERPRINT
                    && hasEnrolledFingerprint(userId)) {
                return;
            }
        } else {
            // Don't collect data for user has both biometrics enrolled
            if (hasEnrolledFace(userId) && hasEnrolledFingerprint(userId)) {
                return;
            }
        }

        updateAuthenticationStatsMapIfNeeded(userId);

+43 −1
Original line number Diff line number Diff line
@@ -126,6 +126,7 @@ public class AuthenticationStatsCollectorTest {
    }

    @Test
    @DisableFlags(Flags.FLAG_FRR_DIALOG_IMPROVEMENT)
    public void authenticate_authenticationSucceeded_mapShouldBeUpdated() {
        // Assert that the user doesn't exist in the map initially.
        assertThat(mAuthenticationStatsCollector.getAuthenticationStatsForUser(USER_ID_1)).isNull();
@@ -148,6 +149,7 @@ public class AuthenticationStatsCollectorTest {
    }

    @Test
    @DisableFlags(Flags.FLAG_FRR_DIALOG_IMPROVEMENT)
    public void authenticate_authenticationFailed_mapShouldBeUpdated() {
        // Assert that the user doesn't exist in the map initially.
        assertThat(mAuthenticationStatsCollector.getAuthenticationStatsForUser(USER_ID_1)).isNull();
@@ -170,6 +172,46 @@ public class AuthenticationStatsCollectorTest {
        assertThat(authenticationStats.getLastFrrNotificationTime()).isEqualTo(0L);
    }

    @Test
    @EnableFlags(Flags.FLAG_FRR_DIALOG_IMPROVEMENT)
    public void authenticate_dualBiometrics_nonFp_mapShouldNotExist() {
        // Assert that the user doesn't exist in the map initially.
        assertThat(mAuthenticationStatsCollector.getAuthenticationStatsForUser(USER_ID_1)).isNull();

        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT))
                .thenReturn(true);
        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(true);
        when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
        when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(true);

        mAuthenticationStatsCollector.authenticate(USER_ID_1, true /* authenticated */);

        assertThat(mAuthenticationStatsCollector.getAuthenticationStatsForUser(USER_ID_1)).isNull();
    }

    @Test
    @EnableFlags(Flags.FLAG_FRR_DIALOG_IMPROVEMENT)
    public void authenticate_dualBiometrics_fp_mapShouldExist() {
        // Use fingerprint modality
        mAuthenticationStatsCollector = new AuthenticationStatsCollector(mContext,
                BiometricsProtoEnums.MODALITY_FINGERPRINT, mBiometricNotification, mClock);

        // Assert that the user doesn't exist in the map initially.
        assertThat(mAuthenticationStatsCollector.getAuthenticationStatsForUser(USER_ID_1)).isNull();

        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT))
                .thenReturn(true);
        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(true);
        when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
        when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(true);

        mAuthenticationStatsCollector.authenticate(USER_ID_1, true /* authenticated */);

        AuthenticationStats authenticationStats =
                mAuthenticationStatsCollector.getAuthenticationStatsForUser(USER_ID_1);
        assertThat(authenticationStats.getUserId()).isEqualTo(USER_ID_1);
    }

    /**
     * Our current use case does not need the counters to update after the notification
     * limit is reached. If we need these counters to continue counting in the future,
@@ -200,8 +242,8 @@ public class AuthenticationStatsCollectorTest {
        assertThat(authenticationStats.getLastFrrNotificationTime()).isEqualTo(200L);
    }

    // TODO WIP
    @Test
    @DisableFlags(Flags.FLAG_FRR_DIALOG_IMPROVEMENT)
    public void authenticate_frrNotExceeded_notificationNotExceeded_shouldNotSendNotification() {

        mAuthenticationStatsCollector.setAuthenticationStatsForUser(USER_ID_1,