Loading core/java/android/hardware/biometrics/BiometricConstants.java +7 −0 Original line number Diff line number Diff line Loading @@ -162,6 +162,13 @@ public interface BiometricConstants { * @hide */ int BIOMETRIC_ERROR_POWER_PRESSED = 19; /** * Mandatory biometrics is not in effect. * @hide */ int BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE = 20; /** * This constant is only used by SystemUI. It notifies SystemUI that authentication was paused * because the authentication attempt was unsuccessful. Loading core/java/android/hardware/biometrics/BiometricManager.java +17 −1 Original line number Diff line number Diff line Loading @@ -79,6 +79,20 @@ public class BiometricManager { public static final int BIOMETRIC_ERROR_NO_HARDWARE = BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT; /** * Lockout error. * @hide */ public static final int BIOMETRIC_ERROR_LOCKOUT = BiometricConstants.BIOMETRIC_ERROR_LOCKOUT; /** * Mandatory biometrics is not effective. * @hide */ public static final int BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE = BiometricConstants.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE; /** * A security vulnerability has been discovered and the sensor is unavailable until a * security update has addressed this issue. This error can be received if for example, Loading Loading @@ -113,7 +127,9 @@ public class BiometricManager { BIOMETRIC_ERROR_HW_UNAVAILABLE, BIOMETRIC_ERROR_NONE_ENROLLED, BIOMETRIC_ERROR_NO_HARDWARE, BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED}) BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED, BIOMETRIC_ERROR_LOCKOUT, BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE}) @Retention(RetentionPolicy.SOURCE) public @interface BiometricError {} Loading services/core/java/com/android/server/biometrics/PreAuthInfo.java +11 −21 Original line number Diff line number Diff line Loading @@ -77,13 +77,15 @@ class PreAuthInfo { private final int mBiometricStrengthRequested; private final BiometricCameraManager mBiometricCameraManager; private final boolean mOnlyMandatoryBiometricsRequested; private final boolean mIsMandatoryBiometricsAuthentication; private PreAuthInfo(boolean biometricRequested, int biometricStrengthRequested, boolean credentialRequested, List<BiometricSensor> eligibleSensors, List<Pair<BiometricSensor, Integer>> ineligibleSensors, boolean credentialAvailable, PromptInfo promptInfo, int userId, Context context, BiometricCameraManager biometricCameraManager, boolean isOnlyMandatoryBiometricsRequested) { boolean isOnlyMandatoryBiometricsRequested, boolean isMandatoryBiometricsAuthentication) { mBiometricRequested = biometricRequested; mBiometricStrengthRequested = biometricStrengthRequested; mBiometricCameraManager = biometricCameraManager; Loading @@ -97,6 +99,7 @@ class PreAuthInfo { this.userId = userId; this.context = context; this.mOnlyMandatoryBiometricsRequested = isOnlyMandatoryBiometricsRequested; this.mIsMandatoryBiometricsAuthentication = isMandatoryBiometricsAuthentication; } static PreAuthInfo create(ITrustManager trustManager, Loading @@ -110,10 +113,12 @@ class PreAuthInfo { final boolean isOnlyMandatoryBiometricsRequested = promptInfo.getAuthenticators() == BiometricManager.Authenticators.MANDATORY_BIOMETRICS; boolean isMandatoryBiometricsAuthentication = false; if (dropCredentialFallback(promptInfo.getAuthenticators(), settingObserver.getMandatoryBiometricsEnabledAndRequirementsSatisfiedForUser( userId), trustManager)) { isMandatoryBiometricsAuthentication = true; promptInfo.setAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG); promptInfo.setNegativeButtonText(context.getString(R.string.cancel)); } Loading Loading @@ -166,7 +171,8 @@ class PreAuthInfo { return new PreAuthInfo(biometricRequested, requestedStrength, credentialRequested, eligibleSensors, ineligibleSensors, credentialAvailable, promptInfo, userId, context, biometricCameraManager, isOnlyMandatoryBiometricsRequested); context, biometricCameraManager, isOnlyMandatoryBiometricsRequested, isMandatoryBiometricsAuthentication); } private static boolean dropCredentialFallback(int authenticators, Loading Loading @@ -387,25 +393,6 @@ class PreAuthInfo { status = CREDENTIAL_NOT_ENROLLED; } } } else if (Flags.mandatoryBiometrics() && mOnlyMandatoryBiometricsRequested) { if (!eligibleSensors.isEmpty()) { for (BiometricSensor sensor : eligibleSensors) { modality |= sensor.modality; } if (modality == TYPE_FACE && cameraPrivacyEnabled) { // If the only modality requested is face, credential is unavailable, // and the face sensor privacy is enabled then return // BIOMETRIC_SENSOR_PRIVACY_ENABLED. // // Note: This sensor will not be eligible for calls to authenticate. status = BIOMETRIC_SENSOR_PRIVACY_ENABLED; } else { status = AUTHENTICATOR_OK; } } else { status = MANDATORY_BIOMETRIC_UNAVAILABLE_ERROR; } } else if (mBiometricRequested) { if (!eligibleSensors.isEmpty()) { for (BiometricSensor sensor : eligibleSensors) { Loading Loading @@ -434,6 +421,9 @@ class PreAuthInfo { } else if (credentialRequested) { modality |= TYPE_CREDENTIAL; status = credentialAvailable ? AUTHENTICATOR_OK : CREDENTIAL_NOT_ENROLLED; } else if (Flags.mandatoryBiometrics() && mOnlyMandatoryBiometricsRequested && !mIsMandatoryBiometricsAuthentication) { status = MANDATORY_BIOMETRIC_UNAVAILABLE_ERROR; } else { // This should not be possible via the public API surface and is here mainly for // "correctness". An exception should have been thrown before getting here. Loading services/core/java/com/android/server/biometrics/Utils.java +10 −1 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_NOT_ENROLLED; import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_NO_HARDWARE; import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_SENSOR_PRIVACY_ENABLED; import static com.android.server.biometrics.PreAuthInfo.CREDENTIAL_NOT_ENROLLED; import static com.android.server.biometrics.PreAuthInfo.MANDATORY_BIOMETRIC_UNAVAILABLE_ERROR; import android.annotation.NonNull; import android.annotation.Nullable; Loading @@ -48,6 +49,7 @@ import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.BiometricManager; import android.hardware.biometrics.BiometricPrompt; import android.hardware.biometrics.BiometricPrompt.AuthenticationResultType; import android.hardware.biometrics.Flags; import android.hardware.biometrics.IBiometricService; import android.hardware.biometrics.PromptInfo; import android.hardware.biometrics.SensorProperties; Loading Loading @@ -309,11 +311,16 @@ public class Utils { break; case BiometricConstants.BIOMETRIC_ERROR_LOCKOUT: case BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT: biometricManagerCode = BiometricManager.BIOMETRIC_SUCCESS; biometricManagerCode = Flags.mandatoryBiometrics() ? BiometricManager.BIOMETRIC_ERROR_LOCKOUT : BiometricManager.BIOMETRIC_SUCCESS; break; case BiometricConstants.BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED: biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE; break; case BiometricConstants.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE: biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE; break; default: Slog.e(BiometricService.TAG, "Unhandled result code: " + biometricConstantsCode); biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE; Loading Loading @@ -375,6 +382,8 @@ public class Utils { return BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT; case BIOMETRIC_SENSOR_PRIVACY_ENABLED: return BiometricConstants.BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED; case MANDATORY_BIOMETRIC_UNAVAILABLE_ERROR: return BiometricConstants.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE; case BIOMETRIC_DISABLED_BY_DEVICE_POLICY: case BIOMETRIC_HARDWARE_NOT_DETECTED: case BIOMETRIC_NOT_ENABLED_FOR_APPS: Loading services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java +33 −2 Original line number Diff line number Diff line Loading @@ -79,6 +79,7 @@ import android.os.IBinder; import android.os.RemoteException; import android.os.UserManager; import android.platform.test.annotations.Presubmit; import android.platform.test.annotations.RequiresFlagsDisabled; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; Loading Loading @@ -1488,15 +1489,30 @@ public class BiometricServiceTest { } @Test @RequiresFlagsDisabled(Flags.FLAG_MANDATORY_BIOMETRICS) public void testCanAuthenticate_whenLockoutTimed() throws Exception { testCanAuthenticate_whenLockedOut(LockoutTracker.LOCKOUT_TIMED); } @Test @RequiresFlagsDisabled(Flags.FLAG_MANDATORY_BIOMETRICS) public void testCanAuthenticate_whenLockoutPermanent() throws Exception { testCanAuthenticate_whenLockedOut(LockoutTracker.LOCKOUT_PERMANENT); } @Test @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS) public void testCanAuthenticate_whenLockoutTimed_returnsLockoutError() throws Exception { testCanAuthenticate_whenLockedOut_returnLockoutError(LockoutTracker.LOCKOUT_TIMED); } @Test @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS) public void testCanAuthenticate_whenLockoutPermanent_returnsLockoutError() throws Exception { testCanAuthenticate_whenLockedOut_returnLockoutError(LockoutTracker.LOCKOUT_PERMANENT); } @RequiresFlagsDisabled(Flags.FLAG_MANDATORY_BIOMETRICS) private void testCanAuthenticate_whenLockedOut(@LockoutTracker.LockoutMode int lockoutMode) throws Exception { // When only biometric is requested, and sensor is strong enough Loading @@ -1510,6 +1526,21 @@ public class BiometricServiceTest { invokeCanAuthenticate(mBiometricService, Authenticators.BIOMETRIC_STRONG)); } @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS) private void testCanAuthenticate_whenLockedOut_returnLockoutError( @LockoutTracker.LockoutMode int lockoutMode) throws Exception { // When only biometric is requested, and sensor is strong enough setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG); when(mFingerprintAuthenticator.getLockoutModeForUser(anyInt())) .thenReturn(lockoutMode); // Lockout is not considered an error for BiometricManager#canAuthenticate assertEquals(BiometricManager.BIOMETRIC_ERROR_LOCKOUT, invokeCanAuthenticate(mBiometricService, Authenticators.BIOMETRIC_STRONG)); } @Test @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS) public void testCanAuthenticate_whenMandatoryBiometricsRequested() Loading @@ -1529,7 +1560,7 @@ public class BiometricServiceTest { when(mTrustManager.isInSignificantPlace()).thenReturn(true); assertEquals(BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE, assertEquals(BiometricManager.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE, invokeCanAuthenticate(mBiometricService, Authenticators.MANDATORY_BIOMETRICS)); } Loading Loading @@ -1572,7 +1603,7 @@ public class BiometricServiceTest { setupAuthForOnly(TYPE_CREDENTIAL, Authenticators.DEVICE_CREDENTIAL); assertEquals(BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE, assertEquals(BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE, invokeCanAuthenticate(mBiometricService, Authenticators.MANDATORY_BIOMETRICS)); when(mTrustManager.isInSignificantPlace()).thenReturn(true); Loading Loading
core/java/android/hardware/biometrics/BiometricConstants.java +7 −0 Original line number Diff line number Diff line Loading @@ -162,6 +162,13 @@ public interface BiometricConstants { * @hide */ int BIOMETRIC_ERROR_POWER_PRESSED = 19; /** * Mandatory biometrics is not in effect. * @hide */ int BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE = 20; /** * This constant is only used by SystemUI. It notifies SystemUI that authentication was paused * because the authentication attempt was unsuccessful. Loading
core/java/android/hardware/biometrics/BiometricManager.java +17 −1 Original line number Diff line number Diff line Loading @@ -79,6 +79,20 @@ public class BiometricManager { public static final int BIOMETRIC_ERROR_NO_HARDWARE = BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT; /** * Lockout error. * @hide */ public static final int BIOMETRIC_ERROR_LOCKOUT = BiometricConstants.BIOMETRIC_ERROR_LOCKOUT; /** * Mandatory biometrics is not effective. * @hide */ public static final int BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE = BiometricConstants.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE; /** * A security vulnerability has been discovered and the sensor is unavailable until a * security update has addressed this issue. This error can be received if for example, Loading Loading @@ -113,7 +127,9 @@ public class BiometricManager { BIOMETRIC_ERROR_HW_UNAVAILABLE, BIOMETRIC_ERROR_NONE_ENROLLED, BIOMETRIC_ERROR_NO_HARDWARE, BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED}) BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED, BIOMETRIC_ERROR_LOCKOUT, BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE}) @Retention(RetentionPolicy.SOURCE) public @interface BiometricError {} Loading
services/core/java/com/android/server/biometrics/PreAuthInfo.java +11 −21 Original line number Diff line number Diff line Loading @@ -77,13 +77,15 @@ class PreAuthInfo { private final int mBiometricStrengthRequested; private final BiometricCameraManager mBiometricCameraManager; private final boolean mOnlyMandatoryBiometricsRequested; private final boolean mIsMandatoryBiometricsAuthentication; private PreAuthInfo(boolean biometricRequested, int biometricStrengthRequested, boolean credentialRequested, List<BiometricSensor> eligibleSensors, List<Pair<BiometricSensor, Integer>> ineligibleSensors, boolean credentialAvailable, PromptInfo promptInfo, int userId, Context context, BiometricCameraManager biometricCameraManager, boolean isOnlyMandatoryBiometricsRequested) { boolean isOnlyMandatoryBiometricsRequested, boolean isMandatoryBiometricsAuthentication) { mBiometricRequested = biometricRequested; mBiometricStrengthRequested = biometricStrengthRequested; mBiometricCameraManager = biometricCameraManager; Loading @@ -97,6 +99,7 @@ class PreAuthInfo { this.userId = userId; this.context = context; this.mOnlyMandatoryBiometricsRequested = isOnlyMandatoryBiometricsRequested; this.mIsMandatoryBiometricsAuthentication = isMandatoryBiometricsAuthentication; } static PreAuthInfo create(ITrustManager trustManager, Loading @@ -110,10 +113,12 @@ class PreAuthInfo { final boolean isOnlyMandatoryBiometricsRequested = promptInfo.getAuthenticators() == BiometricManager.Authenticators.MANDATORY_BIOMETRICS; boolean isMandatoryBiometricsAuthentication = false; if (dropCredentialFallback(promptInfo.getAuthenticators(), settingObserver.getMandatoryBiometricsEnabledAndRequirementsSatisfiedForUser( userId), trustManager)) { isMandatoryBiometricsAuthentication = true; promptInfo.setAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG); promptInfo.setNegativeButtonText(context.getString(R.string.cancel)); } Loading Loading @@ -166,7 +171,8 @@ class PreAuthInfo { return new PreAuthInfo(biometricRequested, requestedStrength, credentialRequested, eligibleSensors, ineligibleSensors, credentialAvailable, promptInfo, userId, context, biometricCameraManager, isOnlyMandatoryBiometricsRequested); context, biometricCameraManager, isOnlyMandatoryBiometricsRequested, isMandatoryBiometricsAuthentication); } private static boolean dropCredentialFallback(int authenticators, Loading Loading @@ -387,25 +393,6 @@ class PreAuthInfo { status = CREDENTIAL_NOT_ENROLLED; } } } else if (Flags.mandatoryBiometrics() && mOnlyMandatoryBiometricsRequested) { if (!eligibleSensors.isEmpty()) { for (BiometricSensor sensor : eligibleSensors) { modality |= sensor.modality; } if (modality == TYPE_FACE && cameraPrivacyEnabled) { // If the only modality requested is face, credential is unavailable, // and the face sensor privacy is enabled then return // BIOMETRIC_SENSOR_PRIVACY_ENABLED. // // Note: This sensor will not be eligible for calls to authenticate. status = BIOMETRIC_SENSOR_PRIVACY_ENABLED; } else { status = AUTHENTICATOR_OK; } } else { status = MANDATORY_BIOMETRIC_UNAVAILABLE_ERROR; } } else if (mBiometricRequested) { if (!eligibleSensors.isEmpty()) { for (BiometricSensor sensor : eligibleSensors) { Loading Loading @@ -434,6 +421,9 @@ class PreAuthInfo { } else if (credentialRequested) { modality |= TYPE_CREDENTIAL; status = credentialAvailable ? AUTHENTICATOR_OK : CREDENTIAL_NOT_ENROLLED; } else if (Flags.mandatoryBiometrics() && mOnlyMandatoryBiometricsRequested && !mIsMandatoryBiometricsAuthentication) { status = MANDATORY_BIOMETRIC_UNAVAILABLE_ERROR; } else { // This should not be possible via the public API surface and is here mainly for // "correctness". An exception should have been thrown before getting here. Loading
services/core/java/com/android/server/biometrics/Utils.java +10 −1 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_NOT_ENROLLED; import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_NO_HARDWARE; import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_SENSOR_PRIVACY_ENABLED; import static com.android.server.biometrics.PreAuthInfo.CREDENTIAL_NOT_ENROLLED; import static com.android.server.biometrics.PreAuthInfo.MANDATORY_BIOMETRIC_UNAVAILABLE_ERROR; import android.annotation.NonNull; import android.annotation.Nullable; Loading @@ -48,6 +49,7 @@ import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.BiometricManager; import android.hardware.biometrics.BiometricPrompt; import android.hardware.biometrics.BiometricPrompt.AuthenticationResultType; import android.hardware.biometrics.Flags; import android.hardware.biometrics.IBiometricService; import android.hardware.biometrics.PromptInfo; import android.hardware.biometrics.SensorProperties; Loading Loading @@ -309,11 +311,16 @@ public class Utils { break; case BiometricConstants.BIOMETRIC_ERROR_LOCKOUT: case BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT: biometricManagerCode = BiometricManager.BIOMETRIC_SUCCESS; biometricManagerCode = Flags.mandatoryBiometrics() ? BiometricManager.BIOMETRIC_ERROR_LOCKOUT : BiometricManager.BIOMETRIC_SUCCESS; break; case BiometricConstants.BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED: biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE; break; case BiometricConstants.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE: biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE; break; default: Slog.e(BiometricService.TAG, "Unhandled result code: " + biometricConstantsCode); biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE; Loading Loading @@ -375,6 +382,8 @@ public class Utils { return BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT; case BIOMETRIC_SENSOR_PRIVACY_ENABLED: return BiometricConstants.BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED; case MANDATORY_BIOMETRIC_UNAVAILABLE_ERROR: return BiometricConstants.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE; case BIOMETRIC_DISABLED_BY_DEVICE_POLICY: case BIOMETRIC_HARDWARE_NOT_DETECTED: case BIOMETRIC_NOT_ENABLED_FOR_APPS: Loading
services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java +33 −2 Original line number Diff line number Diff line Loading @@ -79,6 +79,7 @@ import android.os.IBinder; import android.os.RemoteException; import android.os.UserManager; import android.platform.test.annotations.Presubmit; import android.platform.test.annotations.RequiresFlagsDisabled; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; Loading Loading @@ -1488,15 +1489,30 @@ public class BiometricServiceTest { } @Test @RequiresFlagsDisabled(Flags.FLAG_MANDATORY_BIOMETRICS) public void testCanAuthenticate_whenLockoutTimed() throws Exception { testCanAuthenticate_whenLockedOut(LockoutTracker.LOCKOUT_TIMED); } @Test @RequiresFlagsDisabled(Flags.FLAG_MANDATORY_BIOMETRICS) public void testCanAuthenticate_whenLockoutPermanent() throws Exception { testCanAuthenticate_whenLockedOut(LockoutTracker.LOCKOUT_PERMANENT); } @Test @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS) public void testCanAuthenticate_whenLockoutTimed_returnsLockoutError() throws Exception { testCanAuthenticate_whenLockedOut_returnLockoutError(LockoutTracker.LOCKOUT_TIMED); } @Test @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS) public void testCanAuthenticate_whenLockoutPermanent_returnsLockoutError() throws Exception { testCanAuthenticate_whenLockedOut_returnLockoutError(LockoutTracker.LOCKOUT_PERMANENT); } @RequiresFlagsDisabled(Flags.FLAG_MANDATORY_BIOMETRICS) private void testCanAuthenticate_whenLockedOut(@LockoutTracker.LockoutMode int lockoutMode) throws Exception { // When only biometric is requested, and sensor is strong enough Loading @@ -1510,6 +1526,21 @@ public class BiometricServiceTest { invokeCanAuthenticate(mBiometricService, Authenticators.BIOMETRIC_STRONG)); } @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS) private void testCanAuthenticate_whenLockedOut_returnLockoutError( @LockoutTracker.LockoutMode int lockoutMode) throws Exception { // When only biometric is requested, and sensor is strong enough setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG); when(mFingerprintAuthenticator.getLockoutModeForUser(anyInt())) .thenReturn(lockoutMode); // Lockout is not considered an error for BiometricManager#canAuthenticate assertEquals(BiometricManager.BIOMETRIC_ERROR_LOCKOUT, invokeCanAuthenticate(mBiometricService, Authenticators.BIOMETRIC_STRONG)); } @Test @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS) public void testCanAuthenticate_whenMandatoryBiometricsRequested() Loading @@ -1529,7 +1560,7 @@ public class BiometricServiceTest { when(mTrustManager.isInSignificantPlace()).thenReturn(true); assertEquals(BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE, assertEquals(BiometricManager.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE, invokeCanAuthenticate(mBiometricService, Authenticators.MANDATORY_BIOMETRICS)); } Loading Loading @@ -1572,7 +1603,7 @@ public class BiometricServiceTest { setupAuthForOnly(TYPE_CREDENTIAL, Authenticators.DEVICE_CREDENTIAL); assertEquals(BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE, assertEquals(BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE, invokeCanAuthenticate(mBiometricService, Authenticators.MANDATORY_BIOMETRICS)); when(mTrustManager.isInSignificantPlace()).thenReturn(true); Loading