Merge changes I02898d24,I3b8d172b into sc-dev

* changes:
  9/n: Add test case for udfps rejection after face rejection
  8/n: Add additional multi-sensor reject logic
This commit is contained in:
Kevin Chyn
2021-07-22 18:38:44 +00:00
committed by Android (Google) Code Review
2 changed files with 80 additions and 5 deletions

View File

@@ -268,11 +268,18 @@ public class CoexCoordinator {
AuthenticationClient<?> udfps = mClientMap.getOrDefault(SENSOR_TYPE_UDFPS, null);
AuthenticationClient<?> face = mClientMap.getOrDefault(SENSOR_TYPE_FACE, null);
if (isCurrentFaceAuth(client)) {
// UDFPS should still be running in this case, do not vibrate. However, we
// should notify the callback and finish the client, so that Keyguard and
// BiometricScheduler do not get stuck.
Slog.d(TAG, "Face rejected in multi-sensor auth, udfps: " + udfps);
callback.handleLifecycleAfterAuth();
if (isUdfpsActivelyAuthing(udfps)) {
// UDFPS should still be running in this case, do not vibrate. However, we
// should notify the callback and finish the client, so that Keyguard and
// BiometricScheduler do not get stuck.
Slog.d(TAG, "Face rejected in multi-sensor auth, udfps: " + udfps);
callback.handleLifecycleAfterAuth();
} else {
// UDFPS is not actively authenticating (finger not touching, already
// rejected, etc).
callback.sendHapticFeedback();
callback.handleLifecycleAfterAuth();
}
} else if (isCurrentUdfps(client)) {
// Face should either be running, or have already finished
SuccessfulAuth auth = popSuccessfulFaceAuthIfExists(currentTimeMillis);

View File

@@ -258,6 +258,74 @@ public class CoexCoordinatorTest {
verify(mCallback).handleLifecycleAfterAuth();
}
@Test
public void testKeyguard_faceRejectedWhenUdfpsTouching_thenUdfpsRejected() {
mCoexCoordinator.reset();
AuthenticationClient<?> faceClient = mock(AuthenticationClient.class);
when(faceClient.isKeyguard()).thenReturn(true);
when(faceClient.getState()).thenReturn(AuthenticationClient.STATE_STARTED);
AuthenticationClient<?> udfpsClient = mock(AuthenticationClient.class,
withSettings().extraInterfaces(Udfps.class));
when(udfpsClient.getState()).thenReturn(AuthenticationClient.STATE_STARTED);
when(udfpsClient.isKeyguard()).thenReturn(true);
when(((Udfps) udfpsClient).isPointerDown()).thenReturn(true);
mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_FACE, faceClient);
mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_UDFPS, udfpsClient);
mCoexCoordinator.onAuthenticationRejected(0 /* currentTimeMillis */, faceClient,
LockoutTracker.LOCKOUT_NONE, mCallback);
verify(mCallback, never()).sendHapticFeedback();
verify(mCallback).handleLifecycleAfterAuth();
// BiometricScheduler removes the face authentication client after rejection
mCoexCoordinator.removeAuthenticationClient(SENSOR_TYPE_FACE, faceClient);
// Then UDFPS rejected
CoexCoordinator.Callback udfpsCallback = mock(CoexCoordinator.Callback.class);
mCoexCoordinator.onAuthenticationRejected(1 /* currentTimeMillis */, udfpsClient,
LockoutTracker.LOCKOUT_NONE, udfpsCallback);
verify(udfpsCallback).sendHapticFeedback();
verify(udfpsCallback).sendAuthenticationResult(eq(false) /* addAuthTokenIfStrong */);
verify(mCallback, never()).sendHapticFeedback();
}
@Test
public void testKeyguard_udfpsRejected_thenFaceRejected() {
mCoexCoordinator.reset();
AuthenticationClient<?> faceClient = mock(AuthenticationClient.class);
when(faceClient.isKeyguard()).thenReturn(true);
when(faceClient.getState()).thenReturn(AuthenticationClient.STATE_STARTED);
AuthenticationClient<?> udfpsClient = mock(AuthenticationClient.class,
withSettings().extraInterfaces(Udfps.class));
when(udfpsClient.getState()).thenReturn(AuthenticationClient.STATE_STARTED);
when(udfpsClient.isKeyguard()).thenReturn(true);
when(((Udfps) udfpsClient).isPointerDown()).thenReturn(true);
mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_FACE, faceClient);
mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_UDFPS, udfpsClient);
mCoexCoordinator.onAuthenticationRejected(0 /* currentTimeMillis */, udfpsClient,
LockoutTracker.LOCKOUT_NONE, mCallback);
// Client becomes paused, but finger does not necessarily lift, since we suppress the haptic
when(udfpsClient.getState()).thenReturn(AuthenticationClient.STATE_STARTED_PAUSED);
verify(mCallback, never()).sendHapticFeedback();
verify(mCallback).handleLifecycleAfterAuth();
// Then face rejected. Note that scheduler leaves UDFPS in the CoexCoordinator since
// unlike face, its lifecycle becomes "paused" instead of "finished".
CoexCoordinator.Callback faceCallback = mock(CoexCoordinator.Callback.class);
mCoexCoordinator.onAuthenticationRejected(1 /* currentTimeMillis */, faceClient,
LockoutTracker.LOCKOUT_NONE, faceCallback);
verify(faceCallback).sendHapticFeedback();
verify(faceCallback).sendAuthenticationResult(eq(false) /* addAuthTokenIfStrong */);
verify(mCallback, never()).sendHapticFeedback();
}
@Test
public void testNonKeyguard_rejectAndNotLockedOut() {
mCoexCoordinator.reset();