summaryrefslogtreecommitdiff
path: root/core/java
diff options
context:
space:
mode:
authorKevin Chyn <kchyn@google.com>2021-02-20 04:27:26 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2021-02-20 04:27:26 +0000
commitbe83ac78d234b737365cd59392fece3f4a746e6a (patch)
tree2d0d7a8992b0c8491d667e422cdbde67a327d42a /core/java
parent42f0a047df20a1f6afeee336488ab7cec4afd921 (diff)
parent0d1b06e3d51955b29e52e5f97f07035001969bed (diff)
Merge changes from topic "revert-13630975-revert-13593269-QAPPBSWOVZ-FERZONVHNV" into sc-dev
* changes: Revert^2 "Try to ensure tests run sequentially" Fix NPE during fingerprint removal Revert^2 "Update RemovalClient to support new biometric AIDL"
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/hardware/biometrics/BiometricManager.java3
-rw-r--r--core/java/android/hardware/biometrics/BiometricTestSession.java75
-rw-r--r--core/java/android/hardware/biometrics/IAuthService.aidl3
-rw-r--r--core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl3
-rw-r--r--core/java/android/hardware/biometrics/IBiometricService.aidl3
-rw-r--r--core/java/android/hardware/biometrics/ITestSession.aidl2
-rw-r--r--core/java/android/hardware/biometrics/ITestSessionCallback.aidl25
-rw-r--r--core/java/android/hardware/face/FaceManager.java23
-rw-r--r--core/java/android/hardware/face/IFaceService.aidl8
-rw-r--r--core/java/android/hardware/fingerprint/FingerprintManager.java76
-rw-r--r--core/java/android/hardware/fingerprint/IFingerprintService.aidl6
11 files changed, 187 insertions, 40 deletions
diff --git a/core/java/android/hardware/biometrics/BiometricManager.java b/core/java/android/hardware/biometrics/BiometricManager.java
index 4ca31050bd52..5b28e0035b09 100644
--- a/core/java/android/hardware/biometrics/BiometricManager.java
+++ b/core/java/android/hardware/biometrics/BiometricManager.java
@@ -237,7 +237,8 @@ public class BiometricManager {
public BiometricTestSession createTestSession(int sensorId) {
try {
return new BiometricTestSession(mContext, sensorId,
- mService.createTestSession(sensorId, mContext.getOpPackageName()));
+ (context, sensorId1, callback) -> mService
+ .createTestSession(sensorId1, callback, context.getOpPackageName()));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/hardware/biometrics/BiometricTestSession.java b/core/java/android/hardware/biometrics/BiometricTestSession.java
index 1c3560882f1b..ff1a17e07c11 100644
--- a/core/java/android/hardware/biometrics/BiometricTestSession.java
+++ b/core/java/android/hardware/biometrics/BiometricTestSession.java
@@ -19,6 +19,7 @@ package android.hardware.biometrics;
import static android.Manifest.permission.TEST_BIOMETRIC;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.TestApi;
import android.content.Context;
@@ -27,6 +28,9 @@ import android.os.RemoteException;
import android.util.ArraySet;
import android.util.Log;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
/**
* Common set of interfaces to test biometric-related APIs, including {@link BiometricPrompt} and
* {@link android.hardware.fingerprint.FingerprintManager}.
@@ -36,22 +40,58 @@ import android.util.Log;
public class BiometricTestSession implements AutoCloseable {
private static final String TAG = "BiometricTestSession";
+ /**
+ * @hide
+ */
+ public interface TestSessionProvider {
+ @NonNull
+ ITestSession createTestSession(@NonNull Context context, int sensorId,
+ @NonNull ITestSessionCallback callback) throws RemoteException;
+ }
+
private final Context mContext;
private final int mSensorId;
private final ITestSession mTestSession;
// Keep track of users that were tested, which need to be cleaned up when finishing.
- private final ArraySet<Integer> mTestedUsers;
+ @NonNull private final ArraySet<Integer> mTestedUsers;
+
+ // Track the users currently cleaning up, and provide a latch that gets notified when all
+ // users have finished cleaning up. This is an imperfect system, as there can technically be
+ // multiple cleanups per user. Theoretically we should track the cleanup's BaseClientMonitor's
+ // unique ID, but it's complicated to plumb it through. This should be fine for now.
+ @Nullable private CountDownLatch mCloseLatch;
+ @NonNull private final ArraySet<Integer> mUsersCleaningUp;
+
+ private final ITestSessionCallback mCallback = new ITestSessionCallback.Stub() {
+ @Override
+ public void onCleanupStarted(int userId) {
+ Log.d(TAG, "onCleanupStarted, sensor: " + mSensorId + ", userId: " + userId);
+ }
+
+ @Override
+ public void onCleanupFinished(int userId) {
+ Log.d(TAG, "onCleanupFinished, sensor: " + mSensorId
+ + ", userId: " + userId
+ + ", remaining users: " + mUsersCleaningUp.size());
+ mUsersCleaningUp.remove(userId);
+
+ if (mUsersCleaningUp.isEmpty() && mCloseLatch != null) {
+ mCloseLatch.countDown();
+ }
+ }
+ };
/**
* @hide
*/
public BiometricTestSession(@NonNull Context context, int sensorId,
- @NonNull ITestSession testSession) {
+ @NonNull TestSessionProvider testSessionProvider) throws RemoteException {
mContext = context;
mSensorId = sensorId;
- mTestSession = testSession;
+ mTestSession = testSessionProvider.createTestSession(context, sensorId, mCallback);
mTestedUsers = new ArraySet<>();
+ mUsersCleaningUp = new ArraySet<>();
setTestHalEnabled(true);
}
@@ -176,6 +216,11 @@ public class BiometricTestSession implements AutoCloseable {
@RequiresPermission(TEST_BIOMETRIC)
public void cleanupInternalState(int userId) {
try {
+ if (mUsersCleaningUp.contains(userId)) {
+ Log.w(TAG, "Cleanup already in progress for user: " + userId);
+ }
+
+ mUsersCleaningUp.add(userId);
mTestSession.cleanupInternalState(userId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -185,12 +230,24 @@ public class BiometricTestSession implements AutoCloseable {
@Override
@RequiresPermission(TEST_BIOMETRIC)
public void close() {
- // Disable the test HAL first, so that enumerate is run on the real HAL, which should have
- // no enrollments. Test-only framework enrollments will be deleted.
- setTestHalEnabled(false);
-
- for (int user : mTestedUsers) {
- cleanupInternalState(user);
+ // Cleanup can be performed using the test HAL, since it always responds to enumerate with
+ // zero enrollments.
+ if (!mTestedUsers.isEmpty()) {
+ mCloseLatch = new CountDownLatch(1);
+ for (int user : mTestedUsers) {
+ cleanupInternalState(user);
+ }
+
+ try {
+ Log.d(TAG, "Awaiting latch...");
+ mCloseLatch.await(10, TimeUnit.SECONDS);
+ Log.d(TAG, "Finished awaiting");
+ } catch (InterruptedException e) {
+ Log.e(TAG, "Latch interrupted", e);
+ }
}
+
+ // Disable the test HAL after the sensor becomes idle.
+ setTestHalEnabled(false);
}
}
diff --git a/core/java/android/hardware/biometrics/IAuthService.aidl b/core/java/android/hardware/biometrics/IAuthService.aidl
index 0dfd5dbf300e..d8c9dbc849a9 100644
--- a/core/java/android/hardware/biometrics/IAuthService.aidl
+++ b/core/java/android/hardware/biometrics/IAuthService.aidl
@@ -20,6 +20,7 @@ import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
import android.hardware.biometrics.IBiometricServiceReceiver;
import android.hardware.biometrics.IInvalidationCallback;
import android.hardware.biometrics.ITestSession;
+import android.hardware.biometrics.ITestSessionCallback;
import android.hardware.biometrics.PromptInfo;
import android.hardware.biometrics.SensorPropertiesInternal;
@@ -32,7 +33,7 @@ import android.hardware.biometrics.SensorPropertiesInternal;
*/
interface IAuthService {
// Creates a test session with the specified sensorId
- ITestSession createTestSession(int sensorId, String opPackageName);
+ ITestSession createTestSession(int sensorId, ITestSessionCallback callback, String opPackageName);
// Retrieve static sensor properties for all biometric sensors
List<SensorPropertiesInternal> getSensorProperties(String opPackageName);
diff --git a/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl b/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl
index c854ac9847d8..7639c5dd4d16 100644
--- a/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl
+++ b/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl
@@ -20,6 +20,7 @@ import android.hardware.biometrics.IBiometricSensorReceiver;
import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
import android.hardware.biometrics.IInvalidationCallback;
import android.hardware.biometrics.ITestSession;
+import android.hardware.biometrics.ITestSessionCallback;
import android.hardware.biometrics.SensorPropertiesInternal;
import android.hardware.face.IFaceServiceReceiver;
import android.hardware.face.Face;
@@ -32,7 +33,7 @@ import android.hardware.face.Face;
interface IBiometricAuthenticator {
// Creates a test session
- ITestSession createTestSession(String opPackageName);
+ ITestSession createTestSession(ITestSessionCallback callback, String opPackageName);
// Retrieve static sensor properties
SensorPropertiesInternal getSensorProperties(String opPackageName);
diff --git a/core/java/android/hardware/biometrics/IBiometricService.aidl b/core/java/android/hardware/biometrics/IBiometricService.aidl
index a14a910a9e50..24331863a05f 100644
--- a/core/java/android/hardware/biometrics/IBiometricService.aidl
+++ b/core/java/android/hardware/biometrics/IBiometricService.aidl
@@ -21,6 +21,7 @@ import android.hardware.biometrics.IBiometricServiceReceiver;
import android.hardware.biometrics.IBiometricAuthenticator;
import android.hardware.biometrics.IInvalidationCallback;
import android.hardware.biometrics.ITestSession;
+import android.hardware.biometrics.ITestSessionCallback;
import android.hardware.biometrics.PromptInfo;
import android.hardware.biometrics.SensorPropertiesInternal;
@@ -30,7 +31,7 @@ import android.hardware.biometrics.SensorPropertiesInternal;
*/
interface IBiometricService {
// Creates a test session with the specified sensorId
- ITestSession createTestSession(int sensorId, String opPackageName);
+ ITestSession createTestSession(int sensorId, ITestSessionCallback callback, String opPackageName);
// Retrieve static sensor properties for all biometric sensors
List<SensorPropertiesInternal> getSensorProperties(String opPackageName);
diff --git a/core/java/android/hardware/biometrics/ITestSession.aidl b/core/java/android/hardware/biometrics/ITestSession.aidl
index fa7a62c53531..f8395a119c0b 100644
--- a/core/java/android/hardware/biometrics/ITestSession.aidl
+++ b/core/java/android/hardware/biometrics/ITestSession.aidl
@@ -18,7 +18,7 @@ package android.hardware.biometrics;
import android.hardware.biometrics.SensorPropertiesInternal;
/**
- * A test service for FingerprintManager and BiometricPrompt.
+ * A test service for FingerprintManager and BiometricManager.
* @hide
*/
interface ITestSession {
diff --git a/core/java/android/hardware/biometrics/ITestSessionCallback.aidl b/core/java/android/hardware/biometrics/ITestSessionCallback.aidl
new file mode 100644
index 000000000000..3d9517f29548
--- /dev/null
+++ b/core/java/android/hardware/biometrics/ITestSessionCallback.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2020 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.biometrics;
+
+/**
+ * ITestSession callback for FingerprintManager and BiometricManager.
+ * @hide
+ */
+interface ITestSessionCallback {
+ void onCleanupStarted(int userId);
+ void onCleanupFinished(int userId);
+}
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index 886a8c1fdae5..a9bcdeff7e47 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -574,12 +574,23 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
mService.remove(mToken, face.getBiometricId(), userId, mServiceReceiver,
mContext.getOpPackageName());
} catch (RemoteException e) {
- Slog.w(TAG, "Remote exception in remove: ", e);
- if (callback != null) {
- callback.onRemovalError(face, FACE_ERROR_HW_UNAVAILABLE,
- getErrorString(mContext, FACE_ERROR_HW_UNAVAILABLE,
- 0 /* vendorCode */));
- }
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ /**
+ * Removes all face templates for the given user.
+ * @hide
+ */
+ @RequiresPermission(MANAGE_BIOMETRIC)
+ public void removeAll(int userId, @NonNull RemovalCallback callback) {
+ if (mService != null) {
+ try {
+ mRemovalCallback = callback;
+ mService.removeAll(mToken, userId, mServiceReceiver, mContext.getOpPackageName());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
}
diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl
index a3e7e2d2c5cb..6e7c701ef5ff 100644
--- a/core/java/android/hardware/face/IFaceService.aidl
+++ b/core/java/android/hardware/face/IFaceService.aidl
@@ -19,6 +19,7 @@ import android.hardware.biometrics.IBiometricSensorReceiver;
import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
import android.hardware.biometrics.IInvalidationCallback;
import android.hardware.biometrics.ITestSession;
+import android.hardware.biometrics.ITestSessionCallback;
import android.hardware.face.IFaceServiceReceiver;
import android.hardware.face.Face;
import android.hardware.face.FaceSensorPropertiesInternal;
@@ -32,7 +33,7 @@ import android.view.Surface;
interface IFaceService {
// Creates a test session with the specified sensorId
- ITestSession createTestSession(int sensorId, String opPackageName);
+ ITestSession createTestSession(int sensorId, ITestSessionCallback callback, String opPackageName);
// Requests a proto dump of the specified sensor
byte[] dumpSensorServiceStateProto(int sensorId, boolean clearSchedulerBuffer);
@@ -83,10 +84,13 @@ interface IFaceService {
// Cancel enrollment in progress
void cancelEnrollment(IBinder token);
- // Any errors resulting from this call will be returned to the listener
+ // Removes the specified face enrollment for the specified userId.
void remove(IBinder token, int faceId, int userId, IFaceServiceReceiver receiver,
String opPackageName);
+ // Removes all face enrollments for the specified userId.
+ void removeAll(IBinder token, int userId, IFaceServiceReceiver receiver, String opPackageName);
+
// Get the enrolled face for user.
List<Face> getEnrolledFaces(int sensorId, int userId, String opPackageName);
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index a614ebfe1793..fc795d8a0488 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -114,6 +114,21 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
*/
public static final int SENSOR_ID_ANY = -1;
+ private static class RemoveTracker {
+ static final int REMOVE_SINGLE = 1;
+ static final int REMOVE_ALL = 2;
+ @IntDef({REMOVE_SINGLE, REMOVE_ALL})
+ @interface RemoveRequest {}
+
+ final @RemoveRequest int mRemoveRequest;
+ @Nullable final Fingerprint mSingleFingerprint;
+
+ RemoveTracker(@RemoveRequest int request, @Nullable Fingerprint fingerprint) {
+ mRemoveRequest = request;
+ mSingleFingerprint = fingerprint;
+ }
+ }
+
private IFingerprintService mService;
private Context mContext;
private IBinder mToken = new Binder();
@@ -123,10 +138,9 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
private RemovalCallback mRemovalCallback;
private GenerateChallengeCallback mGenerateChallengeCallback;
private CryptoObject mCryptoObject;
- private Fingerprint mRemovalFingerprint;
+ @Nullable private RemoveTracker mRemoveTracker;
private Handler mHandler;
-
/**
* Retrieves a list of properties for all fingerprint sensors on the device.
* @hide
@@ -154,7 +168,8 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
public BiometricTestSession createTestSession(int sensorId) {
try {
return new BiometricTestSession(mContext, sensorId,
- mService.createTestSession(sensorId, mContext.getOpPackageName()));
+ (context, sensorId1, callback) -> mService
+ .createTestSession(sensorId1, callback, context.getOpPackageName()));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -735,15 +750,27 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
public void remove(Fingerprint fp, int userId, RemovalCallback callback) {
if (mService != null) try {
mRemovalCallback = callback;
- mRemovalFingerprint = fp;
+ mRemoveTracker = new RemoveTracker(RemoveTracker.REMOVE_SINGLE, fp);
mService.remove(mToken, fp.getBiometricId(), userId, mServiceReceiver,
mContext.getOpPackageName());
} catch (RemoteException e) {
- Slog.w(TAG, "Remote exception in remove: ", e);
- if (callback != null) {
- callback.onRemovalError(fp, FINGERPRINT_ERROR_HW_UNAVAILABLE,
- getErrorString(mContext, FINGERPRINT_ERROR_HW_UNAVAILABLE,
- 0 /* vendorCode */));
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Removes all face templates for the given user.
+ * @hide
+ */
+ @RequiresPermission(MANAGE_FINGERPRINT)
+ public void removeAll(int userId, @NonNull RemovalCallback callback) {
+ if (mService != null) {
+ try {
+ mRemovalCallback = callback;
+ mRemoveTracker = new RemoveTracker(RemoveTracker.REMOVE_ALL, null /* fp */);
+ mService.removeAll(mToken, userId, mServiceReceiver, mContext.getOpPackageName());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -1044,16 +1071,29 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
if (mRemovalCallback == null) {
return;
}
- if (fingerprint == null) {
- Slog.e(TAG, "Received MSG_REMOVED, but fingerprint is null");
+
+ if (mRemoveTracker == null) {
+ Slog.w(TAG, "Removal tracker is null");
return;
}
- int fingerId = fingerprint.getBiometricId();
- int reqFingerId = mRemovalFingerprint.getBiometricId();
- if (reqFingerId != 0 && fingerId != 0 && fingerId != reqFingerId) {
- Slog.w(TAG, "Finger id didn't match: " + fingerId + " != " + reqFingerId);
- return;
+ if (mRemoveTracker.mRemoveRequest == RemoveTracker.REMOVE_SINGLE) {
+ if (fingerprint == null) {
+ Slog.e(TAG, "Received MSG_REMOVED, but fingerprint is null");
+ return;
+ }
+
+ if (mRemoveTracker.mSingleFingerprint == null) {
+ Slog.e(TAG, "Missing fingerprint");
+ return;
+ }
+
+ final int fingerId = fingerprint.getBiometricId();
+ int reqFingerId = mRemoveTracker.mSingleFingerprint.getBiometricId();
+ if (reqFingerId != 0 && fingerId != 0 && fingerId != reqFingerId) {
+ Slog.w(TAG, "Finger id didn't match: " + fingerId + " != " + reqFingerId);
+ return;
+ }
}
mRemovalCallback.onRemovalSucceeded(fingerprint, remaining);
@@ -1110,7 +1150,9 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
mAuthenticationCallback.onAuthenticationError(clientErrMsgId,
getErrorString(mContext, errMsgId, vendorCode));
} else if (mRemovalCallback != null) {
- mRemovalCallback.onRemovalError(mRemovalFingerprint, clientErrMsgId,
+ final Fingerprint fp = mRemoveTracker != null
+ ? mRemoveTracker.mSingleFingerprint : null;
+ mRemovalCallback.onRemovalError(fp, clientErrMsgId,
getErrorString(mContext, errMsgId, vendorCode));
}
}
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index 8888247e2823..054c0d0f6513 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -19,6 +19,7 @@ import android.hardware.biometrics.IBiometricSensorReceiver;
import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
import android.hardware.biometrics.IInvalidationCallback;
import android.hardware.biometrics.ITestSession;
+import android.hardware.biometrics.ITestSessionCallback;
import android.hardware.fingerprint.IFingerprintClientActiveCallback;
import android.hardware.fingerprint.IFingerprintServiceReceiver;
import android.hardware.fingerprint.IUdfpsOverlayController;
@@ -33,7 +34,7 @@ import java.util.List;
interface IFingerprintService {
// Creates a test session with the specified sensorId
- ITestSession createTestSession(int sensorId, String opPackageName);
+ ITestSession createTestSession(int sensorId, ITestSessionCallback callback, String opPackageName);
// Requests a proto dump of the specified sensor
byte[] dumpSensorServiceStateProto(int sensorId, boolean clearSchedulerBuffer);
@@ -87,6 +88,9 @@ interface IFingerprintService {
void remove(IBinder token, int fingerId, int userId, IFingerprintServiceReceiver receiver,
String opPackageName);
+ // Removes all face enrollments for the specified userId.
+ void removeAll(IBinder token, int userId, IFingerprintServiceReceiver receiver, String opPackageName);
+
// Rename the fingerprint specified by fingerId and userId to the given name
void rename(int fingerId, int userId, String name);