summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl4
-rw-r--r--core/java/android/hardware/fingerprint/IUdfpsOverlayControllerCallback.aidl24
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java40
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java19
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java12
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/UdfpsHelper.java17
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java2
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java2
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java2
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java2
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java2
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/AcquisitionClientTest.java118
13 files changed, 226 insertions, 20 deletions
diff --git a/core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl b/core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl
index 81c7d894ee09..d2cb5bfe6910 100644
--- a/core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl
+++ b/core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl
@@ -15,6 +15,8 @@
*/
package android.hardware.fingerprint;
+import android.hardware.fingerprint.IUdfpsOverlayControllerCallback;
+
/**
* Interface for interacting with the under-display fingerprint sensor (UDFPS) overlay.
* @hide
@@ -28,7 +30,7 @@ oneway interface IUdfpsOverlayController {
const int REASON_AUTH_FPM_OTHER = 5; // Other FingerprintManager usage
// Shows the overlay.
- void showUdfpsOverlay(int sensorId, int reason);
+ void showUdfpsOverlay(int sensorId, int reason, IUdfpsOverlayControllerCallback callback);
// Hides the overlay.
void hideUdfpsOverlay(int sensorId);
diff --git a/core/java/android/hardware/fingerprint/IUdfpsOverlayControllerCallback.aidl b/core/java/android/hardware/fingerprint/IUdfpsOverlayControllerCallback.aidl
new file mode 100644
index 000000000000..51ada29f828f
--- /dev/null
+++ b/core/java/android/hardware/fingerprint/IUdfpsOverlayControllerCallback.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.fingerprint;
+
+/**
+ * @hide
+ */
+oneway interface IUdfpsOverlayControllerCallback {
+ // Notify system_server if the user cancels a UDFPS-related operation (enroll, auth)
+ void onUserCanceled();
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index edc9b8f7478f..0ffd7d215b49 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -20,7 +20,10 @@ import static com.android.internal.util.Preconditions.checkArgument;
import static com.android.internal.util.Preconditions.checkNotNull;
import android.annotation.SuppressLint;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.content.res.Resources;
import android.graphics.PixelFormat;
import android.graphics.Point;
@@ -29,6 +32,8 @@ import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.IUdfpsOverlayController;
import android.os.SystemClock;
+import android.hardware.fingerprint.IUdfpsOverlayControllerCallback;
+import android.os.RemoteException;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
@@ -110,10 +115,13 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
private static class ServerRequest {
// Reason the overlay has been requested. See IUdfpsOverlayController for definitions.
final int mRequestReason;
+ @NonNull final IUdfpsOverlayControllerCallback mCallback;
@Nullable final UdfpsEnrollHelper mEnrollHelper;
- ServerRequest(int requestReason, @Nullable UdfpsEnrollHelper enrollHelper) {
+ ServerRequest(int requestReason, @NonNull IUdfpsOverlayControllerCallback callback,
+ @Nullable UdfpsEnrollHelper enrollHelper) {
mRequestReason = requestReason;
+ mCallback = callback;
mEnrollHelper = enrollHelper;
}
@@ -128,11 +136,20 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
mEnrollHelper.onEnrollmentHelp();
}
}
+
+ void onUserCanceled() {
+ try {
+ mCallback.onUserCanceled();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Remote exception", e);
+ }
+ }
}
public class UdfpsOverlayController extends IUdfpsOverlayController.Stub {
@Override
- public void showUdfpsOverlay(int sensorId, int reason) {
+ public void showUdfpsOverlay(int sensorId, int reason,
+ @NonNull IUdfpsOverlayControllerCallback callback) {
final UdfpsEnrollHelper enrollHelper;
if (reason == IUdfpsOverlayController.REASON_ENROLL_FIND_SENSOR
|| reason == IUdfpsOverlayController.REASON_ENROLL_ENROLLING) {
@@ -141,7 +158,7 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
enrollHelper = null;
}
- mServerRequest = new ServerRequest(reason, enrollHelper);
+ mServerRequest = new ServerRequest(reason, callback, enrollHelper);
updateOverlay();
}
@@ -195,6 +212,19 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
return (float) Math.sqrt(Math.pow(vx, 2.0) + Math.pow(vy, 2.0));
}
+ private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (mServerRequest != null
+ && Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
+ Log.d(TAG, "ACTION_CLOSE_SYSTEM_DIALOGS received");
+ mServerRequest.onUserCanceled();
+ mServerRequest = null;
+ updateOverlay();
+ }
+ }
+ };
+
@SuppressLint("ClickableViewAccessibility")
private final UdfpsView.OnTouchListener mOnTouchListener = (view, event) -> {
UdfpsView udfpsView = (UdfpsView) view;
@@ -310,6 +340,10 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
mCoreLayoutParams.privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
mFingerprintManager.setUdfpsOverlayController(new UdfpsOverlayController());
+
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+ context.registerReceiver(mBroadcastReceiver, filter);
}
@Nullable
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index f84aa5940e61..07686181649d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -31,6 +31,7 @@ import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorProperties;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.IUdfpsOverlayController;
+import android.hardware.fingerprint.IUdfpsOverlayControllerCallback;
import android.os.PowerManager;
import android.os.RemoteException;
import android.testing.AndroidTestingRunner;
@@ -89,6 +90,8 @@ public class UdfpsControllerTest extends SysuiTestCase {
private StatusBarStateController mStatusBarStateController;
@Mock
private StatusBar mStatusBar;
+ @Mock
+ private IUdfpsOverlayControllerCallback mUdfpsOverlayControllerCallback;
private FakeExecutor mFgExecutor;
@@ -152,7 +155,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
@Test
public void dozeTimeTick() throws RemoteException {
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
- IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
+ IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD, mUdfpsOverlayControllerCallback);
mFgExecutor.runAllReady();
mUdfpsController.dozeTimeTick();
verify(mUdfpsView).dozeTimeTick();
@@ -161,7 +164,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
@Test
public void showUdfpsOverlay_addsViewToWindow() throws RemoteException {
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
- IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
+ IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD, mUdfpsOverlayControllerCallback);
mFgExecutor.runAllReady();
verify(mWindowManager).addView(eq(mUdfpsView), any());
}
@@ -169,7 +172,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
@Test
public void hideUdfpsOverlay_removesViewFromWindow() throws RemoteException {
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
- IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
+ IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD, mUdfpsOverlayControllerCallback);
mOverlayController.hideUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
mFgExecutor.runAllReady();
verify(mWindowManager).removeView(eq(mUdfpsView));
@@ -183,7 +186,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
// GIVEN that the overlay is showing
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
- IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
+ IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD, mUdfpsOverlayControllerCallback);
mFgExecutor.runAllReady();
// WHEN ACTION_DOWN is received
verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture());
@@ -205,7 +208,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
public void aodInterrupt() throws RemoteException {
// GIVEN that the overlay is showing
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
- IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
+ IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD, mUdfpsOverlayControllerCallback);
mFgExecutor.runAllReady();
// WHEN fingerprint is requested because of AOD interrupt
mUdfpsController.onAodInterrupt(0, 0, 2f, 3f);
@@ -221,7 +224,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
public void cancelAodInterrupt() throws RemoteException {
// GIVEN AOD interrupt
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
- IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
+ IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD, mUdfpsOverlayControllerCallback);
mFgExecutor.runAllReady();
mUdfpsController.onAodInterrupt(0, 0, 0f, 0f);
// WHEN it is cancelled
@@ -234,7 +237,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
public void aodInterruptTimeout() throws RemoteException {
// GIVEN AOD interrupt
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
- IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
+ IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD, mUdfpsOverlayControllerCallback);
mFgExecutor.runAllReady();
mUdfpsController.onAodInterrupt(0, 0, 0f, 0f);
// WHEN it times out
@@ -247,7 +250,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
@Test
public void registersAndUnregistersViewForCallbacks() throws RemoteException {
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
- IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD);
+ IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD, mUdfpsOverlayControllerCallback);
mFgExecutor.runAllReady();
verify(mStatusBarStateController).addCallback(mUdfpsController.mStatusBarStateListener);
verify(mStatusBar).addExpansionChangedListener(
diff --git a/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java b/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java
index b3580fb79042..93fea90cd89a 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java
@@ -80,6 +80,18 @@ public abstract class AcquisitionClient<T> extends HalClientMonitor<T> implement
onErrorInternal(errorCode, vendorCode, true /* finish */);
}
+ /**
+ * Notifies the caller that the operation was canceled by the user. Note that the actual
+ * operation still needs to wait for the HAL to send ERROR_CANCELED.
+ */
+ public void onUserCanceled() {
+ // Send USER_CANCELED, but do not finish. Wait for the HAL to respond with ERROR_CANCELED,
+ // which then finishes the AcquisitionClient's lifecycle.
+ onErrorInternal(BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED, 0 /* vendorCode */,
+ false /* finish */);
+ stopHalOperation();
+ }
+
protected void onErrorInternal(int errorCode, int vendorCode, boolean finish) {
// In some cases, the framework will send an error to the caller before a true terminal
// case (success, failure, or error) is received from the HAL (e.g. versions of fingerprint
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/UdfpsHelper.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/UdfpsHelper.java
index 37f8e8c2c1ee..f0e45978c365 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/UdfpsHelper.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/UdfpsHelper.java
@@ -22,9 +22,12 @@ import android.content.Context;
import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.IUdfpsOverlayController;
+import android.hardware.fingerprint.IUdfpsOverlayControllerCallback;
import android.os.RemoteException;
import android.util.Slog;
+import com.android.server.biometrics.sensors.AcquisitionClient;
+
/**
* Contains helper methods for under-display fingerprint HIDL.
*/
@@ -77,12 +80,22 @@ public class UdfpsHelper {
}
public static void showUdfpsOverlay(int sensorId, int reason,
- @Nullable IUdfpsOverlayController udfpsOverlayController) {
+ @Nullable IUdfpsOverlayController udfpsOverlayController,
+ @NonNull AcquisitionClient<?> client) {
if (udfpsOverlayController == null) {
return;
}
+
+ final IUdfpsOverlayControllerCallback callback =
+ new IUdfpsOverlayControllerCallback.Stub() {
+ @Override
+ public void onUserCanceled() {
+ client.onUserCanceled();
+ }
+ };
+
try {
- udfpsOverlayController.showUdfpsOverlay(sensorId, reason);
+ udfpsOverlayController.showUdfpsOverlay(sensorId, reason, callback);
} catch (RemoteException e) {
Slog.e(TAG, "Remote exception when showing the UDFPS overlay", e);
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
index f9527d9379bc..e2743f624c37 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
@@ -89,7 +89,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient<ISession> imp
@Override
protected void startHalOperation() {
UdfpsHelper.showUdfpsOverlay(getSensorId(), Utils.getUdfpsAuthReason(this),
- mUdfpsOverlayController);
+ mUdfpsOverlayController, this);
try {
mCancellationSignal = getFreshDaemon().authenticate(mSequentialId, mOperationId);
} catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java
index bcd1b8bc9976..620a9cf3e6f2 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java
@@ -72,7 +72,7 @@ class FingerprintDetectClient extends AcquisitionClient<ISession> {
protected void startHalOperation() {
UdfpsHelper.showUdfpsOverlay(getSensorId(),
IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD,
- mUdfpsOverlayController);
+ mUdfpsOverlayController, this);
try {
mCancellationSignal = getFreshDaemon().detectInteraction(mSequentialId);
} catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
index ae64c77f1365..63fa66cdca20 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
@@ -121,7 +121,7 @@ class FingerprintEnrollClient extends EnrollClient<ISession> implements Udfps {
protected void startHalOperation() {
UdfpsHelper.showUdfpsOverlay(getSensorId(),
UdfpsHelper.getReasonFromEnrollReason(mEnrollReason),
- mUdfpsOverlayController);
+ mUdfpsOverlayController, this);
try {
mCancellationSignal = getFreshDaemon().enroll(mSequentialId,
HardwareAuthTokenUtils.toHardwareAuthToken(mHardwareAuthToken));
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
index 83a3d9492b22..db371125478d 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
@@ -120,7 +120,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi
@Override
protected void startHalOperation() {
UdfpsHelper.showUdfpsOverlay(getSensorId(), Utils.getUdfpsAuthReason(this),
- mUdfpsOverlayController);
+ mUdfpsOverlayController, this);
try {
// GroupId was never used. In fact, groupId is always the same as userId.
getFreshDaemon().authenticate(mOperationId, getTargetUserId());
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java
index 8acb284667c7..db44aee1c0ed 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java
@@ -85,7 +85,7 @@ class FingerprintDetectClient extends AcquisitionClient<IBiometricsFingerprint>
protected void startHalOperation() {
UdfpsHelper.showUdfpsOverlay(getSensorId(),
IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD,
- mUdfpsOverlayController);
+ mUdfpsOverlayController, this);
try {
getFreshDaemon().authenticate(0 /* operationId */, getTargetUserId());
} catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
index 33db64c3259b..41d23089a530 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
@@ -84,7 +84,7 @@ public class FingerprintEnrollClient extends EnrollClient<IBiometricsFingerprint
protected void startHalOperation() {
UdfpsHelper.showUdfpsOverlay(getSensorId(),
UdfpsHelper.getReasonFromEnrollReason(mEnrollReason),
- mUdfpsOverlayController);
+ mUdfpsOverlayController, this);
try {
// GroupId was never used. In fact, groupId is always the same as userId.
getFreshDaemon().enroll(mHardwareAuthToken, getTargetUserId(), mTimeoutSec);
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/AcquisitionClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/AcquisitionClientTest.java
new file mode 100644
index 000000000000..46f96364ff9e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/AcquisitionClientTest.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+import android.content.Context;
+import android.hardware.biometrics.BiometricConstants;
+import android.os.IBinder;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.annotation.NonNull;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@Presubmit
+@SmallTest
+public class AcquisitionClientTest {
+
+ private static final int TEST_SENSOR_ID = 100;
+
+ @Mock
+ private Context mContext;
+ @Mock
+ private IBinder mToken;
+ @Mock
+ private ClientMonitorCallbackConverter mClientCallback;
+ @Mock
+ private BaseClientMonitor.Callback mSchedulerCallback;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void testUserCanceled() throws Exception {
+ // Start an AcquisitionClient
+ final TestAcquisitionClient client = new TestAcquisitionClient(mContext, Object::new,
+ mToken, mClientCallback);
+ client.start(mSchedulerCallback);
+ assertTrue(client.mHalOperationRunning);
+ verify(mSchedulerCallback).onClientStarted(eq(client));
+
+ // Pretend that it got canceled by the user.
+ client.onUserCanceled();
+ verify(mSchedulerCallback, never()).onClientFinished(any(), anyBoolean());
+ verify(mClientCallback).onError(eq(TEST_SENSOR_ID),
+ anyInt(),
+ eq(BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED),
+ eq(0) /* vendorCode */);
+ assertFalse(client.mHalOperationRunning);
+
+ // Pretend that the HAL responded with ERROR_CANCELED
+ client.onError(BiometricConstants.BIOMETRIC_ERROR_CANCELED, 0 /* vendorCode */);
+ verifyNoMoreInteractions(mClientCallback);
+ verify(mSchedulerCallback).onClientFinished(eq(client), anyBoolean());
+ }
+
+ private static class TestAcquisitionClient extends AcquisitionClient<Object> {
+ boolean mHalOperationRunning;
+
+ public TestAcquisitionClient(@NonNull Context context,
+ @NonNull LazyDaemon<Object> lazyDaemon, @NonNull IBinder token,
+ @NonNull ClientMonitorCallbackConverter callback) {
+ super(context, lazyDaemon, token, callback, 0 /* userId */, "Test", 0 /* cookie */,
+ TEST_SENSOR_ID /* sensorId */, 0 /* statsModality */, 0 /* statsAction */,
+ 0 /* statsClient */);
+ }
+
+ @Override
+ public void start(@NonNull Callback callback) {
+ super.start(callback);
+ startHalOperation();
+ }
+
+ @Override
+ protected void stopHalOperation() {
+ mHalOperationRunning = false;
+ }
+
+ @Override
+ protected void startHalOperation() {
+ mHalOperationRunning = true;
+ }
+
+ @Override
+ public int getProtoEnum() {
+ return 0;
+ }
+ }
+}