diff options
| author | 2023-08-24 12:52:07 -0700 | |
|---|---|---|
| committer | 2023-08-24 12:52:07 -0700 | |
| commit | 4d226f3d28eceecbf1578ba66347b804aed93db1 (patch) | |
| tree | 5b0eef944ace80d28f9813a860dbbdcc3ba11adf | |
| parent | 7aafa2293df88477f3a1867c62b0ce55679f08f4 (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.java | 12 | ||||
| -rw-r--r-- | services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java | 120 |
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; } } |