Loading core/java/android/hardware/biometrics/BiometricManager.java +16 −0 Original line number Diff line number Diff line Loading @@ -137,6 +137,7 @@ public class BiometricManager { BIOMETRIC_WEAK, BIOMETRIC_CONVENIENCE, DEVICE_CREDENTIAL, MANDATORY_BIOMETRICS, }) @Retention(RetentionPolicy.SOURCE) @interface Types {} Loading Loading @@ -214,6 +215,21 @@ public class BiometricManager { */ int DEVICE_CREDENTIAL = 1 << 15; /** * The bit is used to request for mandatory biometrics. * * <p> The requirements to trigger mandatory biometrics are as follows: * 1. User must have enabled the toggle for mandatory biometrics is settings * 2. User must have enrollments for all {@link #BIOMETRIC_STRONG} sensors available * 3. The device must not be in a trusted location * </p> * * <p> If all the above conditions are satisfied, only {@link #BIOMETRIC_STRONG} sensors * will be eligible for authentication, and device credential fallback will be dropped. * @hide */ int MANDATORY_BIOMETRICS = 1 << 16; } /** Loading core/java/android/hardware/biometrics/BiometricPrompt.java +9 −4 Original line number Diff line number Diff line Loading @@ -794,10 +794,15 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan public void onDialogDismissed(int reason) { // Check the reason and invoke OnClickListener(s) if necessary if (reason == DISMISSED_REASON_NEGATIVE) { if (mNegativeButtonInfo != null) { mNegativeButtonInfo.executor.execute(() -> { mNegativeButtonInfo.listener.onClick(null, DialogInterface.BUTTON_NEGATIVE); mIsPromptShowing = false; }); } else { mAuthenticationCallback.onAuthenticationError(BIOMETRIC_ERROR_USER_CANCELED, null /* errString */); } } else if (reason == DISMISSED_REASON_CONTENT_VIEW_MORE_OPTIONS) { if (mContentViewMoreOptionsButtonInfo != null) { mContentViewMoreOptionsButtonInfo.executor.execute(() -> { Loading core/java/android/hardware/biometrics/PromptInfo.java +4 −0 Original line number Diff line number Diff line Loading @@ -195,6 +195,10 @@ public class PromptInfo implements Parcelable { return true; } else if (mContentView != null && isContentViewMoreOptionsButtonUsed()) { return true; } else if (Flags.mandatoryBiometrics() && (mAuthenticators & BiometricManager.Authenticators.MANDATORY_BIOMETRICS) != 0) { return true; } return false; } Loading core/java/android/provider/Settings.java +6 −0 Original line number Diff line number Diff line Loading @@ -11045,6 +11045,12 @@ public final class Settings { @Readable public static final String BIOMETRIC_APP_ENABLED = "biometric_app_enabled"; /** * Whether or not mandatory biometrics is enabled. * @hide */ public static final String MANDATORY_BIOMETRICS = "mandatory_biometrics"; /** * Whether or not active unlock triggers on wake. * @hide Loading core/tests/coretests/src/android/hardware/biometrics/BiometricPromptTest.java +20 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; Loading Loading @@ -209,6 +210,25 @@ public class BiometricPromptTest { "The number of list items exceeds "); } @Test public void testOnDialogDismissed_dialogDismissedNegative() throws RemoteException { final ArgumentCaptor<IBiometricServiceReceiver> biometricServiceReceiverCaptor = ArgumentCaptor.forClass(IBiometricServiceReceiver.class); final BiometricPrompt.AuthenticationCallback callback = mock(BiometricPrompt.AuthenticationCallback.class); mBiometricPrompt.authenticate(mCancellationSignal, mExecutor, callback); mLooper.dispatchAll(); verify(mService).authenticate(any(), anyLong(), anyInt(), biometricServiceReceiverCaptor.capture(), anyString(), any()); biometricServiceReceiverCaptor.getValue().onDialogDismissed( BiometricPrompt.DISMISSED_REASON_NEGATIVE); verify(callback).onAuthenticationError(BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED, null /* errString */); } private String generateRandomString(int charNum) { final Random random = new Random(); final StringBuilder longString = new StringBuilder(charNum); Loading Loading
core/java/android/hardware/biometrics/BiometricManager.java +16 −0 Original line number Diff line number Diff line Loading @@ -137,6 +137,7 @@ public class BiometricManager { BIOMETRIC_WEAK, BIOMETRIC_CONVENIENCE, DEVICE_CREDENTIAL, MANDATORY_BIOMETRICS, }) @Retention(RetentionPolicy.SOURCE) @interface Types {} Loading Loading @@ -214,6 +215,21 @@ public class BiometricManager { */ int DEVICE_CREDENTIAL = 1 << 15; /** * The bit is used to request for mandatory biometrics. * * <p> The requirements to trigger mandatory biometrics are as follows: * 1. User must have enabled the toggle for mandatory biometrics is settings * 2. User must have enrollments for all {@link #BIOMETRIC_STRONG} sensors available * 3. The device must not be in a trusted location * </p> * * <p> If all the above conditions are satisfied, only {@link #BIOMETRIC_STRONG} sensors * will be eligible for authentication, and device credential fallback will be dropped. * @hide */ int MANDATORY_BIOMETRICS = 1 << 16; } /** Loading
core/java/android/hardware/biometrics/BiometricPrompt.java +9 −4 Original line number Diff line number Diff line Loading @@ -794,10 +794,15 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan public void onDialogDismissed(int reason) { // Check the reason and invoke OnClickListener(s) if necessary if (reason == DISMISSED_REASON_NEGATIVE) { if (mNegativeButtonInfo != null) { mNegativeButtonInfo.executor.execute(() -> { mNegativeButtonInfo.listener.onClick(null, DialogInterface.BUTTON_NEGATIVE); mIsPromptShowing = false; }); } else { mAuthenticationCallback.onAuthenticationError(BIOMETRIC_ERROR_USER_CANCELED, null /* errString */); } } else if (reason == DISMISSED_REASON_CONTENT_VIEW_MORE_OPTIONS) { if (mContentViewMoreOptionsButtonInfo != null) { mContentViewMoreOptionsButtonInfo.executor.execute(() -> { Loading
core/java/android/hardware/biometrics/PromptInfo.java +4 −0 Original line number Diff line number Diff line Loading @@ -195,6 +195,10 @@ public class PromptInfo implements Parcelable { return true; } else if (mContentView != null && isContentViewMoreOptionsButtonUsed()) { return true; } else if (Flags.mandatoryBiometrics() && (mAuthenticators & BiometricManager.Authenticators.MANDATORY_BIOMETRICS) != 0) { return true; } return false; } Loading
core/java/android/provider/Settings.java +6 −0 Original line number Diff line number Diff line Loading @@ -11045,6 +11045,12 @@ public final class Settings { @Readable public static final String BIOMETRIC_APP_ENABLED = "biometric_app_enabled"; /** * Whether or not mandatory biometrics is enabled. * @hide */ public static final String MANDATORY_BIOMETRICS = "mandatory_biometrics"; /** * Whether or not active unlock triggers on wake. * @hide Loading
core/tests/coretests/src/android/hardware/biometrics/BiometricPromptTest.java +20 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; Loading Loading @@ -209,6 +210,25 @@ public class BiometricPromptTest { "The number of list items exceeds "); } @Test public void testOnDialogDismissed_dialogDismissedNegative() throws RemoteException { final ArgumentCaptor<IBiometricServiceReceiver> biometricServiceReceiverCaptor = ArgumentCaptor.forClass(IBiometricServiceReceiver.class); final BiometricPrompt.AuthenticationCallback callback = mock(BiometricPrompt.AuthenticationCallback.class); mBiometricPrompt.authenticate(mCancellationSignal, mExecutor, callback); mLooper.dispatchAll(); verify(mService).authenticate(any(), anyLong(), anyInt(), biometricServiceReceiverCaptor.capture(), anyString(), any()); biometricServiceReceiverCaptor.getValue().onDialogDismissed( BiometricPrompt.DISMISSED_REASON_NEGATIVE); verify(callback).onAuthenticationError(BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED, null /* errString */); } private String generateRandomString(int charNum) { final Random random = new Random(); final StringBuilder longString = new StringBuilder(charNum); Loading