summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Kevin Chyn <kchyn@google.com> 2021-01-26 14:50:39 -0800
committer Kevin Chyn <kchyn@google.com> 2021-01-27 05:19:41 +0000
commit82b6469abfe25c66dc01ef99e41b10b72ee36ca4 (patch)
tree8d5147b5bd7f4677953dbdbf264e37a2621c87c0
parent77bb0b72919bb93d89095f2f78accac160633c02 (diff)
Check pending queue for cancelAuthentication
If cancelAuthentication is requested but actual authentication has not started yet (e.g. a previous non-cancelable operation such as updateActiveGroup or getAuthenticatorId is still running), look through the pending queue and mark all matched authentication clients as STATE_WAITING_IN_QUEUE_CANCELING. Test: atest BiometricSchedulerTest Fixes: 178105328 Change-Id: I755359adbdcda7f054135a190426b4a78a7a5125
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java26
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java57
2 files changed, 76 insertions, 7 deletions
diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
index c86bfcb4a88e..271537a9876c 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
@@ -563,14 +563,26 @@ public class BiometricScheduler {
final boolean isAuthenticating =
mCurrentOperation.mClientMonitor instanceof AuthenticationConsumer;
final boolean tokenMatches = mCurrentOperation.mClientMonitor.getToken() == token;
- if (!isAuthenticating || !tokenMatches) {
- Slog.w(getTag(), "Not cancelling authentication"
- + ", current operation : " + mCurrentOperation
- + ", tokenMatches: " + tokenMatches);
- return;
- }
- cancelInternal(mCurrentOperation);
+ if (isAuthenticating && tokenMatches) {
+ Slog.d(getTag(), "Cancelling authentication: " + mCurrentOperation);
+ cancelInternal(mCurrentOperation);
+ } else if (!isAuthenticating) {
+ // Look through the current queue for all authentication clients for the specified
+ // token, and mark them as STATE_WAITING_IN_QUEUE_CANCELING. Note that we're marking
+ // all of them, instead of just the first one, since the API surface currently doesn't
+ // allow us to distinguish between multiple authentication requests from the same
+ // process. However, this generally does not happen anyway, and would be a class of
+ // bugs on its own.
+ for (Operation operation : mPendingOperations) {
+ if (operation.mClientMonitor instanceof AuthenticationConsumer
+ && operation.mClientMonitor.getToken() == token) {
+ Slog.d(getTag(), "Marking " + operation
+ + " as STATE_WAITING_IN_QUEUE_CANCELING");
+ operation.mState = Operation.STATE_WAITING_IN_QUEUE_CANCELING;
+ }
+ }
+ }
}
/**
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
index 90ce6cbb7718..57b0d01b3025 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
@@ -33,6 +33,7 @@ import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.IBiometricService;
import android.os.Binder;
import android.os.IBinder;
+import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import androidx.annotation.NonNull;
@@ -267,6 +268,39 @@ public class BiometricSchedulerTest {
assertEquals(0, bsp.recentOperations.length);
}
+ @Test
+ public void testCancelPendingAuth() throws RemoteException {
+ final HalClientMonitor.LazyDaemon<Object> lazyDaemon = () -> mock(Object.class);
+
+ final TestClientMonitor client1 = new TestClientMonitor(mContext, mToken, lazyDaemon);
+ final ClientMonitorCallbackConverter callback = mock(ClientMonitorCallbackConverter.class);
+ final TestAuthenticationClient client2 = new TestAuthenticationClient(mContext, lazyDaemon,
+ mToken, callback);
+
+ // Add a non-cancellable client, then add the auth client
+ mScheduler.scheduleClientMonitor(client1);
+ mScheduler.scheduleClientMonitor(client2);
+ waitForIdle();
+
+ assertEquals(mScheduler.getCurrentClient(), client1);
+ assertEquals(Operation.STATE_WAITING_IN_QUEUE,
+ mScheduler.mPendingOperations.getFirst().mState);
+
+ // Request cancel before the authentication client has started
+ mScheduler.cancelAuthentication(mToken);
+ waitForIdle();
+ assertEquals(Operation.STATE_WAITING_IN_QUEUE_CANCELING,
+ mScheduler.mPendingOperations.getFirst().mState);
+
+ // Finish the blocking client. The authentication client should send ERROR_CANCELED
+ client1.getCallback().onClientFinished(client1, true /* success */);
+ waitForIdle();
+ verify(callback).onError(anyInt(), anyInt(),
+ eq(BiometricConstants.BIOMETRIC_ERROR_CANCELED),
+ eq(0) /* vendorCode */);
+ assertNull(mScheduler.getCurrentClient());
+ }
+
private BiometricSchedulerProto getDump(boolean clearSchedulerBuffer) throws Exception {
return BiometricSchedulerProto.parseFrom(mScheduler.dumpProtoState(clearSchedulerBuffer));
}
@@ -293,6 +327,29 @@ public class BiometricSchedulerTest {
}
}
+ private static class TestAuthenticationClient extends AuthenticationClient<Object> {
+
+ public TestAuthenticationClient(@NonNull Context context,
+ @NonNull LazyDaemon<Object> lazyDaemon, @NonNull IBinder token,
+ @NonNull ClientMonitorCallbackConverter listener) {
+ super(context, lazyDaemon, token, listener, 0 /* targetUserId */, 0 /* operationId */,
+ false /* restricted */, TAG, 1 /* cookie */, false /* requireConfirmation */,
+ TEST_SENSOR_ID, true /* isStrongBiometric */, 0 /* statsModality */,
+ 0 /* statsClient */, null /* taskStackListener */, mock(LockoutTracker.class),
+ false /* isKeyguard */);
+ }
+
+ @Override
+ protected void stopHalOperation() {
+
+ }
+
+ @Override
+ protected void startHalOperation() {
+
+ }
+ }
+
private static class TestClientMonitor2 extends TestClientMonitor {
private final int mProtoEnum;