From b1b868fabe8ffccdd613905ce2320e437e681386 Mon Sep 17 00:00:00 2001 From: Curtis Belmonte Date: Mon, 9 Aug 2021 12:43:11 -0700 Subject: [PATCH] Show fingerprint icon when face fails on BiometricPrompt When BiometricPrompt is launched with both a face and fingerprint enrolled, ensure that the fingerprint icon is shown immediately after face authentication fails. This replaces the old behavior where an error icon would be shown for ~2 seconds after face authentication failed. Test: Manual: 1. Enroll both fingerprint and face on a device 2. Trigger BiometricPrompt (e.g. Internet > Settings > Share) 3. Ensure face authentication fails (e.g. by not looking at device) 4. Verify that the fingerprint icon is shown immediately Fixes: 195794375 Change-Id: I5abf788df5e973711d932af685e674f03e89fae6 --- .../AuthBiometricFaceToFingerprintView.java | 13 ++++++++++--- .../AuthBiometricFaceToFingerprintViewTest.java | 10 ++++------ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintView.java index 98ad875068192..ae3e94b9a1cb0 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintView.java @@ -44,11 +44,17 @@ public class AuthBiometricFaceToFingerprintView extends AuthBiometricFaceView { private static final String TAG = "BiometricPrompt/AuthBiometricFaceToFingerprintView"; protected static class UdfpsIconController extends IconController { + @BiometricState private int mIconState = STATE_IDLE; + protected UdfpsIconController( @NonNull Context context, @NonNull ImageView iconView, @NonNull TextView textView) { super(context, iconView, textView); } + void updateState(@BiometricState int newState) { + updateState(mIconState, newState); + } + @Override protected void updateState(int lastState, int newState) { final boolean lastStateIsErrorIcon = @@ -86,6 +92,7 @@ public class AuthBiometricFaceToFingerprintView extends AuthBiometricFaceView { } mState = newState; + mIconState = newState; } } @@ -191,11 +198,11 @@ public class AuthBiometricFaceToFingerprintView extends AuthBiometricFaceView { // Deactivate the face icon controller so it stops drawing to the view mFaceIconController.deactivate(); - // Then, activate this icon controller. We need to start in the "error" state - mUdfpsIconController.updateState(mState, newState); + // Then, activate this icon controller. We need to start in the "idle" state + mUdfpsIconController.updateState(STATE_IDLE); } } else { // Fingerprint - mUdfpsIconController.updateState(mState, newState); + mUdfpsIconController.updateState(newState); } super.updateState(newState); diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintViewTest.java index 090cf9f63eaff..f91c029388455 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFaceToFingerprintViewTest.java @@ -101,7 +101,7 @@ public class AuthBiometricFaceToFingerprintViewTest extends SysuiTestCase { mFaceToFpView.onDialogAnimatedIn(); verify(mFaceToFpView.mFaceIconController) .updateState(anyInt(), eq(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING)); - verify(mFaceToFpView.mUdfpsIconController, never()).updateState(anyInt(), anyInt()); + verify(mFaceToFpView.mUdfpsIconController, never()).updateState(anyInt()); } @Test @@ -109,13 +109,13 @@ public class AuthBiometricFaceToFingerprintViewTest extends SysuiTestCase { mFaceToFpView.onDialogAnimatedIn(); verify(mFaceToFpView.mFaceIconController) .updateState(anyInt(), eq(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING)); - verify(mFaceToFpView.mUdfpsIconController, never()).updateState(anyInt(), anyInt()); + verify(mFaceToFpView.mUdfpsIconController, never()).updateState(anyInt()); mFaceToFpView.updateState(AuthBiometricFaceView.STATE_AUTHENTICATED); verify(mFaceToFpView.mFaceIconController).updateState( eq(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING), eq(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATED)); - verify(mFaceToFpView.mUdfpsIconController, never()).updateState(anyInt(), anyInt()); + verify(mFaceToFpView.mUdfpsIconController, never()).updateState(anyInt()); assertEquals(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATED, mFaceToFpView.mState); } @@ -130,14 +130,12 @@ public class AuthBiometricFaceToFingerprintViewTest extends SysuiTestCase { verify(mFaceToFpView.mFaceIconController).deactivate(); verify(mFaceToFpView.mUdfpsIconController).updateState( - eq(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING), - eq(AuthBiometricFaceToFingerprintView.STATE_ERROR)); + eq(AuthBiometricFaceToFingerprintView.STATE_IDLE)); verify(mConfirmButton).setVisibility(eq(View.GONE)); mFaceToFpView.updateState(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING); verify(mFaceToFpView.mUdfpsIconController).updateState( - eq(AuthBiometricFaceToFingerprintView.STATE_ERROR), eq(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING)); }