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
This commit is contained in:
Curtis Belmonte
2021-08-09 12:43:11 -07:00
parent e2c96ac3ad
commit b1b868fabe
2 changed files with 14 additions and 9 deletions

View File

@@ -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);

View File

@@ -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));
}