summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Diya Bera <diyab@google.com> 2023-08-24 12:52:07 -0700
committer Diya Bera <diyab@google.com> 2023-08-24 12:52:07 -0700
commit4d226f3d28eceecbf1578ba66347b804aed93db1 (patch)
tree5b0eef944ace80d28f9813a860dbbdcc3ba11adf
parent7aafa2293df88477f3a1867c62b0ce55679f08f4 (diff)
Prioritize hardware error over no enrollment error
Test: atest PreAuthInfoTest Bug: 295229235 Change-Id: I779599763d70ba4e629da12905a9eb40a291d1db
-rw-r--r--services/core/java/com/android/server/biometrics/PreAuthInfo.java12
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java120
2 files changed, 97 insertions, 35 deletions
diff --git a/services/core/java/com/android/server/biometrics/PreAuthInfo.java b/services/core/java/com/android/server/biometrics/PreAuthInfo.java
index b1740a780539..c29d9bd19149 100644
--- a/services/core/java/com/android/server/biometrics/PreAuthInfo.java
+++ b/services/core/java/com/android/server/biometrics/PreAuthInfo.java
@@ -273,14 +273,18 @@ class PreAuthInfo {
private Pair<BiometricSensor, Integer> calculateErrorByPriority() {
Pair<BiometricSensor, Integer> sensorNotEnrolled = null;
Pair<BiometricSensor, Integer> sensorLockout = null;
+ Pair<BiometricSensor, Integer> hardwareNotDetected = null;
for (Pair<BiometricSensor, Integer> pair : ineligibleSensors) {
- int status = pair.second;
+ final int status = pair.second;
if (status == BIOMETRIC_LOCKOUT_TIMED || status == BIOMETRIC_LOCKOUT_PERMANENT) {
sensorLockout = pair;
}
- if (pair.second == BIOMETRIC_NOT_ENROLLED) {
+ if (status == BIOMETRIC_NOT_ENROLLED) {
sensorNotEnrolled = pair;
}
+ if (status == BIOMETRIC_HARDWARE_NOT_DETECTED) {
+ hardwareNotDetected = pair;
+ }
}
// If there is a sensor locked out, prioritize lockout over other sensor's error.
@@ -289,6 +293,10 @@ class PreAuthInfo {
return sensorLockout;
}
+ if (hardwareNotDetected != null) {
+ return hardwareNotDetected;
+ }
+
// If the caller requested STRONG, and the device contains both STRONG and non-STRONG
// sensors, prioritize BIOMETRIC_NOT_ENROLLED over the weak sensor's
// BIOMETRIC_INSUFFICIENT_STRENGTH error.
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java b/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java
index c2bdf501198e..b40d7ee39a4c 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java
@@ -18,6 +18,8 @@ package com.android.server.biometrics;
import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE;
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
+import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
+import static android.hardware.biometrics.BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE;
import static com.android.server.biometrics.sensors.LockoutTracker.LOCKOUT_NONE;
@@ -53,12 +55,15 @@ public class PreAuthInfoTest {
@Rule
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+ private static final int SENSOR_ID_FINGERPRINT = 0;
private static final int SENSOR_ID_FACE = 1;
private static final String TEST_PACKAGE_NAME = "PreAuthInfoTestPackage";
@Mock
IBiometricAuthenticator mFaceAuthenticator;
@Mock
+ IBiometricAuthenticator mFingerprintAuthenticator;
+ @Mock
Context mContext;
@Mock
ITrustManager mTrustManager;
@@ -79,6 +84,11 @@ public class PreAuthInfoTest {
when(mFaceAuthenticator.isHardwareDetected(any())).thenReturn(true);
when(mFaceAuthenticator.getLockoutModeForUser(anyInt()))
.thenReturn(LOCKOUT_NONE);
+ when(mFingerprintAuthenticator.hasEnrolledTemplates(anyInt(), any()))
+ .thenReturn(true);
+ when(mFingerprintAuthenticator.isHardwareDetected(any())).thenReturn(true);
+ when(mFingerprintAuthenticator.getLockoutModeForUser(anyInt()))
+ .thenReturn(LOCKOUT_NONE);
when(mBiometricCameraManager.isCameraPrivacyEnabled()).thenReturn(false);
when(mBiometricCameraManager.isAnyCameraUnavailable()).thenReturn(false);
}
@@ -87,18 +97,7 @@ public class PreAuthInfoTest {
public void testFaceAuthentication_whenCameraPrivacyIsEnabled() throws Exception {
when(mBiometricCameraManager.isCameraPrivacyEnabled()).thenReturn(true);
- BiometricSensor sensor = new BiometricSensor(mContext, SENSOR_ID_FACE, TYPE_FACE,
- BiometricManager.Authenticators.BIOMETRIC_STRONG, mFaceAuthenticator) {
- @Override
- boolean confirmationAlwaysRequired(int userId) {
- return false;
- }
-
- @Override
- boolean confirmationSupported() {
- return false;
- }
- };
+ BiometricSensor sensor = getFaceSensor();
PromptInfo promptInfo = new PromptInfo();
promptInfo.setConfirmationRequested(false /* requireConfirmation */);
promptInfo.setAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG);
@@ -114,18 +113,7 @@ public class PreAuthInfoTest {
@Test
public void testFaceAuthentication_whenCameraPrivacyIsDisabledAndCameraIsAvailable()
throws Exception {
- BiometricSensor sensor = new BiometricSensor(mContext, SENSOR_ID_FACE, TYPE_FACE,
- BiometricManager.Authenticators.BIOMETRIC_STRONG, mFaceAuthenticator) {
- @Override
- boolean confirmationAlwaysRequired(int userId) {
- return false;
- }
-
- @Override
- boolean confirmationSupported() {
- return false;
- }
- };
+ BiometricSensor sensor = getFaceSensor();
PromptInfo promptInfo = new PromptInfo();
promptInfo.setConfirmationRequested(false /* requireConfirmation */);
promptInfo.setAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG);
@@ -141,6 +129,80 @@ public class PreAuthInfoTest {
@Test
public void testFaceAuthentication_whenCameraIsUnavailable() throws RemoteException {
when(mBiometricCameraManager.isAnyCameraUnavailable()).thenReturn(true);
+
+ BiometricSensor sensor = getFaceSensor();
+ PromptInfo promptInfo = new PromptInfo();
+ promptInfo.setConfirmationRequested(false /* requireConfirmation */);
+ promptInfo.setAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG);
+ promptInfo.setDisallowBiometricsIfPolicyExists(false /* checkDevicePolicy */);
+ PreAuthInfo preAuthInfo = PreAuthInfo.create(mTrustManager, mDevicePolicyManager,
+ mSettingObserver, List.of(sensor),
+ 0 /* userId */, promptInfo, TEST_PACKAGE_NAME,
+ false /* checkDevicePolicyManager */, mContext, mBiometricCameraManager);
+
+ assertThat(preAuthInfo.eligibleSensors).hasSize(0);
+ }
+
+ @Test
+ public void testCanAuthenticateResult_whenCameraUnavailableAndNoFingerprintsEnrolled()
+ throws RemoteException {
+ when(mBiometricCameraManager.isAnyCameraUnavailable()).thenReturn(true);
+ when(mFingerprintAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(false);
+
+ BiometricSensor faceSensor = getFaceSensor();
+ BiometricSensor fingerprintSensor = getFingerprintSensor();
+ PromptInfo promptInfo = new PromptInfo();
+ promptInfo.setConfirmationRequested(false /* requireConfirmation */);
+ promptInfo.setAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG);
+ promptInfo.setDisallowBiometricsIfPolicyExists(false /* checkDevicePolicy */);
+ PreAuthInfo preAuthInfo = PreAuthInfo.create(mTrustManager, mDevicePolicyManager,
+ mSettingObserver, List.of(faceSensor, fingerprintSensor),
+ 0 /* userId */, promptInfo, TEST_PACKAGE_NAME,
+ false /* checkDevicePolicyManager */, mContext, mBiometricCameraManager);
+
+ assertThat(preAuthInfo.eligibleSensors).hasSize(0);
+ assertThat(preAuthInfo.getCanAuthenticateResult()).isEqualTo(
+ BIOMETRIC_ERROR_HW_UNAVAILABLE);
+ }
+
+ @Test
+ public void testFingerprintAuthentication_whenCameraIsUnavailable() throws RemoteException {
+ when(mBiometricCameraManager.isAnyCameraUnavailable()).thenReturn(true);
+
+ BiometricSensor faceSensor = getFaceSensor();
+ BiometricSensor fingerprintSensor = getFingerprintSensor();
+ PromptInfo promptInfo = new PromptInfo();
+ promptInfo.setConfirmationRequested(false /* requireConfirmation */);
+ promptInfo.setAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG);
+ promptInfo.setDisallowBiometricsIfPolicyExists(false /* checkDevicePolicy */);
+ PreAuthInfo preAuthInfo = PreAuthInfo.create(mTrustManager, mDevicePolicyManager,
+ mSettingObserver, List.of(faceSensor, fingerprintSensor),
+ 0 /* userId */, promptInfo, TEST_PACKAGE_NAME,
+ false /* checkDevicePolicyManager */, mContext, mBiometricCameraManager);
+
+ assertThat(preAuthInfo.eligibleSensors).hasSize(1);
+ assertThat(preAuthInfo.eligibleSensors.get(0).modality).isEqualTo(TYPE_FINGERPRINT);
+ }
+
+ private BiometricSensor getFingerprintSensor() {
+ BiometricSensor sensor = new BiometricSensor(mContext, SENSOR_ID_FINGERPRINT,
+ TYPE_FINGERPRINT, BiometricManager.Authenticators.BIOMETRIC_STRONG,
+ mFingerprintAuthenticator) {
+ @Override
+ boolean confirmationAlwaysRequired(int userId) {
+ return false;
+ }
+
+ @Override
+ boolean confirmationSupported() {
+ return false;
+ }
+ };
+
+ return sensor;
+ }
+
+ private BiometricSensor getFaceSensor() {
BiometricSensor sensor = new BiometricSensor(mContext, SENSOR_ID_FACE, TYPE_FACE,
BiometricManager.Authenticators.BIOMETRIC_STRONG, mFaceAuthenticator) {
@Override
@@ -153,15 +215,7 @@ public class PreAuthInfoTest {
return false;
}
};
- PromptInfo promptInfo = new PromptInfo();
- promptInfo.setConfirmationRequested(false /* requireConfirmation */);
- promptInfo.setAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG);
- promptInfo.setDisallowBiometricsIfPolicyExists(false /* checkDevicePolicy */);
- PreAuthInfo preAuthInfo = PreAuthInfo.create(mTrustManager, mDevicePolicyManager,
- mSettingObserver, List.of(sensor),
- 0 /* userId */, promptInfo, TEST_PACKAGE_NAME,
- false /* checkDevicePolicyManager */, mContext, mBiometricCameraManager);
- assertThat(preAuthInfo.eligibleSensors).hasSize(0);
+ return sensor;
}
}