summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Kevin Chyn <kchyn@google.com> 2020-11-17 12:40:14 -0800
committer Kevin Chyn <kchyn@google.com> 2020-11-17 20:02:56 -0800
commit0a60a1ce041f7265f1274d5bfdb1d648b585231e (patch)
treeb634f7de08cc9f891a9d9f6e6262571d1cd04b24
parentfe03ccafaaf8f96b436dbf4565b65111b7f8c99d (diff)
Finish TestSession implementation for FaceProvider
Also moves static classes to top in face/aidl/Sensor.java Bug: 173453845 Test: atest CtsBiometricsTestCases Change-Id: I9220747161e3842494ac7d02c1c472037718a9f9
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java5
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/BiometricTestSessionImpl.java205
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceGetAuthenticatorIdClient.java5
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java16
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceResetLockoutClient.java5
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java207
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/TestHal.java98
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/TestSession.java102
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/BiometricTestSessionImpl.java2
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java47
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/TestSession.java2
11 files changed, 585 insertions, 109 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 2784f46a96c2..e8e9b9a6b8f6 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
@@ -564,6 +564,11 @@ public class BiometricScheduler {
public void dump(PrintWriter pw) {
pw.println("Dump of BiometricScheduler " + getTag());
+ pw.println("Current operation: " + mCurrentOperation);
+ pw.println("Pending operations: " + mPendingOperations.size());
+ for (Operation operation : mPendingOperations) {
+ pw.println("Pending operation: " + operation);
+ }
for (CrashState crashState : mCrashStates) {
pw.println("Crash State " + crashState);
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/BiometricTestSessionImpl.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/BiometricTestSessionImpl.java
new file mode 100644
index 000000000000..13bbb7e8a704
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/BiometricTestSessionImpl.java
@@ -0,0 +1,205 @@
+/*
+ * 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 com.android.server.biometrics.sensors.face.aidl;
+
+import static android.Manifest.permission.TEST_BIOMETRIC;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.hardware.biometrics.ITestSession;
+import android.hardware.face.Face;
+import android.hardware.face.IFaceServiceReceiver;
+import android.os.Binder;
+import android.util.Slog;
+
+import com.android.server.biometrics.HardwareAuthTokenUtils;
+import com.android.server.biometrics.Utils;
+import com.android.server.biometrics.sensors.face.FaceUtils;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Random;
+import java.util.Set;
+
+/**
+ * A test session implementation for {@link FaceProvider}. See
+ * {@link android.hardware.biometrics.BiometricTestSession}.
+ */
+public class BiometricTestSessionImpl extends ITestSession.Stub {
+
+ private static final String TAG = "BiometricTestSessionImpl";
+
+ @NonNull private final Context mContext;
+ private final int mSensorId;
+ @NonNull private final FaceProvider mProvider;
+ @NonNull private final Sensor mSensor;
+ @NonNull private final Set<Integer> mEnrollmentIds;
+ @NonNull private final Random mRandom;
+
+ /**
+ * Internal receiver currently only used for enroll. Results do not need to be forwarded to the
+ * test, since enrollment is a platform-only API. The authentication path is tested through
+ * the public BiometricPrompt APIs and does not use this receiver.
+ */
+ private final IFaceServiceReceiver mReceiver = new IFaceServiceReceiver.Stub() {
+ @Override
+ public void onEnrollResult(Face face, int remaining) {
+
+ }
+
+ @Override
+ public void onAcquired(int acquireInfo, int vendorCode) {
+
+ }
+
+ @Override
+ public void onAuthenticationSucceeded(Face face, int userId, boolean isStrongBiometric) {
+
+ }
+
+ @Override
+ public void onFaceDetected(int sensorId, int userId, boolean isStrongBiometric) {
+
+ }
+
+ @Override
+ public void onAuthenticationFailed() {
+
+ }
+
+ @Override
+ public void onError(int error, int vendorCode) {
+
+ }
+
+ @Override
+ public void onRemoved(Face face, int remaining) {
+
+ }
+
+ @Override
+ public void onFeatureSet(boolean success, int feature) {
+
+ }
+
+ @Override
+ public void onFeatureGet(boolean success, int feature, boolean value) {
+
+ }
+
+ @Override
+ public void onChallengeGenerated(int sensorId, long challenge) {
+
+ }
+
+ @Override
+ public void onChallengeInterrupted(int sensorId) {
+
+ }
+
+ @Override
+ public void onChallengeInterruptFinished(int sensorId) {
+
+ }
+ };
+
+ BiometricTestSessionImpl(@NonNull Context context, int sensorId,
+ @NonNull FaceProvider provider, @NonNull Sensor sensor) {
+ mContext = context;
+ mSensorId = sensorId;
+ mProvider = provider;
+ mSensor = sensor;
+ mEnrollmentIds = new HashSet<>();
+ mRandom = new Random();
+ }
+
+ @Override
+ public void setTestHalEnabled(boolean enabled) {
+ Utils.checkPermission(mContext, TEST_BIOMETRIC);
+
+ mProvider.setTestHalEnabled(enabled);
+ mSensor.setTestHalEnabled(enabled);
+ }
+
+ @Override
+ public void startEnroll(int userId) {
+ Utils.checkPermission(mContext, TEST_BIOMETRIC);
+
+ mProvider.scheduleEnroll(mSensorId, new Binder(), new byte[69], userId, mReceiver,
+ mContext.getOpPackageName(), new int[0] /* disabledFeatures */, null /* surface */);
+ }
+
+ @Override
+ public void finishEnroll(int userId) {
+ Utils.checkPermission(mContext, TEST_BIOMETRIC);
+
+ int nextRandomId = mRandom.nextInt();
+ while (mEnrollmentIds.contains(nextRandomId)) {
+ nextRandomId = mRandom.nextInt();
+ }
+
+ mEnrollmentIds.add(nextRandomId);
+ mSensor.getSessionForUser(userId).mHalSessionCallback
+ .onEnrollmentProgress(nextRandomId, 0 /* remaining */);
+ }
+
+ @Override
+ public void acceptAuthentication(int userId) {
+ Utils.checkPermission(mContext, TEST_BIOMETRIC);
+
+ // Fake authentication with any of the existing faces
+ List<Face> faces = FaceUtils.getInstance(mSensorId)
+ .getBiometricsForUser(mContext, userId);
+ if (faces.isEmpty()) {
+ Slog.w(TAG, "No faces, returning");
+ return;
+ }
+ final int fid = faces.get(0).getBiometricId();
+ mSensor.getSessionForUser(userId).mHalSessionCallback.onAuthenticationSucceeded(fid,
+ HardwareAuthTokenUtils.toHardwareAuthToken(new byte[69]));
+ }
+
+ @Override
+ public void rejectAuthentication(int userId) {
+ Utils.checkPermission(mContext, TEST_BIOMETRIC);
+
+ mSensor.getSessionForUser(userId).mHalSessionCallback.onAuthenticationFailed();
+ }
+
+ @Override
+ public void notifyAcquired(int userId, int acquireInfo) {
+ Utils.checkPermission(mContext, TEST_BIOMETRIC);
+
+ mSensor.getSessionForUser(userId).mHalSessionCallback
+ .onAcquired((byte) acquireInfo, 0 /* vendorCode */);
+ }
+
+ @Override
+ public void notifyError(int userId, int errorCode) {
+ Utils.checkPermission(mContext, TEST_BIOMETRIC);
+
+ mSensor.getSessionForUser(userId).mHalSessionCallback.onError((byte) errorCode,
+ 0 /* vendorCode */);
+ }
+
+ @Override
+ public void cleanupInternalState(int userId) {
+ Utils.checkPermission(mContext, TEST_BIOMETRIC);
+
+ mProvider.scheduleInternalCleanup(mSensorId, userId);
+ }
+}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceGetAuthenticatorIdClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceGetAuthenticatorIdClient.java
index 3280e9815660..c27b6e5a4b7d 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceGetAuthenticatorIdClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceGetAuthenticatorIdClient.java
@@ -47,6 +47,11 @@ class FaceGetAuthenticatorIdClient extends ClientMonitor<ISession> {
// Nothing to do here
}
+ public void start(@NonNull Callback callback) {
+ super.start(callback);
+ startHalOperation();
+ }
+
@Override
protected void startHalOperation() {
try {
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
index 01c16fd1f4a6..cb6b8d405635 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
@@ -67,6 +67,8 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
private static final String TAG = "FaceProvider";
private static final int ENROLL_TIMEOUT_SEC = 75;
+ private boolean mTestHalEnabled;
+
@NonNull private final Context mContext;
@NonNull private final String mHalInstanceName;
@NonNull private final SparseArray<Sensor> mSensors; // Map of sensors that this HAL supports
@@ -150,6 +152,10 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
@Nullable
private synchronized IFace getHalInstance() {
+ if (mTestHalEnabled) {
+ return new TestHal();
+ }
+
if (mDaemon != null) {
return mDaemon;
}
@@ -525,7 +531,9 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
@Override
public void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto) {
-
+ if (mSensors.contains(sensorId)) {
+ mSensors.get(sensorId).dumpProtoState(sensorId, proto);
+ }
}
@Override
@@ -576,7 +584,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
@NonNull
@Override
public ITestSession createTestSession(int sensorId, @NonNull String opPackageName) {
- return null; // TODO
+ return mSensors.get(sensorId).createTestSession();
}
@Override
@@ -590,4 +598,8 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
}
});
}
+
+ void setTestHalEnabled(boolean enabled) {
+ mTestHalEnabled = enabled;
+ }
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceResetLockoutClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceResetLockoutClient.java
index 5d100ec5e6dd..5b1f5465ea0a 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceResetLockoutClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceResetLockoutClient.java
@@ -61,6 +61,11 @@ public class FaceResetLockoutClient extends ClientMonitor<ISession> {
// Nothing to do here
}
+ public void start(@NonNull Callback callback) {
+ super.start(callback);
+ startHalOperation();
+ }
+
@Override
protected void startHalOperation() {
try {
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
index 2dd6e7375613..d9d473722fd5 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
@@ -19,7 +19,9 @@ package com.android.server.biometrics.sensors.face.aidl;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
+import android.content.pm.UserInfo;
import android.hardware.biometrics.BiometricsProtoEnums;
+import android.hardware.biometrics.ITestSession;
import android.hardware.biometrics.face.Error;
import android.hardware.biometrics.face.IFace;
import android.hardware.biometrics.face.ISession;
@@ -31,10 +33,15 @@ import android.hardware.keymaster.HardwareAuthToken;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
+import android.os.UserManager;
import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.util.FrameworkStatsLog;
import com.android.server.biometrics.HardwareAuthTokenUtils;
+import com.android.server.biometrics.SensorServiceStateProto;
+import com.android.server.biometrics.SensorStateProto;
+import com.android.server.biometrics.UserStateProto;
import com.android.server.biometrics.Utils;
import com.android.server.biometrics.sensors.AcquisitionClient;
import com.android.server.biometrics.sensors.AuthenticationConsumer;
@@ -56,6 +63,8 @@ import java.util.Map;
*/
public class Sensor implements IBinder.DeathRecipient {
+ private boolean mTestHalEnabled;
+
@NonNull private final String mTag;
@NonNull private final FaceProvider mProvider;
@NonNull private final Context mContext;
@@ -67,27 +76,6 @@ public class Sensor implements IBinder.DeathRecipient {
@NonNull private final ClientMonitor.LazyDaemon<ISession> mLazySession;
@Nullable private Session mCurrentSession;
- @Override
- public void binderDied() {
- Slog.e(mTag, "Binder died");
- mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
- if (client instanceof Interruptable) {
- Slog.e(mTag, "Sending ERROR_HW_UNAVAILABLE for client: " + client);
- final Interruptable interruptable = (Interruptable) client;
- interruptable.onError(FaceManager.FACE_ERROR_HW_UNAVAILABLE,
- 0 /* vendorCode */);
-
- mScheduler.recordCrashState();
-
- FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
- BiometricsProtoEnums.MODALITY_FACE,
- BiometricsProtoEnums.ISSUE_HAL_DEATH);
- mCurrentSession = null;
- }
- });
- }
-
static class Session {
@NonNull final HalSessionCallback mHalSessionCallback;
@NonNull private final String mTag;
@@ -104,67 +92,6 @@ public class Sensor implements IBinder.DeathRecipient {
}
}
- Sensor(@NonNull String tag, @NonNull FaceProvider provider, @NonNull Context context,
- @NonNull Handler handler, @NonNull FaceSensorPropertiesInternal sensorProperties) {
- mTag = tag;
- mProvider = provider;
- mContext = context;
- mHandler = handler;
- mSensorProperties = sensorProperties;
- mScheduler = new BiometricScheduler(tag, null /* gestureAvailabilityDispatcher */);
- mLockoutCache = new LockoutCache();
- mAuthenticatorIds = new HashMap<>();
- mLazySession = () -> (mCurrentSession != null) ? mCurrentSession.mSession : null;
- }
-
- @NonNull ClientMonitor.LazyDaemon<ISession> getLazySession() {
- return mLazySession;
- }
-
- @NonNull FaceSensorPropertiesInternal getSensorProperties() {
- return mSensorProperties;
- }
-
- @SuppressWarnings("BooleanMethodIsAlwaysInverted")
- boolean hasSessionForUser(int userId) {
- return mCurrentSession != null && mCurrentSession.mUserId == userId;
- }
-
- @Nullable Session getSessionForUser(int userId) {
- if (mCurrentSession != null && mCurrentSession.mUserId == userId) {
- return mCurrentSession;
- } else {
- return null;
- }
- }
-
- void createNewSession(@NonNull IFace daemon, int sensorId, int userId)
- throws RemoteException {
-
- final HalSessionCallback.Callback callback = () -> {
- Slog.e(mTag, "Got ERROR_HW_UNAVAILABLE");
- mCurrentSession = null;
- };
- final HalSessionCallback resultController = new HalSessionCallback(mContext, mHandler,
- mTag, mScheduler, sensorId, userId, callback);
-
- final ISession newSession = daemon.createSession(sensorId, userId, resultController);
- newSession.asBinder().linkToDeath(this, 0 /* flags */);
- mCurrentSession = new Session(mTag, newSession, userId, resultController);
- }
-
- @NonNull BiometricScheduler getScheduler() {
- return mScheduler;
- }
-
- @NonNull LockoutCache getLockoutCache() {
- return mLockoutCache;
- }
-
- @NonNull Map<Integer, Long> getAuthenticatorIds() {
- return mAuthenticatorIds;
- }
-
static class HalSessionCallback extends ISessionCallback.Stub {
/**
* Interface to sends results to the HalSessionCallback's owner.
@@ -453,4 +380,120 @@ public class Sensor implements IBinder.DeathRecipient {
}
}
+
+ Sensor(@NonNull String tag, @NonNull FaceProvider provider, @NonNull Context context,
+ @NonNull Handler handler, @NonNull FaceSensorPropertiesInternal sensorProperties) {
+ mTag = tag;
+ mProvider = provider;
+ mContext = context;
+ mHandler = handler;
+ mSensorProperties = sensorProperties;
+ mScheduler = new BiometricScheduler(tag, null /* gestureAvailabilityDispatcher */);
+ mLockoutCache = new LockoutCache();
+ mAuthenticatorIds = new HashMap<>();
+ mLazySession = () -> {
+ if (mTestHalEnabled) {
+ return new TestSession(mCurrentSession.mHalSessionCallback);
+ } else {
+ return mCurrentSession != null ? mCurrentSession.mSession : null;
+ }
+ };
+ }
+
+ @NonNull ClientMonitor.LazyDaemon<ISession> getLazySession() {
+ return mLazySession;
+ }
+
+ @NonNull FaceSensorPropertiesInternal getSensorProperties() {
+ return mSensorProperties;
+ }
+
+ @SuppressWarnings("BooleanMethodIsAlwaysInverted")
+ boolean hasSessionForUser(int userId) {
+ return mCurrentSession != null && mCurrentSession.mUserId == userId;
+ }
+
+ @Nullable Session getSessionForUser(int userId) {
+ if (mCurrentSession != null && mCurrentSession.mUserId == userId) {
+ return mCurrentSession;
+ } else {
+ return null;
+ }
+ }
+
+ @NonNull ITestSession createTestSession() {
+ return new BiometricTestSessionImpl(mContext, mSensorProperties.sensorId, mProvider, this);
+ }
+
+ void createNewSession(@NonNull IFace daemon, int sensorId, int userId)
+ throws RemoteException {
+
+ final HalSessionCallback.Callback callback = () -> {
+ Slog.e(mTag, "Got ERROR_HW_UNAVAILABLE");
+ mCurrentSession = null;
+ };
+ final HalSessionCallback resultController = new HalSessionCallback(mContext, mHandler,
+ mTag, mScheduler, sensorId, userId, callback);
+
+ final ISession newSession = daemon.createSession(sensorId, userId, resultController);
+ newSession.asBinder().linkToDeath(this, 0 /* flags */);
+ mCurrentSession = new Session(mTag, newSession, userId, resultController);
+ }
+
+ @NonNull BiometricScheduler getScheduler() {
+ return mScheduler;
+ }
+
+ @NonNull LockoutCache getLockoutCache() {
+ return mLockoutCache;
+ }
+
+ @NonNull Map<Integer, Long> getAuthenticatorIds() {
+ return mAuthenticatorIds;
+ }
+
+ void setTestHalEnabled(boolean enabled) {
+ mTestHalEnabled = enabled;
+ }
+
+ void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto) {
+ final long sensorToken = proto.start(SensorServiceStateProto.SENSOR_STATES);
+
+ proto.write(SensorStateProto.SENSOR_ID, mSensorProperties.sensorId);
+ proto.write(SensorStateProto.IS_BUSY, mScheduler.getCurrentClient() != null);
+
+ for (UserInfo user : UserManager.get(mContext).getUsers()) {
+ final int userId = user.getUserHandle().getIdentifier();
+
+ final long userToken = proto.start(SensorStateProto.USER_STATES);
+ proto.write(UserStateProto.USER_ID, userId);
+ proto.write(UserStateProto.NUM_ENROLLED,
+ FaceUtils.getInstance(mSensorProperties.sensorId)
+ .getBiometricsForUser(mContext, userId).size());
+ proto.end(userToken);
+ }
+
+ proto.end(sensorToken);
+ }
+
+ @Override
+ public void binderDied() {
+ Slog.e(mTag, "Binder died");
+ mHandler.post(() -> {
+ final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ if (client instanceof Interruptable) {
+ Slog.e(mTag, "Sending ERROR_HW_UNAVAILABLE for client: " + client);
+ final Interruptable interruptable = (Interruptable) client;
+ interruptable.onError(FaceManager.FACE_ERROR_HW_UNAVAILABLE,
+ 0 /* vendorCode */);
+
+ mScheduler.recordCrashState();
+
+ FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
+ BiometricsProtoEnums.MODALITY_FACE,
+ BiometricsProtoEnums.ISSUE_HAL_DEATH);
+ mCurrentSession = null;
+ }
+ });
+ }
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestHal.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestHal.java
new file mode 100644
index 000000000000..34bf9bc63a64
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestHal.java
@@ -0,0 +1,98 @@
+/*
+ * 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 com.android.server.biometrics.sensors.face.aidl;
+
+import android.hardware.biometrics.common.ICancellationSignal;
+import android.hardware.biometrics.face.IFace;
+import android.hardware.biometrics.face.ISession;
+import android.hardware.biometrics.face.ISessionCallback;
+import android.hardware.biometrics.face.SensorProps;
+import android.hardware.common.NativeHandle;
+import android.hardware.keymaster.HardwareAuthToken;
+import android.os.Binder;
+import android.os.IBinder;
+
+/**
+ * Test HAL that provides only no-ops.
+ */
+public class TestHal extends IFace.Stub {
+ @Override
+ public SensorProps[] getSensorProps() {
+ return new SensorProps[0];
+ }
+
+ @Override
+ public ISession createSession(int sensorId, int userId, ISessionCallback cb) {
+ return new ISession() {
+ @Override
+ public void generateChallenge(int cookie, int timeoutSec) {
+
+ }
+
+ @Override
+ public void revokeChallenge(int cookie, long challenge) {
+
+ }
+
+ @Override
+ public ICancellationSignal enroll(int cookie, HardwareAuthToken hat,
+ NativeHandle previewSurface) {
+ return null;
+ }
+
+ @Override
+ public ICancellationSignal authenticate(int cookie, long operationId) {
+ return null;
+ }
+
+ @Override
+ public ICancellationSignal detectInteraction(int cookie) {
+ return null;
+ }
+
+ @Override
+ public void enumerateEnrollments(int cookie) {
+
+ }
+
+ @Override
+ public void removeEnrollments(int cookie, int[] enrollmentIds) {
+
+ }
+
+ @Override
+ public void getAuthenticatorId(int cookie) {
+
+ }
+
+ @Override
+ public void invalidateAuthenticatorId(int cookie) {
+
+ }
+
+ @Override
+ public void resetLockout(int cookie, HardwareAuthToken hat) {
+
+ }
+
+ @Override
+ public IBinder asBinder() {
+ return new Binder();
+ }
+ };
+ }
+}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestSession.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestSession.java
new file mode 100644
index 000000000000..9707eddfee74
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestSession.java
@@ -0,0 +1,102 @@
+/*
+ * 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 com.android.server.biometrics.sensors.face.aidl;
+
+import android.annotation.NonNull;
+import android.hardware.biometrics.common.ICancellationSignal;
+import android.hardware.biometrics.face.Error;
+import android.hardware.biometrics.face.ISession;
+import android.hardware.common.NativeHandle;
+import android.hardware.keymaster.HardwareAuthToken;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+/**
+ * Test session that provides mostly no-ops.
+ */
+public class TestSession extends ISession.Stub {
+ private static final String TAG = "TestSession";
+
+ @NonNull
+ private final Sensor.HalSessionCallback mHalSessionCallback;
+
+ TestSession(@NonNull Sensor.HalSessionCallback halSessionCallback) {
+ mHalSessionCallback = halSessionCallback;
+ }
+
+ @Override
+ public void generateChallenge(int cookie, int timeoutSec) {
+ mHalSessionCallback.onChallengeGenerated(0 /* challenge */);
+ }
+
+ @Override
+ public void revokeChallenge(int cookie, long challenge) {
+ mHalSessionCallback.onChallengeRevoked(challenge);
+ }
+
+ @Override
+ public ICancellationSignal enroll(int cookie, HardwareAuthToken hat,
+ NativeHandle previewSurface) {
+ return null;
+ }
+
+ @Override
+ public ICancellationSignal authenticate(int cookie, long operationId) {
+ return new ICancellationSignal() {
+ @Override
+ public void cancel() throws RemoteException {
+ mHalSessionCallback.onError(Error.CANCELED, 0 /* vendorCode */);
+ }
+
+ @Override
+ public IBinder asBinder() {
+ return new Binder();
+ }
+ };
+ }
+
+ @Override
+ public ICancellationSignal detectInteraction(int cookie) {
+ return null;
+ }
+
+ @Override
+ public void enumerateEnrollments(int cookie) {
+
+ }
+
+ @Override
+ public void removeEnrollments(int cookie, int[] enrollmentIds) {
+
+ }
+
+ @Override
+ public void getAuthenticatorId(int cookie) {
+ mHalSessionCallback.onAuthenticatorIdRetrieved(0);
+ }
+
+ @Override
+ public void invalidateAuthenticatorId(int cookie) {
+
+ }
+
+ @Override
+ public void resetLockout(int cookie, HardwareAuthToken hat) {
+ mHalSessionCallback.onLockoutCleared();
+ }
+}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/BiometricTestSessionImpl.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/BiometricTestSessionImpl.java
index 973132533661..3f9aef2b8651 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/BiometricTestSessionImpl.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/BiometricTestSessionImpl.java
@@ -143,7 +143,7 @@ class BiometricTestSessionImpl extends ITestSession.Stub {
Utils.checkPermission(mContext, TEST_BIOMETRIC);
// Fake authentication with any of the existing fingers
- List<Fingerprint> fingerprints = FingerprintUtils.getInstance()
+ List<Fingerprint> fingerprints = FingerprintUtils.getInstance(mSensorId)
.getBiometricsForUser(mContext, userId);
if (fingerprints.isEmpty()) {
Slog.w(TAG, "No fingerprints, returning");
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
index 380608f1b0a9..ecb998594d44 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
@@ -80,27 +80,6 @@ class Sensor implements IBinder.DeathRecipient {
@Nullable private Session mCurrentSession;
@NonNull private final ClientMonitor.LazyDaemon<ISession> mLazySession;
- @Override
- public void binderDied() {
- Slog.e(mTag, "Binder died");
- mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
- if (client instanceof Interruptable) {
- Slog.e(mTag, "Sending ERROR_HW_UNAVAILABLE for client: " + client);
- final Interruptable interruptable = (Interruptable) client;
- interruptable.onError(FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE,
- 0 /* vendorCode */);
-
- mScheduler.recordCrashState();
-
- FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
- BiometricsProtoEnums.MODALITY_FINGERPRINT,
- BiometricsProtoEnums.ISSUE_HAL_DEATH);
- mCurrentSession = null;
- }
- });
- }
-
static class Session {
@NonNull private final String mTag;
@NonNull private final ISession mSession;
@@ -501,11 +480,33 @@ class Sensor implements IBinder.DeathRecipient {
final long userToken = proto.start(SensorStateProto.USER_STATES);
proto.write(UserStateProto.USER_ID, userId);
- proto.write(UserStateProto.NUM_ENROLLED, FingerprintUtils.getInstance()
- .getBiometricsForUser(mContext, userId).size());
+ proto.write(UserStateProto.NUM_ENROLLED,
+ FingerprintUtils.getInstance(mSensorProperties.sensorId)
+ .getBiometricsForUser(mContext, userId).size());
proto.end(userToken);
}
proto.end(sensorToken);
}
+
+ @Override
+ public void binderDied() {
+ Slog.e(mTag, "Binder died");
+ mHandler.post(() -> {
+ final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ if (client instanceof Interruptable) {
+ Slog.e(mTag, "Sending ERROR_HW_UNAVAILABLE for client: " + client);
+ final Interruptable interruptable = (Interruptable) client;
+ interruptable.onError(FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE,
+ 0 /* vendorCode */);
+
+ mScheduler.recordCrashState();
+
+ FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
+ BiometricsProtoEnums.MODALITY_FINGERPRINT,
+ BiometricsProtoEnums.ISSUE_HAL_DEATH);
+ mCurrentSession = null;
+ }
+ });
+ }
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/TestSession.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/TestSession.java
index dd9150a32914..d6378780594f 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/TestSession.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/TestSession.java
@@ -23,7 +23,7 @@ import android.hardware.keymaster.HardwareAuthToken;
import android.util.Slog;
/**
- * Test HAL that provides only provides mostly no-ops.
+ * Test session that provides mostly no-ops.
*/
class TestSession extends ISession.Stub {