diff options
| author | Kevin Chyn <kchyn@google.com> | 2021-02-20 04:27:26 +0000 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2021-02-20 04:27:26 +0000 |
| commit | be83ac78d234b737365cd59392fece3f4a746e6a (patch) | |
| tree | 2d0d7a8992b0c8491d667e422cdbde67a327d42a /core/java | |
| parent | 42f0a047df20a1f6afeee336488ab7cec4afd921 (diff) | |
| parent | 0d1b06e3d51955b29e52e5f97f07035001969bed (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')
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); |
