diff options
| author | 2019-10-03 14:10:01 -0700 | |
|---|---|---|
| committer | 2019-10-18 16:45:52 -0700 | |
| commit | 0f9da353b5cc6acc8e42b49d51c96eb527680c3b (patch) | |
| tree | 8762080c3bc030f9f12f75c74b222ca8cacc73f9 | |
| parent | f2da1a1178cc1a15e2b2ee532a495503c4112eb8 (diff) | |
Remove strings from low level onError(...) calls
In order to get a correctly translated error messages, getString(...)
should be called on the application context, as opposed to the system
context. This is because the system context is unaware of the user's
locale.
Bug: 141025588
Test: Face Unlock works E2E
Test: Works with BiometricPromptDemo
Test: atest BiometricServiceTest
Test: atest AuthControllerTest
Test: atest CommandQueueTest
Change-Id: Ic228bb7ebb0d6a4ebaf96b9f1d2d70ed4e9dd79a
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); } |