Merge "FRR - Add a device overlay to control QPR1 release targets" into udc-qpr-dev am: da7b419bfa am: 3c829b4521
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/24774803
Change-Id: Ia6e2b632ef129e15f1c619080e685112d6a925c2
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index d09bf44..9ffd17f 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -5451,6 +5451,10 @@
to enroll the other eligible biometric. -->
<fraction name="config_biometricNotificationFrrThreshold">25%</fraction>
+ <!-- Whether to enable the biometric notification for dual-modality device that enrolled a
+ single biometric and experiences high FRR. -->
+ <bool name="config_biometricFrrNotificationEnabled">false</bool>
+
<!-- The component name for the default profile supervisor, which can be set as a profile owner
even after user setup is complete. The defined component should be used for supervision purposes
only. The component must be part of a system app. -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 7f1a6f9..fe11449 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2604,6 +2604,7 @@
<!-- Biometric FRR config -->
<java-symbol type="fraction" name="config_biometricNotificationFrrThreshold" />
+ <java-symbol type="bool" name="config_biometricFrrNotificationEnabled" />
<!-- Biometric FRR notification messages -->
<java-symbol type="string" name="device_unlock_notification_name" />
diff --git a/services/core/java/com/android/server/biometrics/AuthenticationStatsCollector.java b/services/core/java/com/android/server/biometrics/AuthenticationStatsCollector.java
index 6edbfb7..4df2581 100644
--- a/services/core/java/com/android/server/biometrics/AuthenticationStatsCollector.java
+++ b/services/core/java/com/android/server/biometrics/AuthenticationStatsCollector.java
@@ -57,6 +57,7 @@
@NonNull private final FaceManager mFaceManager;
@NonNull private final FingerprintManager mFingerprintManager;
+ private final boolean mEnabled;
private final float mThreshold;
private final int mModality;
@@ -80,6 +81,7 @@
public AuthenticationStatsCollector(@NonNull Context context, int modality,
@NonNull BiometricNotification biometricNotification) {
mContext = context;
+ mEnabled = context.getResources().getBoolean(R.bool.config_biometricFrrNotificationEnabled);
mThreshold = context.getResources()
.getFraction(R.fraction.config_biometricNotificationFrrThreshold, 1, 1);
mUserAuthenticationStatsMap = new HashMap<>();
@@ -110,6 +112,11 @@
/** Update total authentication and rejected attempts. */
public void authenticate(int userId, boolean authenticated) {
+ // Don't collect data if the feature is disabled.
+ if (!mEnabled) {
+ return;
+ }
+
// Don't collect data for single-modality devices or user has both biometrics enrolled.
if (isSingleModalityDevice()
|| (hasEnrolledFace(userId) && hasEnrolledFingerprint(userId))) {
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthenticationStatsCollectorTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthenticationStatsCollectorTest.java
index a11a8f5..d2e83e9 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/AuthenticationStatsCollectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthenticationStatsCollectorTest.java
@@ -87,6 +87,8 @@
public void setUp() {
when(mContext.getResources()).thenReturn(mResources);
+ when(mResources.getBoolean(eq(R.bool.config_biometricFrrNotificationEnabled)))
+ .thenReturn(true);
when(mResources.getFraction(eq(R.fraction.config_biometricNotificationFrrThreshold),
anyInt(), anyInt())).thenReturn(FRR_THRESHOLD);
@@ -110,7 +112,6 @@
0 /* modality */, mBiometricNotification);
}
-
@Test
public void authenticate_authenticationSucceeded_mapShouldBeUpdated() {
// Assert that the user doesn't exist in the map initially.
@@ -342,4 +343,32 @@
// Assert that notification count has been updated.
assertThat(authenticationStats.getEnrollmentNotifications()).isEqualTo(1);
}
+
+ @Test
+ public void authenticate_featureDisabled_mapMustNotBeUpdated() {
+ // Disable the feature.
+ when(mResources.getBoolean(eq(R.bool.config_biometricFrrNotificationEnabled)))
+ .thenReturn(false);
+ AuthenticationStatsCollector authenticationStatsCollector =
+ new AuthenticationStatsCollector(mContext, 0 /* modality */,
+ mBiometricNotification);
+
+ authenticationStatsCollector.setAuthenticationStatsForUser(USER_ID_1,
+ new AuthenticationStats(USER_ID_1, 500 /* totalAttempts */,
+ 400 /* rejectedAttempts */, 0 /* enrollmentNotifications */,
+ 0 /* modality */));
+
+ authenticationStatsCollector.authenticate(USER_ID_1, false /* authenticated */);
+
+ // Assert that no notification should be sent.
+ verify(mBiometricNotification, never()).sendFaceEnrollNotification(any());
+ verify(mBiometricNotification, never()).sendFpEnrollNotification(any());
+ // Assert that data hasn't been updated.
+ AuthenticationStats authenticationStats = authenticationStatsCollector
+ .getAuthenticationStatsForUser(USER_ID_1);
+ assertThat(authenticationStats.getTotalAttempts()).isEqualTo(500);
+ assertThat(authenticationStats.getRejectedAttempts()).isEqualTo(400);
+ assertThat(authenticationStats.getEnrollmentNotifications()).isEqualTo(0);
+ assertThat(authenticationStats.getFrr()).isWithin(0f).of(0.8f);
+ }
}