Loading services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java +2 −0 Original line number Original line Diff line number Diff line Loading @@ -355,7 +355,9 @@ public class BiometricScheduler { /** /** * Creates a new scheduler. * Creates a new scheduler. * @param context system_server context. * @param tag for the specific instance of the scheduler. Should be unique. * @param tag for the specific instance of the scheduler. Should be unique. * @param sensorType the sensorType that this scheduler is handling. * @param gestureAvailabilityDispatcher may be null if the sensor does not support gestures * @param gestureAvailabilityDispatcher may be null if the sensor does not support gestures * (such as fingerprint swipe). * (such as fingerprint swipe). */ */ Loading services/core/java/com/android/server/biometrics/sensors/CoexCoordinator.java +18 −1 Original line number Original line Diff line number Diff line Loading @@ -141,6 +141,7 @@ public class CoexCoordinator { } else { } else { // Multi sensor authentication // Multi sensor authentication AuthenticationClient<?> udfps = mClientMap.getOrDefault(SENSOR_TYPE_UDFPS, null); AuthenticationClient<?> udfps = mClientMap.getOrDefault(SENSOR_TYPE_UDFPS, null); AuthenticationClient<?> face = mClientMap.getOrDefault(SENSOR_TYPE_FACE, null); if (isCurrentFaceAuth(client)) { if (isCurrentFaceAuth(client)) { if (isPointerDown(udfps)) { if (isPointerDown(udfps)) { // Face auth success while UDFPS pointer down. No callback, no haptic. // Face auth success while UDFPS pointer down. No callback, no haptic. Loading @@ -149,6 +150,14 @@ public class CoexCoordinator { callback.sendHapticFeedback(); callback.sendHapticFeedback(); callback.sendAuthenticationResult(true /* addAuthTokenIfStrong */); callback.sendAuthenticationResult(true /* addAuthTokenIfStrong */); } } } else if (isCurrentUdfps(client)) { if (isFaceScanning()) { // UDFPS succeeds while face is still scanning // Cancel face auth and/or prevent it from invoking haptics/callbacks after face.cancel(); } callback.sendHapticFeedback(); callback.sendAuthenticationResult(true /* addAuthTokenIfStrong */); } } } } } else { } else { Loading @@ -175,7 +184,15 @@ public class CoexCoordinator { return client == mClientMap.getOrDefault(SENSOR_TYPE_FACE, null); return client == mClientMap.getOrDefault(SENSOR_TYPE_FACE, null); } } private boolean isPointerDown(@Nullable AuthenticationClient<?> client) { private boolean isCurrentUdfps(@NonNull AuthenticationClient<?> client) { return client == mClientMap.getOrDefault(SENSOR_TYPE_UDFPS, null); } private boolean isFaceScanning() { return mClientMap.containsKey(SENSOR_TYPE_FACE); } private static boolean isPointerDown(@Nullable AuthenticationClient<?> client) { if (client instanceof Udfps) { if (client instanceof Udfps) { return ((Udfps) client).isPointerDown(); return ((Udfps) client).isPointerDown(); } } Loading services/tests/servicestests/src/com/android/server/biometrics/sensors/CoexCoordinatorTest.java +21 −0 Original line number Original line Diff line number Diff line Loading @@ -154,4 +154,25 @@ public class CoexCoordinatorTest { verify(mCallback, never()).sendHapticFeedback(); verify(mCallback, never()).sendHapticFeedback(); verify(mCallback, never()).sendAuthenticationResult(anyBoolean()); verify(mCallback, never()).sendAuthenticationResult(anyBoolean()); } } @Test public void testKeyguard_udfpsAuthSuccess_whileFaceScanning() { mCoexCoordinator.reset(); AuthenticationClient<?> faceClient = mock(AuthenticationClient.class); when(faceClient.isKeyguard()).thenReturn(true); AuthenticationClient<?> udfpsClient = mock(AuthenticationClient.class, withSettings().extraInterfaces(Udfps.class)); when(udfpsClient.isKeyguard()).thenReturn(true); when(((Udfps) udfpsClient).isPointerDown()).thenReturn(true); mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_FACE, faceClient); mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_UDFPS, udfpsClient); mCoexCoordinator.onAuthenticationSucceeded(udfpsClient, mCallback); verify(mCallback).sendHapticFeedback(); verify(mCallback).sendAuthenticationResult(eq(true)); verify(faceClient).cancel(); } } } Loading
services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java +2 −0 Original line number Original line Diff line number Diff line Loading @@ -355,7 +355,9 @@ public class BiometricScheduler { /** /** * Creates a new scheduler. * Creates a new scheduler. * @param context system_server context. * @param tag for the specific instance of the scheduler. Should be unique. * @param tag for the specific instance of the scheduler. Should be unique. * @param sensorType the sensorType that this scheduler is handling. * @param gestureAvailabilityDispatcher may be null if the sensor does not support gestures * @param gestureAvailabilityDispatcher may be null if the sensor does not support gestures * (such as fingerprint swipe). * (such as fingerprint swipe). */ */ Loading
services/core/java/com/android/server/biometrics/sensors/CoexCoordinator.java +18 −1 Original line number Original line Diff line number Diff line Loading @@ -141,6 +141,7 @@ public class CoexCoordinator { } else { } else { // Multi sensor authentication // Multi sensor authentication AuthenticationClient<?> udfps = mClientMap.getOrDefault(SENSOR_TYPE_UDFPS, null); AuthenticationClient<?> udfps = mClientMap.getOrDefault(SENSOR_TYPE_UDFPS, null); AuthenticationClient<?> face = mClientMap.getOrDefault(SENSOR_TYPE_FACE, null); if (isCurrentFaceAuth(client)) { if (isCurrentFaceAuth(client)) { if (isPointerDown(udfps)) { if (isPointerDown(udfps)) { // Face auth success while UDFPS pointer down. No callback, no haptic. // Face auth success while UDFPS pointer down. No callback, no haptic. Loading @@ -149,6 +150,14 @@ public class CoexCoordinator { callback.sendHapticFeedback(); callback.sendHapticFeedback(); callback.sendAuthenticationResult(true /* addAuthTokenIfStrong */); callback.sendAuthenticationResult(true /* addAuthTokenIfStrong */); } } } else if (isCurrentUdfps(client)) { if (isFaceScanning()) { // UDFPS succeeds while face is still scanning // Cancel face auth and/or prevent it from invoking haptics/callbacks after face.cancel(); } callback.sendHapticFeedback(); callback.sendAuthenticationResult(true /* addAuthTokenIfStrong */); } } } } } else { } else { Loading @@ -175,7 +184,15 @@ public class CoexCoordinator { return client == mClientMap.getOrDefault(SENSOR_TYPE_FACE, null); return client == mClientMap.getOrDefault(SENSOR_TYPE_FACE, null); } } private boolean isPointerDown(@Nullable AuthenticationClient<?> client) { private boolean isCurrentUdfps(@NonNull AuthenticationClient<?> client) { return client == mClientMap.getOrDefault(SENSOR_TYPE_UDFPS, null); } private boolean isFaceScanning() { return mClientMap.containsKey(SENSOR_TYPE_FACE); } private static boolean isPointerDown(@Nullable AuthenticationClient<?> client) { if (client instanceof Udfps) { if (client instanceof Udfps) { return ((Udfps) client).isPointerDown(); return ((Udfps) client).isPointerDown(); } } Loading
services/tests/servicestests/src/com/android/server/biometrics/sensors/CoexCoordinatorTest.java +21 −0 Original line number Original line Diff line number Diff line Loading @@ -154,4 +154,25 @@ public class CoexCoordinatorTest { verify(mCallback, never()).sendHapticFeedback(); verify(mCallback, never()).sendHapticFeedback(); verify(mCallback, never()).sendAuthenticationResult(anyBoolean()); verify(mCallback, never()).sendAuthenticationResult(anyBoolean()); } } @Test public void testKeyguard_udfpsAuthSuccess_whileFaceScanning() { mCoexCoordinator.reset(); AuthenticationClient<?> faceClient = mock(AuthenticationClient.class); when(faceClient.isKeyguard()).thenReturn(true); AuthenticationClient<?> udfpsClient = mock(AuthenticationClient.class, withSettings().extraInterfaces(Udfps.class)); when(udfpsClient.isKeyguard()).thenReturn(true); when(((Udfps) udfpsClient).isPointerDown()).thenReturn(true); mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_FACE, faceClient); mCoexCoordinator.addAuthenticationClient(SENSOR_TYPE_UDFPS, udfpsClient); mCoexCoordinator.onAuthenticationSucceeded(udfpsClient, mCallback); verify(mCallback).sendHapticFeedback(); verify(mCallback).sendAuthenticationResult(eq(true)); verify(faceClient).cancel(); } } }