diff options
16 files changed, 279 insertions, 168 deletions
diff --git a/core/java/android/hardware/biometrics/BiometricAuthenticator.java b/core/java/android/hardware/biometrics/BiometricAuthenticator.java index 0ec812fe0350..698876b9c59e 100644 --- a/core/java/android/hardware/biometrics/BiometricAuthenticator.java +++ b/core/java/android/hardware/biometrics/BiometricAuthenticator.java @@ -36,23 +36,30 @@ public interface BiometricAuthenticator { * @hide */ int TYPE_NONE = 0; + + /** + * Constant representing credential (PIN, pattern, or password). + * @hide + */ + int TYPE_CREDENTIAL = 1 << 0; + /** * Constant representing fingerprint. * @hide */ - int TYPE_FINGERPRINT = 1 << 0; + int TYPE_FINGERPRINT = 1 << 1; /** * Constant representing iris. * @hide */ - int TYPE_IRIS = 1 << 1; + int TYPE_IRIS = 1 << 2; /** * Constant representing face. * @hide */ - int TYPE_FACE = 1 << 2; + int TYPE_FACE = 1 << 3; /** * Container for biometric data diff --git a/core/java/android/hardware/biometrics/BiometricConstants.java b/core/java/android/hardware/biometrics/BiometricConstants.java index 27c04b407315..c8bf570e1bc8 100644 --- a/core/java/android/hardware/biometrics/BiometricConstants.java +++ b/core/java/android/hardware/biometrics/BiometricConstants.java @@ -134,6 +134,13 @@ public interface BiometricConstants { int BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL = 14; /** + * This constant is only used by SystemUI. It notifies SystemUI that authentication was paused + * because the authentication attempt was unsuccessful. + * @hide + */ + int BIOMETRIC_PAUSED_REJECTED = 100; + + /** * @hide */ @UnsupportedAppUsage diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java index cf86e25112d2..9c51b5246749 100644 --- a/core/java/android/hardware/biometrics/BiometricPrompt.java +++ b/core/java/android/hardware/biometrics/BiometricPrompt.java @@ -26,6 +26,8 @@ import android.annotation.RequiresPermission; import android.app.KeyguardManager; import android.content.Context; import android.content.DialogInterface; +import android.hardware.face.FaceManager; +import android.hardware.fingerprint.FingerprintManager; import android.os.Binder; import android.os.Bundle; import android.os.CancellationSignal; @@ -339,9 +341,23 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan } @Override - public void onError(int error, String message) throws RemoteException { + public void onError(int modality, int error, int vendorCode) throws RemoteException { mExecutor.execute(() -> { - mAuthenticationCallback.onAuthenticationError(error, message); + String errorMessage; + switch (modality) { + case TYPE_FACE: + errorMessage = FaceManager.getErrorString(mContext, error, vendorCode); + break; + + case TYPE_FINGERPRINT: + errorMessage = FingerprintManager.getErrorString(mContext, error, + vendorCode); + break; + + default: + errorMessage = ""; + } + mAuthenticationCallback.onAuthenticationError(error, errorMessage); }); } diff --git a/core/java/android/hardware/biometrics/IBiometricServiceReceiver.aidl b/core/java/android/hardware/biometrics/IBiometricServiceReceiver.aidl index 22ef33e86e17..c960049438f1 100644 --- a/core/java/android/hardware/biometrics/IBiometricServiceReceiver.aidl +++ b/core/java/android/hardware/biometrics/IBiometricServiceReceiver.aidl @@ -25,7 +25,7 @@ oneway interface IBiometricServiceReceiver { // Noties that authentication failed. void onAuthenticationFailed(); // Notify BiometricPrompt that an error has occurred. - void onError(int error, String message); + void onError(int modality, int error, int vendorCode); // Notifies that a biometric has been acquired. void onAcquired(int acquiredInfo, String message); // Notifies that the SystemUI dialog has been dismissed. diff --git a/core/java/android/hardware/biometrics/IBiometricServiceReceiverInternal.aidl b/core/java/android/hardware/biometrics/IBiometricServiceReceiverInternal.aidl index 66b6e896fc13..61310f302fe4 100644 --- a/core/java/android/hardware/biometrics/IBiometricServiceReceiverInternal.aidl +++ b/core/java/android/hardware/biometrics/IBiometricServiceReceiverInternal.aidl @@ -31,7 +31,7 @@ oneway interface IBiometricServiceReceiverInternal { void onAuthenticationFailed(); // Notify BiometricService than an error has occured. Forward to the correct receiver depending // on the cookie. - void onError(int cookie, int error, String message); + void onError(int cookie, int modality, int error, int vendorCode); // Notifies that a biometric has been acquired. void onAcquired(int acquiredInfo, String message); // Notifies that the SystemUI dialog has been dismissed. diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl index c8ba52a63151..23c6acc606fd 100644 --- a/core/java/com/android/internal/statusbar/IStatusBar.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl @@ -154,12 +154,12 @@ oneway interface IStatusBar // Used to show the authentication dialog (Biometrics, Device Credential) void showAuthenticationDialog(in Bundle bundle, IBiometricServiceReceiverInternal receiver, int biometricModality, boolean requireConfirmation, int userId, String opPackageName); - // Used to notify the authentication dialog that a biometric has been authenticated or rejected - void onBiometricAuthenticated(boolean authenticated, String failureReason); + // Used to notify the authentication dialog that a biometric has been authenticated + void onBiometricAuthenticated(); // Used to set a temporary message, e.g. fingerprint not recognized, finger moved too fast, etc void onBiometricHelp(String message); - // Used to set a message - the dialog will dismiss after a certain amount of time - void onBiometricError(int errorCode, String error); + // Used to show an error - the dialog will dismiss after a certain amount of time + void onBiometricError(int modality, int error, int vendorCode); // Used to hide the authentication dialog, e.g. when the application cancels authentication void hideAuthenticationDialog(); diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl index 659134adec78..499a4d2fb949 100644 --- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl @@ -104,12 +104,12 @@ interface IStatusBarService // Used to show the authentication dialog (Biometrics, Device Credential) void showAuthenticationDialog(in Bundle bundle, IBiometricServiceReceiverInternal receiver, int biometricModality, boolean requireConfirmation, int userId, String opPackageName); - // Used to notify the authentication dialog that a biometric has been authenticated or rejected - void onBiometricAuthenticated(boolean authenticated, String failureReason); + // Used to notify the authentication dialog that a biometric has been authenticated + void onBiometricAuthenticated(); // Used to set a temporary message, e.g. fingerprint not recognized, finger moved too fast, etc void onBiometricHelp(String message); - // Used to set a message - the dialog will dismiss after a certain amount of time - void onBiometricError(int errorCode, String error); + // Used to show an error - the dialog will dismiss after a certain amount of time + void onBiometricError(int modality, int error, int vendorCode); // Used to hide the authentication dialog, e.g. when the application cancels authentication void hideAuthenticationDialog(); } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java index cdc2623d34fd..b75873100025 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java @@ -16,6 +16,9 @@ package com.android.systemui.biometrics; +import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE; +import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; + import android.app.ActivityManager; import android.app.ActivityTaskManager; import android.app.IActivityTaskManager; @@ -27,6 +30,8 @@ import android.hardware.biometrics.Authenticator; import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.BiometricPrompt; import android.hardware.biometrics.IBiometricServiceReceiverInternal; +import android.hardware.face.FaceManager; +import android.hardware.fingerprint.FingerprintManager; import android.os.Bundle; import android.os.Handler; import android.os.Looper; @@ -34,6 +39,7 @@ import android.os.RemoteException; import android.util.Log; import android.view.WindowManager; +import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.os.SomeArgs; import com.android.systemui.SystemUI; @@ -229,15 +235,8 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks, } @Override - public void onBiometricAuthenticated(boolean authenticated, String failureReason) { - if (DEBUG) Log.d(TAG, "onBiometricAuthenticated: " + authenticated - + " reason: " + failureReason); - - if (authenticated) { - mCurrentDialog.onAuthenticationSucceeded(); - } else { - mCurrentDialog.onAuthenticationFailed(failureReason); - } + public void onBiometricAuthenticated() { + mCurrentDialog.onAuthenticationSucceeded(); } @Override @@ -247,16 +246,45 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks, mCurrentDialog.onHelp(message); } + private String getErrorString(int modality, int error, int vendorCode) { + switch (modality) { + case TYPE_FACE: + return FaceManager.getErrorString(mContext, error, vendorCode); + + case TYPE_FINGERPRINT: + return FingerprintManager.getErrorString(mContext, error, vendorCode); + + default: + return ""; + } + } + @Override - public void onBiometricError(int errorCode, String error) { - if (DEBUG) Log.d(TAG, "onBiometricError: " + errorCode + ", " + error); + public void onBiometricError(int modality, int error, int vendorCode) { + if (DEBUG) { + Log.d(TAG, String.format("onBiometricError(%d, %d, %d)", modality, error, vendorCode)); + } + + final boolean isLockout = (error == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT) + || (error == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT); + + // TODO(b/141025588): Create separate methods for handling hard and soft errors. + final boolean isSoftError = (error == BiometricConstants.BIOMETRIC_PAUSED_REJECTED + || error == BiometricConstants.BIOMETRIC_ERROR_TIMEOUT); - final boolean isLockout = errorCode == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT - || errorCode == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT; if (mCurrentDialog.isAllowDeviceCredentials() && isLockout) { + if (DEBUG) Log.d(TAG, "onBiometricError, lockout"); mCurrentDialog.animateToCredentialUI(); + } else if (isSoftError) { + final String errorMessage = (error == BiometricConstants.BIOMETRIC_PAUSED_REJECTED) + ? mContext.getString(R.string.biometric_not_recognized) + : getErrorString(modality, error, vendorCode); + if (DEBUG) Log.d(TAG, "onBiometricError, soft error: " + errorMessage); + mCurrentDialog.onAuthenticationFailed(errorMessage); } else { - mCurrentDialog.onError(error); + final String errorMessage = getErrorString(modality, error, vendorCode); + if (DEBUG) Log.d(TAG, "onBiometricError, hard error: " + errorMessage); + mCurrentDialog.onError(errorMessage); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java index d6a8f906197d..2b1c807c245a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java @@ -273,9 +273,9 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController< default void showAuthenticationDialog(Bundle bundle, IBiometricServiceReceiverInternal receiver, int biometricModality, boolean requireConfirmation, int userId, String opPackageName) { } - default void onBiometricAuthenticated(boolean authenticated, String failureReason) { } + default void onBiometricAuthenticated() { } default void onBiometricHelp(String message) { } - default void onBiometricError(int errorCode, String error) { } + default void onBiometricError(int modality, int error, int vendorCode) { } default void hideAuthenticationDialog() { } /** @@ -757,12 +757,9 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController< } @Override - public void onBiometricAuthenticated(boolean authenticated, String failureReason) { + public void onBiometricAuthenticated() { synchronized (mLock) { - SomeArgs args = SomeArgs.obtain(); - args.arg1 = authenticated; - args.arg2 = failureReason; - mHandler.obtainMessage(MSG_BIOMETRIC_AUTHENTICATED, args).sendToTarget(); + mHandler.obtainMessage(MSG_BIOMETRIC_AUTHENTICATED).sendToTarget(); } } @@ -774,9 +771,13 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController< } @Override - public void onBiometricError(int errorCode, String error) { + public void onBiometricError(int modality, int error, int vendorCode) { synchronized (mLock) { - mHandler.obtainMessage(MSG_BIOMETRIC_ERROR, errorCode, 0, error).sendToTarget(); + SomeArgs args = SomeArgs.obtain(); + args.argi1 = modality; + args.argi2 = error; + args.argi3 = vendorCode; + mHandler.obtainMessage(MSG_BIOMETRIC_ERROR, args).sendToTarget(); } } @@ -1045,13 +1046,9 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController< break; } case MSG_BIOMETRIC_AUTHENTICATED: { - SomeArgs someArgs = (SomeArgs) msg.obj; for (int i = 0; i < mCallbacks.size(); i++) { - mCallbacks.get(i).onBiometricAuthenticated( - (boolean) someArgs.arg1 /* authenticated */, - (String) someArgs.arg2 /* failureReason */); + mCallbacks.get(i).onBiometricAuthenticated(); } - someArgs.recycle(); break; } case MSG_BIOMETRIC_HELP: @@ -1060,9 +1057,15 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController< } break; case MSG_BIOMETRIC_ERROR: + SomeArgs someArgs = (SomeArgs) msg.obj; for (int i = 0; i < mCallbacks.size(); i++) { - mCallbacks.get(i).onBiometricError(msg.arg1, (String) msg.obj); + mCallbacks.get(i).onBiometricError( + someArgs.argi1 /* modality */, + someArgs.argi2 /* error */, + someArgs.argi3 /* vendorCode */ + ); } + someArgs.recycle(); break; case MSG_BIOMETRIC_HIDE: for (int i = 0; i < mCallbacks.size(); i++) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java index e1eb3b0c81b2..b089b740fc47 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java @@ -38,15 +38,18 @@ import android.content.Context; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.hardware.biometrics.Authenticator; +import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.BiometricPrompt; import android.hardware.biometrics.IBiometricServiceReceiverInternal; +import android.hardware.face.FaceManager; import android.os.Bundle; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableContext; import android.testing.TestableLooper.RunWithLooper; +import com.android.internal.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.phone.StatusBar; @@ -89,9 +92,9 @@ public class AuthControllerTest extends SysuiTestCase { when(context.getPackageManager()).thenReturn(mPackageManager); when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE)) - .thenReturn(true); + .thenReturn(true); when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) - .thenReturn(true); + .thenReturn(true); when(mDialog1.getOpPackageName()).thenReturn("Dialog1"); when(mDialog2.getOpPackageName()).thenReturn("Dialog2"); @@ -170,20 +173,34 @@ public class AuthControllerTest extends SysuiTestCase { @Test public void testOnAuthenticationSucceededInvoked_whenSystemRequested() { showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE); - mAuthController.onBiometricAuthenticated(true, null /* failureReason */); + mAuthController.onBiometricAuthenticated(); verify(mDialog1).onAuthenticationSucceeded(); } @Test - public void testOnAuthenticationFailedInvoked_whenSystemRequested() { + public void testOnAuthenticationFailedInvoked_whenBiometricRejected() { showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE); - final String failureReason = "failure reason"; - mAuthController.onBiometricAuthenticated(false, failureReason); + mAuthController.onBiometricError(BiometricAuthenticator.TYPE_NONE, + BiometricConstants.BIOMETRIC_PAUSED_REJECTED, + 0 /* vendorCode */); ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class); verify(mDialog1).onAuthenticationFailed(captor.capture()); - assertEquals(captor.getValue(), failureReason); + assertEquals(captor.getValue(), mContext.getString(R.string.biometric_not_recognized)); + } + + @Test + public void testOnAuthenticationFailedInvoked_whenBiometricTimedOut() { + showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE); + final int error = BiometricConstants.BIOMETRIC_ERROR_TIMEOUT; + final int vendorCode = 0; + mAuthController.onBiometricError(BiometricAuthenticator.TYPE_FACE, error, vendorCode); + + ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class); + verify(mDialog1).onAuthenticationFailed(captor.capture()); + + assertEquals(captor.getValue(), FaceManager.getErrorString(mContext, error, vendorCode)); } @Test @@ -199,27 +216,27 @@ public class AuthControllerTest extends SysuiTestCase { } @Test - public void testOnErrorInvoked_whenSystemRequested() { + public void testOnErrorInvoked_whenSystemRequested() throws Exception { showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE); final int error = 1; - final String errMessage = "error message"; - mAuthController.onBiometricError(error, errMessage); + final int vendorCode = 0; + mAuthController.onBiometricError(BiometricAuthenticator.TYPE_FACE, error, vendorCode); ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class); verify(mDialog1).onError(captor.capture()); - assertEquals(captor.getValue(), errMessage); + assertEquals(captor.getValue(), FaceManager.getErrorString(mContext, error, vendorCode)); } @Test public void testErrorLockout_whenCredentialAllowed_AnimatesToCredentialUI() { showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE); final int error = BiometricConstants.BIOMETRIC_ERROR_LOCKOUT; - final String errorString = "lockout"; + final int vendorCode = 0; when(mDialog1.isAllowDeviceCredentials()).thenReturn(true); - mAuthController.onBiometricError(error, errorString); + mAuthController.onBiometricError(BiometricAuthenticator.TYPE_FACE, error, vendorCode); verify(mDialog1, never()).onError(anyString()); verify(mDialog1).animateToCredentialUI(); } @@ -228,11 +245,11 @@ public class AuthControllerTest extends SysuiTestCase { public void testErrorLockoutPermanent_whenCredentialAllowed_AnimatesToCredentialUI() { showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE); final int error = BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT; - final String errorString = "lockout_permanent"; + final int vendorCode = 0; when(mDialog1.isAllowDeviceCredentials()).thenReturn(true); - mAuthController.onBiometricError(error, errorString); + mAuthController.onBiometricError(BiometricAuthenticator.TYPE_FACE, error, vendorCode); verify(mDialog1, never()).onError(anyString()); verify(mDialog1).animateToCredentialUI(); } @@ -241,12 +258,12 @@ public class AuthControllerTest extends SysuiTestCase { public void testErrorLockout_whenCredentialNotAllowed_sendsOnError() { showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE); final int error = BiometricConstants.BIOMETRIC_ERROR_LOCKOUT; - final String errorString = "lockout"; + final int vendorCode = 0; when(mDialog1.isAllowDeviceCredentials()).thenReturn(false); - mAuthController.onBiometricError(error, errorString); - verify(mDialog1).onError(eq(errorString)); + mAuthController.onBiometricError(BiometricAuthenticator.TYPE_FACE, error, vendorCode); + verify(mDialog1).onError(eq(FaceManager.getErrorString(mContext, error, vendorCode))); verify(mDialog1, never()).animateToCredentialUI(); } @@ -254,12 +271,12 @@ public class AuthControllerTest extends SysuiTestCase { public void testErrorLockoutPermanent_whenCredentialNotAllowed_sendsOnError() { showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE); final int error = BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT; - final String errorString = "lockout_permanent"; + final int vendorCode = 0; when(mDialog1.isAllowDeviceCredentials()).thenReturn(false); - mAuthController.onBiometricError(error, errorString); - verify(mDialog1).onError(eq(errorString)); + mAuthController.onBiometricError(BiometricAuthenticator.TYPE_FACE, error, vendorCode); + verify(mDialog1).onError(eq(FaceManager.getErrorString(mContext, error, vendorCode))); verify(mDialog1, never()).animateToCredentialUI(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java index 1bd01e166ddb..ccb754cc240d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java @@ -379,10 +379,9 @@ public class CommandQueueTest extends SysuiTestCase { @Test public void testOnBiometricAuthenticated() { - String failureReason = "test_failure_reason"; - mCommandQueue.onBiometricAuthenticated(true /* authenticated */, failureReason); + mCommandQueue.onBiometricAuthenticated(); waitForIdleSync(); - verify(mCallbacks).onBiometricAuthenticated(eq(true), eq(failureReason)); + verify(mCallbacks).onBiometricAuthenticated(); } @Test @@ -395,11 +394,12 @@ public class CommandQueueTest extends SysuiTestCase { @Test public void testOnBiometricError() { - final int errorCode = 1; - String errorMessage = "test_error_message"; - mCommandQueue.onBiometricError(errorCode, errorMessage); + final int modality = 1; + final int error = 2; + final int vendorCode = 3; + mCommandQueue.onBiometricError(modality, error, vendorCode); waitForIdleSync(); - verify(mCallbacks).onBiometricError(eq(errorCode), eq(errorMessage)); + verify(mCallbacks).onBiometricError(eq(modality), eq(error), eq(vendorCode)); } @Test diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java index 2b45f1970ef4..619c21e7646b 100644 --- a/services/core/java/com/android/server/biometrics/BiometricService.java +++ b/services/core/java/com/android/server/biometrics/BiometricService.java @@ -168,7 +168,7 @@ public class BiometricService extends SystemService { byte[] mTokenEscrow; // Waiting for SystemUI to complete animation int mErrorEscrow; - String mErrorStringEscrow; + int mVendorCodeEscrow; // Timestamp when authentication started private long mStartTimeMs; @@ -254,7 +254,7 @@ public class BiometricService extends SystemService { } case MSG_ON_AUTHENTICATION_REJECTED: { - handleAuthenticationRejected((String) msg.obj /* failureReason */); + handleAuthenticationRejected(); break; } @@ -262,8 +262,9 @@ public class BiometricService extends SystemService { SomeArgs args = (SomeArgs) msg.obj; handleOnError( args.argi1 /* cookie */, - args.argi2 /* error */, - (String) args.arg1 /* message */); + args.argi2 /* modality */, + args.argi3 /* error */, + args.argi4 /* vendorCode */); args.recycle(); break; } @@ -323,7 +324,12 @@ public class BiometricService extends SystemService { } case MSG_ON_AUTHENTICATION_TIMED_OUT: { - handleAuthenticationTimedOut((String) msg.obj /* errorMessage */); + SomeArgs args = (SomeArgs) msg.obj; + handleAuthenticationTimedOut( + args.argi1 /* modality */, + args.argi2 /* error */, + args.argi3 /* vendorCode */); + args.recycle(); break; } @@ -515,23 +521,28 @@ public class BiometricService extends SystemService { @Override public void onAuthenticationFailed() throws RemoteException { - String failureReason = getContext().getString(R.string.biometric_not_recognized); - Slog.v(TAG, "onAuthenticationFailed: " + failureReason); - mHandler.obtainMessage(MSG_ON_AUTHENTICATION_REJECTED, failureReason).sendToTarget(); + Slog.v(TAG, "onAuthenticationFailed"); + mHandler.obtainMessage(MSG_ON_AUTHENTICATION_REJECTED).sendToTarget(); } @Override - public void onError(int cookie, int error, String message) throws RemoteException { + public void onError(int cookie, int modality, int error, int vendorCode) + throws RemoteException { // Determine if error is hard or soft error. Certain errors (such as TIMEOUT) are // soft errors and we should allow the user to try authenticating again instead of // dismissing BiometricPrompt. if (error == BiometricConstants.BIOMETRIC_ERROR_TIMEOUT) { - mHandler.obtainMessage(MSG_ON_AUTHENTICATION_TIMED_OUT, message).sendToTarget(); + SomeArgs args = SomeArgs.obtain(); + args.argi1 = modality; + args.argi2 = error; + args.argi3 = vendorCode; + mHandler.obtainMessage(MSG_ON_AUTHENTICATION_TIMED_OUT, args).sendToTarget(); } else { SomeArgs args = SomeArgs.obtain(); args.argi1 = cookie; - args.argi2 = error; - args.arg1 = message; + args.argi2 = modality; + args.argi3 = error; + args.argi4 = vendorCode; mHandler.obtainMessage(MSG_ON_ERROR, args).sendToTarget(); } } @@ -1088,14 +1099,14 @@ public class BiometricService extends SystemService { // Notify SysUI that the biometric has been authenticated. SysUI already knows // the implicit/explicit state and will react accordingly. - mStatusBarService.onBiometricAuthenticated(true, null /* failureReason */); + mStatusBarService.onBiometricAuthenticated(); } catch (RemoteException e) { Slog.e(TAG, "Remote exception", e); } } - private void handleAuthenticationRejected(String failureReason) { - Slog.v(TAG, "handleAuthenticationRejected: " + failureReason); + private void handleAuthenticationRejected() { + Slog.v(TAG, "handleAuthenticationRejected()"); try { // Should never happen, log this to catch bad HAL behavior (e.g. auth succeeded // after user dismissed/canceled dialog). @@ -1104,7 +1115,8 @@ public class BiometricService extends SystemService { return; } - mStatusBarService.onBiometricAuthenticated(false, failureReason); + mStatusBarService.onBiometricError(TYPE_NONE, + BiometricConstants.BIOMETRIC_PAUSED_REJECTED, 0 /* vendorCode */); // TODO: This logic will need to be updated if BP is multi-modal if ((mCurrentAuthSession.mModality & TYPE_FACE) != 0) { @@ -1119,8 +1131,9 @@ public class BiometricService extends SystemService { } } - private void handleAuthenticationTimedOut(String message) { - Slog.v(TAG, "handleAuthenticationTimedOut: " + message); + private void handleAuthenticationTimedOut(int modality, int error, int vendorCode) { + Slog.v(TAG, String.format("handleAuthenticationTimedOut(%d, %d, %d)", modality, error, + vendorCode)); try { // Should never happen, log this to catch bad HAL behavior (e.g. auth succeeded // after user dismissed/canceled dialog). @@ -1129,14 +1142,14 @@ public class BiometricService extends SystemService { return; } - mStatusBarService.onBiometricAuthenticated(false, message); + mStatusBarService.onBiometricError(modality, error, vendorCode); mCurrentAuthSession.mState = STATE_AUTH_PAUSED; } catch (RemoteException e) { Slog.e(TAG, "Remote exception", e); } } - private void handleOnError(int cookie, int error, String message) { + private void handleOnError(int cookie, int modality, int error, int vendorCode) { Slog.d(TAG, "handleOnError: " + error + " cookie: " + cookie); // Errors can either be from the current auth session or the pending auth session. // The pending auth session may receive errors such as ERROR_LOCKOUT before @@ -1147,7 +1160,7 @@ public class BiometricService extends SystemService { try { if (mCurrentAuthSession != null && mCurrentAuthSession.containsCookie(cookie)) { mCurrentAuthSession.mErrorEscrow = error; - mCurrentAuthSession.mErrorStringEscrow = message; + mCurrentAuthSession.mVendorCodeEscrow = vendorCode; if (mCurrentAuthSession.mState == STATE_AUTH_STARTED) { final boolean errorLockout = error == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT @@ -1155,20 +1168,20 @@ public class BiometricService extends SystemService { if (mCurrentAuthSession.isAllowDeviceCredential() && errorLockout) { // SystemUI handles transition from biometric to device credential. mCurrentAuthSession.mState = STATE_SHOWING_DEVICE_CREDENTIAL; - mStatusBarService.onBiometricError(error, message); + mStatusBarService.onBiometricError(modality, error, vendorCode); } else { mCurrentAuthSession.mState = STATE_ERROR_PENDING_SYSUI; if (error == BiometricConstants.BIOMETRIC_ERROR_CANCELED) { mStatusBarService.hideAuthenticationDialog(); } else { - mStatusBarService.onBiometricError(error, message); + mStatusBarService.onBiometricError(modality, error, vendorCode); } } } else if (mCurrentAuthSession.mState == STATE_AUTH_PAUSED) { // In the "try again" state, we should forward canceled errors to // the client and and clean up. The only error we should get here is // ERROR_CANCELED due to another client kicking us out. - mCurrentAuthSession.mClientReceiver.onError(error, message); + mCurrentAuthSession.mClientReceiver.onError(modality, error, vendorCode); mStatusBarService.hideAuthenticationDialog(); mCurrentAuthSession = null; } else if (mCurrentAuthSession.mState == STATE_SHOWING_DEVICE_CREDENTIAL) { @@ -1204,7 +1217,7 @@ public class BiometricService extends SystemService { mCurrentAuthSession.mUserId, mCurrentAuthSession.mOpPackageName); } else { - mPendingAuthSession.mClientReceiver.onError(error, message); + mPendingAuthSession.mClientReceiver.onError(modality, error, vendorCode); mPendingAuthSession = null; } } else { @@ -1268,8 +1281,10 @@ public class BiometricService extends SystemService { case BiometricPrompt.DISMISSED_REASON_USER_CANCEL: mCurrentAuthSession.mClientReceiver.onError( + mCurrentAuthSession.mModality, BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED, - getContext().getString(R.string.biometric_error_user_canceled)); + 0 /* vendorCode */ + ); // Cancel authentication. Skip the token/package check since we are cancelling // from system server. The interface is permission protected so this is fine. cancelInternal(null /* token */, null /* package */, false /* fromClient */); @@ -1277,8 +1292,11 @@ public class BiometricService extends SystemService { case BiometricPrompt.DISMISSED_REASON_SERVER_REQUESTED: case BiometricPrompt.DISMISSED_REASON_ERROR: - mCurrentAuthSession.mClientReceiver.onError(mCurrentAuthSession.mErrorEscrow, - mCurrentAuthSession.mErrorStringEscrow); + mCurrentAuthSession.mClientReceiver.onError( + mCurrentAuthSession.mModality, + mCurrentAuthSession.mErrorEscrow, + mCurrentAuthSession.mVendorCodeEscrow + ); break; default: @@ -1413,23 +1431,7 @@ public class BiometricService extends SystemService { } else if (error != BiometricConstants.BIOMETRIC_SUCCESS) { // Check for errors, notify callback, and return try { - final String hardwareUnavailable = - getContext().getString(R.string.biometric_error_hw_unavailable); - switch (error) { - case BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT: - receiver.onError(error, hardwareUnavailable); - break; - case BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE: - receiver.onError(error, hardwareUnavailable); - break; - case BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS: - receiver.onError(error, - getErrorString(modality, error, 0 /* vendorCode */)); - break; - default: - Slog.e(TAG, "Unhandled error"); - break; - } + receiver.onError(modality, error, 0 /* vendorCode */); } catch (RemoteException e) { Slog.e(TAG, "Unable to send error", e); } @@ -1521,11 +1523,10 @@ public class BiometricService extends SystemService { try { // Send error to client mCurrentAuthSession.mClientReceiver.onError( + mCurrentAuthSession.mModality, BiometricConstants.BIOMETRIC_ERROR_CANCELED, - getContext().getString( - com.android.internal.R.string.biometric_error_user_canceled) + 0 /* vendorCode */ ); - mCurrentAuthSession = null; mStatusBarService.hideAuthenticationDialog(); } catch (RemoteException e) { diff --git a/services/core/java/com/android/server/biometrics/face/FaceService.java b/services/core/java/com/android/server/biometrics/face/FaceService.java index de6ee8b20c0e..a0c8e2325f77 100644 --- a/services/core/java/com/android/server/biometrics/face/FaceService.java +++ b/services/core/java/com/android/server/biometrics/face/FaceService.java @@ -20,6 +20,7 @@ import static android.Manifest.permission.INTERACT_ACROSS_USERS; import static android.Manifest.permission.MANAGE_BIOMETRIC; import static android.Manifest.permission.RESET_FACE_LOCKOUT; import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL; +import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE; import android.app.ActivityManager; import android.app.AppOpsManager; @@ -752,8 +753,7 @@ public class FaceService extends BiometricServiceBase { public void onError(long deviceId, int error, int vendorCode, int cookie) throws RemoteException { if (getWrapperReceiver() != null) { - getWrapperReceiver().onError(cookie, error, - FaceManager.getErrorString(getContext(), error, vendorCode)); + getWrapperReceiver().onError(cookie, TYPE_FACE, error, vendorCode); } } } diff --git a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java index d59fcbf7c4d8..44797ad97b37 100644 --- a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java @@ -22,6 +22,7 @@ import static android.Manifest.permission.MANAGE_FINGERPRINT; import static android.Manifest.permission.RESET_FINGERPRINT_LOCKOUT; import static android.Manifest.permission.USE_BIOMETRIC; import static android.Manifest.permission.USE_FINGERPRINT; +import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; import android.app.ActivityManager; import android.app.AlarmManager; @@ -480,8 +481,7 @@ public class FingerprintService extends BiometricServiceBase { public void onError(long deviceId, int error, int vendorCode, int cookie) throws RemoteException { if (getWrapperReceiver() != null) { - getWrapperReceiver().onError(cookie, error, - FingerprintManager.getErrorString(getContext(), error, vendorCode)); + getWrapperReceiver().onError(cookie, TYPE_FINGERPRINT, error, vendorCode); } } } diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index 65bb2342d504..6f927a5465f0 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -623,11 +623,11 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D } @Override - public void onBiometricAuthenticated(boolean authenticated, String failureReason) { + public void onBiometricAuthenticated() { enforceBiometricDialog(); if (mBar != null) { try { - mBar.onBiometricAuthenticated(authenticated, failureReason); + mBar.onBiometricAuthenticated(); } catch (RemoteException ex) { } } @@ -645,11 +645,11 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D } @Override - public void onBiometricError(int errorCode, String error) { + public void onBiometricError(int modality, int error, int vendorCode) { enforceBiometricDialog(); if (mBar != null) { try { - mBar.onBiometricError(errorCode, error); + mBar.onBiometricError(modality, error, vendorCode); } catch (RemoteException ex) { } } diff --git a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java index dd86123ec423..ec47a959de30 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java @@ -143,7 +143,9 @@ public class BiometricServiceTest { false /* allowDeviceCredential */); waitForIdle(); verify(mReceiver1).onError( - eq(BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT), eq(ERROR_HW_UNAVAILABLE)); + eq(BiometricAuthenticator.TYPE_NONE), + eq(BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT), + eq(0 /* vendorCode */)); } @Test @@ -158,7 +160,9 @@ public class BiometricServiceTest { false /* allowDeviceCredential */); waitForIdle(); verify(mReceiver1).onError( - eq(BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS), any()); + eq(BiometricAuthenticator.TYPE_FINGERPRINT), + eq(BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS), + eq(0 /* vendorCode */)); } @Test @@ -175,7 +179,9 @@ public class BiometricServiceTest { false /* allowDeviceCredential */); waitForIdle(); verify(mReceiver1).onError( - eq(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE), eq(ERROR_HW_UNAVAILABLE)); + eq(BiometricAuthenticator.TYPE_NONE), + eq(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE), + eq(0 /* vendorCode */)); } @Test @@ -194,7 +200,9 @@ public class BiometricServiceTest { false /* allowDeviceCredential */); waitForIdle(); verify(mReceiver1).onError( - eq(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE), eq(ERROR_HW_UNAVAILABLE)); + eq(BiometricAuthenticator.TYPE_NONE), + eq(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE), + eq(0 /* vendorCode */)); // Enrolled, not disabled in settings, user requires confirmation in settings resetReceiver(); @@ -204,7 +212,7 @@ public class BiometricServiceTest { invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */, false /* allowDeviceCredential */); waitForIdle(); - verify(mReceiver1, never()).onError(anyInt(), any(String.class)); + verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt()); verify(mBiometricService.mAuthenticators.get(0).impl).prepareForAuthentication( eq(true) /* requireConfirmation */, any(IBinder.class), @@ -254,7 +262,7 @@ public class BiometricServiceTest { // Invokes <Modality>Service#prepareForAuthentication ArgumentCaptor<Integer> cookieCaptor = ArgumentCaptor.forClass(Integer.class); - verify(mReceiver1, never()).onError(anyInt(), any(String.class)); + verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt()); verify(mBiometricService.mAuthenticators.get(0).impl).prepareForAuthentication( anyBoolean() /* requireConfirmation */, any(IBinder.class), @@ -297,8 +305,7 @@ public class BiometricServiceTest { assertEquals(mBiometricService.mCurrentAuthSession.mState, BiometricService.STATE_AUTHENTICATED_PENDING_SYSUI); // Notify SystemUI hardware authenticated - verify(mBiometricService.mStatusBarService).onBiometricAuthenticated( - eq(true) /* authenticated */, eq(null) /* failureReason */); + verify(mBiometricService.mStatusBarService).onBiometricAuthenticated(); // SystemUI sends callback with dismissed reason mBiometricService.mInternalReceiver.onDialogDismissed( @@ -369,8 +376,10 @@ public class BiometricServiceTest { mBiometricService.mInternalReceiver.onAuthenticationFailed(); waitForIdle(); - verify(mBiometricService.mStatusBarService) - .onBiometricAuthenticated(eq(false), eq(ERROR_NOT_RECOGNIZED)); + verify(mBiometricService.mStatusBarService).onBiometricError( + eq(BiometricAuthenticator.TYPE_NONE), + eq(BiometricConstants.BIOMETRIC_PAUSED_REJECTED), + eq(0 /* vendorCode */)); verify(mReceiver1).onAuthenticationFailed(); assertEquals(mBiometricService.mCurrentAuthSession.mState, BiometricService.STATE_AUTH_PAUSED); @@ -386,8 +395,10 @@ public class BiometricServiceTest { mBiometricService.mInternalReceiver.onAuthenticationFailed(); waitForIdle(); - verify(mBiometricService.mStatusBarService) - .onBiometricAuthenticated(eq(false), eq(ERROR_NOT_RECOGNIZED)); + verify(mBiometricService.mStatusBarService).onBiometricError( + eq(BiometricAuthenticator.TYPE_NONE), + eq(BiometricConstants.BIOMETRIC_PAUSED_REJECTED), + eq(0 /* vendorCode */)); verify(mReceiver1).onAuthenticationFailed(); assertEquals(mBiometricService.mCurrentAuthSession.mState, BiometricService.STATE_AUTH_STARTED); @@ -412,15 +423,15 @@ public class BiometricServiceTest { BiometricService.STATE_AUTH_STARTED); mBiometricService.mInternalReceiver.onError( getCookieForCurrentSession(mBiometricService.mCurrentAuthSession), - BiometricConstants.BIOMETRIC_ERROR_CANCELED, ERROR_CANCELED); + BiometricAuthenticator.TYPE_FINGERPRINT, + BiometricConstants.BIOMETRIC_ERROR_CANCELED, 0 /* vendorCode */); waitForIdle(); // Auth session doesn't become null until SystemUI responds that the animation is completed assertNotNull(mBiometricService.mCurrentAuthSession); // ERROR_CANCELED is not sent until SystemUI responded that animation is completed - verify(mReceiver1, never()).onError( - anyInt(), anyString()); - verify(mReceiver2, never()).onError(anyInt(), any(String.class)); + verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt()); + verify(mReceiver2, never()).onError(anyInt(), anyInt(), anyInt()); // SystemUI dialog closed verify(mBiometricService.mStatusBarService).hideAuthenticationDialog(); @@ -430,8 +441,9 @@ public class BiometricServiceTest { .onDialogDismissed(BiometricPrompt.DISMISSED_REASON_SERVER_REQUESTED); waitForIdle(); verify(mReceiver1).onError( + eq(BiometricAuthenticator.TYPE_FINGERPRINT), eq(BiometricConstants.BIOMETRIC_ERROR_CANCELED), - eq(ERROR_CANCELED)); + eq(0 /* vendorCode */)); assertNull(mBiometricService.mCurrentAuthSession); } @@ -443,14 +455,17 @@ public class BiometricServiceTest { mBiometricService.mInternalReceiver.onError( getCookieForCurrentSession(mBiometricService.mCurrentAuthSession), + BiometricAuthenticator.TYPE_FACE, BiometricConstants.BIOMETRIC_ERROR_TIMEOUT, - ERROR_TIMEOUT); + 0 /* vendorCode */); waitForIdle(); assertEquals(mBiometricService.mCurrentAuthSession.mState, BiometricService.STATE_AUTH_PAUSED); - verify(mBiometricService.mStatusBarService) - .onBiometricAuthenticated(eq(false), eq(ERROR_TIMEOUT)); + verify(mBiometricService.mStatusBarService).onBiometricError( + eq(BiometricAuthenticator.TYPE_FACE), + eq(BiometricConstants.BIOMETRIC_ERROR_TIMEOUT), + eq(0 /* vendorCode */)); // Timeout does not count as fail as per BiometricPrompt documentation. verify(mReceiver1, never()).onAuthenticationFailed(); @@ -489,18 +504,21 @@ public class BiometricServiceTest { mBiometricService.mInternalReceiver.onError( getCookieForCurrentSession(mBiometricService.mCurrentAuthSession), + BiometricAuthenticator.TYPE_FACE, BiometricConstants.BIOMETRIC_ERROR_TIMEOUT, - ERROR_TIMEOUT); + 0 /* vendorCode */); mBiometricService.mInternalReceiver.onError( getCookieForCurrentSession(mBiometricService.mCurrentAuthSession), + BiometricAuthenticator.TYPE_FACE, BiometricConstants.BIOMETRIC_ERROR_CANCELED, - ERROR_CANCELED); + 0 /* vendorCode */); waitForIdle(); // Client receives error immediately verify(mReceiver1).onError( + eq(BiometricAuthenticator.TYPE_FACE), eq(BiometricConstants.BIOMETRIC_ERROR_CANCELED), - eq(ERROR_CANCELED)); + eq(0 /* vendorCode */)); // Dialog is hidden immediately verify(mBiometricService.mStatusBarService).hideAuthenticationDialog(); // Auth session is over @@ -519,26 +537,29 @@ public class BiometricServiceTest { mBiometricService.mInternalReceiver.onError( getCookieForCurrentSession(mBiometricService.mCurrentAuthSession), + BiometricAuthenticator.TYPE_FINGERPRINT, BiometricConstants.BIOMETRIC_ERROR_UNABLE_TO_PROCESS, - ERROR_UNABLE_TO_PROCESS); + 0 /* vendorCode */); waitForIdle(); // Sends error to SystemUI and does not notify client yet assertEquals(mBiometricService.mCurrentAuthSession.mState, BiometricService.STATE_ERROR_PENDING_SYSUI); verify(mBiometricService.mStatusBarService).onBiometricError( + eq(BiometricAuthenticator.TYPE_FINGERPRINT), eq(BiometricConstants.BIOMETRIC_ERROR_UNABLE_TO_PROCESS), - eq(ERROR_UNABLE_TO_PROCESS)); + eq(0 /* vendorCode */)); verify(mBiometricService.mStatusBarService, never()).hideAuthenticationDialog(); - verify(mReceiver1, never()).onError(anyInt(), anyString()); + verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt()); // SystemUI animation completed, client is notified, auth session is over mBiometricService.mInternalReceiver .onDialogDismissed(BiometricPrompt.DISMISSED_REASON_ERROR); waitForIdle(); verify(mReceiver1).onError( + eq(BiometricAuthenticator.TYPE_FINGERPRINT), eq(BiometricConstants.BIOMETRIC_ERROR_UNABLE_TO_PROCESS), - eq(ERROR_UNABLE_TO_PROCESS)); + eq(0 /* vendorCode */)); assertNull(mBiometricService.mCurrentAuthSession); } @@ -551,8 +572,9 @@ public class BiometricServiceTest { mBiometricService.mInternalReceiver.onError( getCookieForPendingSession(mBiometricService.mPendingAuthSession), + BiometricAuthenticator.TYPE_FACE, BiometricConstants.BIOMETRIC_ERROR_LOCKOUT, - ERROR_LOCKOUT); + 0 /* vendorCode */); waitForIdle(); // Pending auth session becomes current auth session, since device credential should @@ -583,8 +605,9 @@ public class BiometricServiceTest { mBiometricService.mInternalReceiver.onError( getCookieForPendingSession(mBiometricService.mPendingAuthSession), + BiometricAuthenticator.TYPE_FINGERPRINT, BiometricConstants.BIOMETRIC_ERROR_LOCKOUT, - ERROR_LOCKOUT); + 0 /* vendorCode */); waitForIdle(); // Error is sent to client @@ -651,17 +674,18 @@ public class BiometricServiceTest { assertEquals(BiometricService.STATE_SHOWING_DEVICE_CREDENTIAL, mBiometricService.mCurrentAuthSession.mState); - verify(mReceiver1, never()).onError(anyInt(), anyString()); + verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt()); mBiometricService.mInternalReceiver.onError( getCookieForCurrentSession(mBiometricService.mCurrentAuthSession), + BiometricAuthenticator.TYPE_FINGERPRINT, BiometricConstants.BIOMETRIC_ERROR_CANCELED, - ERROR_CANCELED); + 0 /* vendorCode */); waitForIdle(); assertEquals(BiometricService.STATE_SHOWING_DEVICE_CREDENTIAL, mBiometricService.mCurrentAuthSession.mState); - verify(mReceiver1, never()).onError(anyInt(), anyString()); + verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt()); } @Test @@ -675,15 +699,17 @@ public class BiometricServiceTest { mBiometricService.mInternalReceiver.onError( getCookieForCurrentSession(mBiometricService.mCurrentAuthSession), + BiometricAuthenticator.TYPE_FINGERPRINT, BiometricConstants.BIOMETRIC_ERROR_LOCKOUT, - ERROR_LOCKOUT); + 0 /* vendorCode */); waitForIdle(); assertEquals(BiometricService.STATE_SHOWING_DEVICE_CREDENTIAL, mBiometricService.mCurrentAuthSession.mState); verify(mBiometricService.mStatusBarService).onBiometricError( + eq(BiometricAuthenticator.TYPE_FINGERPRINT), eq(BiometricConstants.BIOMETRIC_ERROR_LOCKOUT), - eq(ERROR_LOCKOUT)); + eq(0 /* vendorCode */)); } @Test @@ -697,15 +723,17 @@ public class BiometricServiceTest { mBiometricService.mInternalReceiver.onError( getCookieForCurrentSession(mBiometricService.mCurrentAuthSession), + BiometricAuthenticator.TYPE_FINGERPRINT, BiometricConstants.BIOMETRIC_ERROR_UNABLE_TO_PROCESS, - ERROR_UNABLE_TO_PROCESS); + 0 /* vendorCode */); waitForIdle(); assertEquals(BiometricService.STATE_ERROR_PENDING_SYSUI, mBiometricService.mCurrentAuthSession.mState); verify(mBiometricService.mStatusBarService).onBiometricError( + eq(BiometricAuthenticator.TYPE_FINGERPRINT), eq(BiometricConstants.BIOMETRIC_ERROR_UNABLE_TO_PROCESS), - eq(ERROR_UNABLE_TO_PROCESS)); + eq(0 /* vendorCode */)); } @Test @@ -719,8 +747,9 @@ public class BiometricServiceTest { .onDialogDismissed(BiometricPrompt.DISMISSED_REASON_USER_CANCEL); waitForIdle(); verify(mReceiver1).onError( + eq(BiometricAuthenticator.TYPE_FINGERPRINT), eq(BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED), - eq(ERROR_USER_CANCELED)); + eq(0 /* vendorCode */)); verify(mBiometricService.mAuthenticators.get(0).impl).cancelAuthenticationFromService( any(), any(), @@ -739,8 +768,9 @@ public class BiometricServiceTest { mBiometricService.mInternalReceiver.onError( getCookieForCurrentSession(mBiometricService.mCurrentAuthSession), + BiometricAuthenticator.TYPE_FACE, BiometricConstants.BIOMETRIC_ERROR_TIMEOUT, - ERROR_TIMEOUT); + 0 /* vendorCode */); mBiometricService.mInternalReceiver.onDialogDismissed( BiometricPrompt.DISMISSED_REASON_NEGATIVE); waitForIdle(); @@ -764,8 +794,9 @@ public class BiometricServiceTest { mBiometricService.mInternalReceiver.onError( getCookieForCurrentSession(mBiometricService.mCurrentAuthSession), + BiometricAuthenticator.TYPE_FACE, BiometricConstants.BIOMETRIC_ERROR_TIMEOUT, - ERROR_TIMEOUT); + 0 /* vendorCode */); mBiometricService.mInternalReceiver.onDialogDismissed( BiometricPrompt.DISMISSED_REASON_USER_CANCEL); waitForIdle(); @@ -803,8 +834,9 @@ public class BiometricServiceTest { anyInt(), anyBoolean()); verify(mReceiver1).onError( + eq(BiometricAuthenticator.TYPE_FACE), eq(BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED), - eq(ERROR_USER_CANCELED)); + eq(0 /* vendorCode */)); assertNull(mBiometricService.mCurrentAuthSession); } |