Loading core/java/android/hardware/biometrics/BiometricConstants.java +6 −0 Original line number Diff line number Diff line Loading @@ -169,6 +169,12 @@ public interface BiometricConstants { */ int BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE = 20; /** * Biometrics is not allowed to verify in apps. * @hide */ int BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS = 21; /** * 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 +7 −0 Original line number Diff line number Diff line Loading @@ -93,6 +93,13 @@ public class BiometricManager { public static final int BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE = BiometricConstants.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE; /** * Biometrics is not allowed to verify in apps. * @hide */ public static final int BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS = BiometricConstants.BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS; /** * 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 services/core/java/com/android/server/biometrics/PreAuthInfo.java +8 −0 Original line number Diff line number Diff line Loading @@ -316,6 +316,7 @@ class PreAuthInfo { Pair<BiometricSensor, Integer> sensorNotEnrolled = null; Pair<BiometricSensor, Integer> sensorLockout = null; Pair<BiometricSensor, Integer> hardwareNotDetected = null; Pair<BiometricSensor, Integer> biometricAppNotAllowed = null; for (Pair<BiometricSensor, Integer> pair : ineligibleSensors) { final int status = pair.second; if (status == BIOMETRIC_LOCKOUT_TIMED || status == BIOMETRIC_LOCKOUT_PERMANENT) { Loading @@ -327,6 +328,9 @@ class PreAuthInfo { if (status == BIOMETRIC_HARDWARE_NOT_DETECTED) { hardwareNotDetected = pair; } if (status == BIOMETRIC_NOT_ENABLED_FOR_APPS) { biometricAppNotAllowed = pair; } } // If there is a sensor locked out, prioritize lockout over other sensor's error. Loading @@ -339,6 +343,10 @@ class PreAuthInfo { return hardwareNotDetected; } if (Flags.mandatoryBiometrics() && biometricAppNotAllowed != null) { return biometricAppNotAllowed; } // 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. Loading services/core/java/com/android/server/biometrics/Utils.java +7 −1 Original line number Diff line number Diff line Loading @@ -321,6 +321,9 @@ public class Utils { case BiometricConstants.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE: biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE; break; case BiometricConstants.BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS: biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS; break; default: Slog.e(BiometricService.TAG, "Unhandled result code: " + biometricConstantsCode); biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE; Loading Loading @@ -384,9 +387,12 @@ public class Utils { return BiometricConstants.BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED; case MANDATORY_BIOMETRIC_UNAVAILABLE_ERROR: return BiometricConstants.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE; case BIOMETRIC_NOT_ENABLED_FOR_APPS: if (Flags.mandatoryBiometrics()) { return BiometricConstants.BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS; } case BIOMETRIC_DISABLED_BY_DEVICE_POLICY: case BIOMETRIC_HARDWARE_NOT_DETECTED: case BIOMETRIC_NOT_ENABLED_FOR_APPS: default: return BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE; } Loading services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java +25 −2 Original line number Diff line number Diff line Loading @@ -558,7 +558,9 @@ public class BiometricServiceTest { waitForIdle(); verify(mReceiver1).onError( eq(BiometricAuthenticator.TYPE_NONE), eq(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE), eq(Flags.mandatoryBiometrics() ? BiometricConstants.BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS : BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE), eq(0 /* vendorCode */)); // Enrolled, not disabled in settings, user requires confirmation in settings Loading Loading @@ -1450,7 +1452,9 @@ public class BiometricServiceTest { } @Test public void testCanAuthenticate_whenBiometricsNotEnabledForApps() throws Exception { @RequiresFlagsDisabled(Flags.FLAG_MANDATORY_BIOMETRICS) public void testCanAuthenticate_whenBiometricsNotEnabledForApps_returnsHardwareUnavailable() throws Exception { setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG); when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt())).thenReturn(false); when(mTrustManager.isDeviceSecure(anyInt(), anyInt())) Loading @@ -1467,6 +1471,25 @@ public class BiometricServiceTest { invokeCanAuthenticate(mBiometricService, authenticators)); } @Test @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS) public void testCanAuthenticate_whenBiometricsNotEnabledForApps() throws Exception { setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG); when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt())).thenReturn(false); when(mTrustManager.isDeviceSecure(anyInt(), anyInt())) .thenReturn(true); // When only biometric is requested int authenticators = Authenticators.BIOMETRIC_STRONG; assertEquals(BiometricManager.BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS, invokeCanAuthenticate(mBiometricService, authenticators)); // When credential and biometric are requested authenticators = Authenticators.BIOMETRIC_STRONG | Authenticators.DEVICE_CREDENTIAL; assertEquals(BiometricManager.BIOMETRIC_SUCCESS, invokeCanAuthenticate(mBiometricService, authenticators)); } @Test public void testCanAuthenticate_whenNoBiometricSensor() throws Exception { mBiometricService = new BiometricService(mContext, mInjector, mBiometricHandlerProvider); Loading Loading
core/java/android/hardware/biometrics/BiometricConstants.java +6 −0 Original line number Diff line number Diff line Loading @@ -169,6 +169,12 @@ public interface BiometricConstants { */ int BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE = 20; /** * Biometrics is not allowed to verify in apps. * @hide */ int BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS = 21; /** * 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 +7 −0 Original line number Diff line number Diff line Loading @@ -93,6 +93,13 @@ public class BiometricManager { public static final int BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE = BiometricConstants.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE; /** * Biometrics is not allowed to verify in apps. * @hide */ public static final int BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS = BiometricConstants.BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS; /** * 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
services/core/java/com/android/server/biometrics/PreAuthInfo.java +8 −0 Original line number Diff line number Diff line Loading @@ -316,6 +316,7 @@ class PreAuthInfo { Pair<BiometricSensor, Integer> sensorNotEnrolled = null; Pair<BiometricSensor, Integer> sensorLockout = null; Pair<BiometricSensor, Integer> hardwareNotDetected = null; Pair<BiometricSensor, Integer> biometricAppNotAllowed = null; for (Pair<BiometricSensor, Integer> pair : ineligibleSensors) { final int status = pair.second; if (status == BIOMETRIC_LOCKOUT_TIMED || status == BIOMETRIC_LOCKOUT_PERMANENT) { Loading @@ -327,6 +328,9 @@ class PreAuthInfo { if (status == BIOMETRIC_HARDWARE_NOT_DETECTED) { hardwareNotDetected = pair; } if (status == BIOMETRIC_NOT_ENABLED_FOR_APPS) { biometricAppNotAllowed = pair; } } // If there is a sensor locked out, prioritize lockout over other sensor's error. Loading @@ -339,6 +343,10 @@ class PreAuthInfo { return hardwareNotDetected; } if (Flags.mandatoryBiometrics() && biometricAppNotAllowed != null) { return biometricAppNotAllowed; } // 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. Loading
services/core/java/com/android/server/biometrics/Utils.java +7 −1 Original line number Diff line number Diff line Loading @@ -321,6 +321,9 @@ public class Utils { case BiometricConstants.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE: biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE; break; case BiometricConstants.BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS: biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS; break; default: Slog.e(BiometricService.TAG, "Unhandled result code: " + biometricConstantsCode); biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE; Loading Loading @@ -384,9 +387,12 @@ public class Utils { return BiometricConstants.BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED; case MANDATORY_BIOMETRIC_UNAVAILABLE_ERROR: return BiometricConstants.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE; case BIOMETRIC_NOT_ENABLED_FOR_APPS: if (Flags.mandatoryBiometrics()) { return BiometricConstants.BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS; } case BIOMETRIC_DISABLED_BY_DEVICE_POLICY: case BIOMETRIC_HARDWARE_NOT_DETECTED: case BIOMETRIC_NOT_ENABLED_FOR_APPS: default: return BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE; } Loading
services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java +25 −2 Original line number Diff line number Diff line Loading @@ -558,7 +558,9 @@ public class BiometricServiceTest { waitForIdle(); verify(mReceiver1).onError( eq(BiometricAuthenticator.TYPE_NONE), eq(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE), eq(Flags.mandatoryBiometrics() ? BiometricConstants.BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS : BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE), eq(0 /* vendorCode */)); // Enrolled, not disabled in settings, user requires confirmation in settings Loading Loading @@ -1450,7 +1452,9 @@ public class BiometricServiceTest { } @Test public void testCanAuthenticate_whenBiometricsNotEnabledForApps() throws Exception { @RequiresFlagsDisabled(Flags.FLAG_MANDATORY_BIOMETRICS) public void testCanAuthenticate_whenBiometricsNotEnabledForApps_returnsHardwareUnavailable() throws Exception { setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG); when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt())).thenReturn(false); when(mTrustManager.isDeviceSecure(anyInt(), anyInt())) Loading @@ -1467,6 +1471,25 @@ public class BiometricServiceTest { invokeCanAuthenticate(mBiometricService, authenticators)); } @Test @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS) public void testCanAuthenticate_whenBiometricsNotEnabledForApps() throws Exception { setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG); when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt())).thenReturn(false); when(mTrustManager.isDeviceSecure(anyInt(), anyInt())) .thenReturn(true); // When only biometric is requested int authenticators = Authenticators.BIOMETRIC_STRONG; assertEquals(BiometricManager.BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS, invokeCanAuthenticate(mBiometricService, authenticators)); // When credential and biometric are requested authenticators = Authenticators.BIOMETRIC_STRONG | Authenticators.DEVICE_CREDENTIAL; assertEquals(BiometricManager.BIOMETRIC_SUCCESS, invokeCanAuthenticate(mBiometricService, authenticators)); } @Test public void testCanAuthenticate_whenNoBiometricSensor() throws Exception { mBiometricService = new BiometricService(mContext, mInjector, mBiometricHandlerProvider); Loading