summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Diya Bera <diyab@google.com> 2023-05-01 18:25:44 +0000
committer Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> 2023-05-01 18:25:44 +0000
commitdc661b7ccbd8f4f1eb2a2f4104daa174d2940b98 (patch)
tree768241f6a4aa5b8ad5f9eaea98ac6e894863b31b
parentd67eaa8483a3af25f1596ab61944d9afd8ae6c77 (diff)
parentc6ba932666bd1d7a45aa52a2d4f0f947054ee18e (diff)
Merge "Start fingerprint user client on reboot" into udc-dev am: a539a7f34c am: 234c0b368a am: c6ba932666
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/22776337 Change-Id: Ie1e39f96e96a7921a31436cf0b47d828baa26edc Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/SensorList.java97
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java112
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java17
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java169
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java17
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/SensorListTest.java66
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceProviderTest.java30
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/SensorTest.java41
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java36
9 files changed, 394 insertions, 191 deletions
diff --git a/services/core/java/com/android/server/biometrics/sensors/SensorList.java b/services/core/java/com/android/server/biometrics/sensors/SensorList.java
new file mode 100644
index 000000000000..1cff92fba31d
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/sensors/SensorList.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2023 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 android.app.IActivityManager;
+import android.app.SynchronousUserSwitchObserver;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Slog;
+import android.util.SparseArray;
+
+/**
+ * Keep track of the sensors that is supported by the HAL.
+ * @param <T> T is either face sensor or fingerprint sensor.
+ */
+public class SensorList<T> {
+ private static final String TAG = "SensorList";
+ private final SparseArray<T> mSensors;
+ private final IActivityManager mActivityManager;
+
+ public SensorList(IActivityManager activityManager) {
+ mSensors = new SparseArray<T>();
+ mActivityManager = activityManager;
+ }
+
+ /**
+ * Adding sensor to the map with the sensor id as key. Also, starts a session if the user Id is
+ * NULL.
+ */
+ public void addSensor(int sensorId, T sensor, int sessionUserId,
+ SynchronousUserSwitchObserver userSwitchObserver) {
+ mSensors.put(sensorId, sensor);
+ registerUserSwitchObserver(sessionUserId, userSwitchObserver);
+ }
+
+ private void registerUserSwitchObserver(int sessionUserId,
+ SynchronousUserSwitchObserver userSwitchObserver) {
+ try {
+ mActivityManager.registerUserSwitchObserver(userSwitchObserver,
+ TAG);
+ if (sessionUserId == UserHandle.USER_NULL) {
+ userSwitchObserver.onUserSwitching(UserHandle.USER_SYSTEM);
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unable to register user switch observer");
+ }
+ }
+
+ /**
+ * Returns the sensor corresponding to the key at a specific position.
+ */
+ public T valueAt(int position) {
+ return mSensors.valueAt(position);
+ }
+
+ /**
+ * Returns the sensor associated with sensorId as key.
+ */
+ public T get(int sensorId) {
+ return mSensors.get(sensorId);
+ }
+
+ /**
+ * Returns the sensorId at the specified position.
+ */
+ public int keyAt(int position) {
+ return mSensors.keyAt(position);
+ }
+
+ /**
+ * Returns the number of sensors added.
+ */
+ public int size() {
+ return mSensors.size();
+ }
+
+ /**
+ * Returns true if a sensor exists for the specified sensorId.
+ */
+ public boolean contains(int sensorId) {
+ return mSensors.contains(sensorId);
+ }
+}
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 c5037b7012f2..a50164718417 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
@@ -20,6 +20,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
+import android.app.SynchronousUserSwitchObserver;
import android.app.TaskStackListener;
import android.content.Context;
import android.content.pm.UserInfo;
@@ -41,9 +42,9 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.UserHandle;
import android.os.UserManager;
import android.util.Slog;
-import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
import android.view.Surface;
@@ -62,6 +63,7 @@ import com.android.server.biometrics.sensors.ClientMonitorCompositeCallback;
import com.android.server.biometrics.sensors.InvalidationRequesterClient;
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
import com.android.server.biometrics.sensors.PerformanceTracker;
+import com.android.server.biometrics.sensors.SensorList;
import com.android.server.biometrics.sensors.face.FaceUtils;
import com.android.server.biometrics.sensors.face.ServiceProvider;
import com.android.server.biometrics.sensors.face.UsageStats;
@@ -86,7 +88,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
@NonNull
@VisibleForTesting
- final SparseArray<Sensor> mSensors; // Map of sensors that this HAL supports
+ final SensorList<Sensor> mFaceSensors;
@NonNull
private final Context mContext;
@NonNull
@@ -117,8 +119,8 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
@Override
public void onTaskStackChanged() {
mHandler.post(() -> {
- for (int i = 0; i < mSensors.size(); i++) {
- final BaseClientMonitor client = mSensors.valueAt(i).getScheduler()
+ for (int i = 0; i < mFaceSensors.size(); i++) {
+ final BaseClientMonitor client = mFaceSensors.valueAt(i).getScheduler()
.getCurrentClient();
if (!(client instanceof AuthenticationClient)) {
Slog.e(getTag(), "Task stack changed for client: " + client);
@@ -133,7 +135,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
&& !client.isAlreadyDone()) {
Slog.e(getTag(), "Stopping background authentication,"
+ " currentClient: " + client);
- mSensors.valueAt(i).getScheduler().cancelAuthenticationOrDetection(
+ mFaceSensors.valueAt(i).getScheduler().cancelAuthenticationOrDetection(
client.getToken(), client.getRequestId());
}
}
@@ -150,7 +152,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
mContext = context;
mBiometricStateCallback = biometricStateCallback;
mHalInstanceName = halInstanceName;
- mSensors = new SparseArray<>();
+ mFaceSensors = new SensorList<>(ActivityManager.getService());
mHandler = new Handler(Looper.getMainLooper());
mUsageStats = new UsageStats(context);
mLockoutResetDispatcher = lockoutResetDispatcher;
@@ -178,8 +180,15 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
false /* resetLockoutRequiresChallenge */);
final Sensor sensor = new Sensor(getTag() + "/" + sensorId, this, mContext, mHandler,
internalProp, lockoutResetDispatcher, mBiometricContext);
-
- mSensors.put(sensorId, sensor);
+ final int userId = sensor.getLazySession().get() == null ? UserHandle.USER_NULL :
+ sensor.getLazySession().get().getUserId();
+ mFaceSensors.addSensor(sensorId, sensor, userId,
+ new SynchronousUserSwitchObserver() {
+ @Override
+ public void onUserSwitching(int newUserId) {
+ scheduleInternalCleanup(sensorId, newUserId, null /* callback */);
+ }
+ });
Slog.d(getTag(), "Added: " + internalProp);
}
}
@@ -223,8 +232,8 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
Slog.e(getTag(), "Unable to linkToDeath", e);
}
- for (int i = 0; i < mSensors.size(); i++) {
- final int sensorId = mSensors.keyAt(i);
+ for (int i = 0; i < mFaceSensors.size(); i++) {
+ final int sensorId = mFaceSensors.keyAt(i);
scheduleLoadAuthenticatorIds(sensorId);
scheduleInternalCleanup(sensorId, ActivityManager.getCurrentUser(),
null /* callback */);
@@ -234,20 +243,20 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
}
private void scheduleForSensor(int sensorId, @NonNull BaseClientMonitor client) {
- if (!mSensors.contains(sensorId)) {
+ if (!mFaceSensors.contains(sensorId)) {
throw new IllegalStateException("Unable to schedule client: " + client
+ " for sensor: " + sensorId);
}
- mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client);
+ mFaceSensors.get(sensorId).getScheduler().scheduleClientMonitor(client);
}
private void scheduleForSensor(int sensorId, @NonNull BaseClientMonitor client,
ClientMonitorCallback callback) {
- if (!mSensors.contains(sensorId)) {
+ if (!mFaceSensors.contains(sensorId)) {
throw new IllegalStateException("Unable to schedule client: " + client
+ " for sensor: " + sensorId);
}
- mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client, callback);
+ mFaceSensors.get(sensorId).getScheduler().scheduleClientMonitor(client, callback);
}
private void scheduleLoadAuthenticatorIds(int sensorId) {
@@ -259,12 +268,12 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
private void scheduleLoadAuthenticatorIdsForUser(int sensorId, int userId) {
mHandler.post(() -> {
final FaceGetAuthenticatorIdClient client = new FaceGetAuthenticatorIdClient(
- mContext, mSensors.get(sensorId).getLazySession(), userId,
+ mContext, mFaceSensors.get(sensorId).getLazySession(), userId,
mContext.getOpPackageName(), sensorId,
createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
BiometricsProtoEnums.CLIENT_UNKNOWN),
mBiometricContext,
- mSensors.get(sensorId).getAuthenticatorIds());
+ mFaceSensors.get(sensorId).getAuthenticatorIds());
scheduleForSensor(sensorId, client);
});
@@ -283,15 +292,15 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
@Override
public boolean containsSensor(int sensorId) {
- return mSensors.contains(sensorId);
+ return mFaceSensors.contains(sensorId);
}
@NonNull
@Override
public List<FaceSensorPropertiesInternal> getSensorProperties() {
final List<FaceSensorPropertiesInternal> props = new ArrayList<>();
- for (int i = 0; i < mSensors.size(); ++i) {
- props.add(mSensors.valueAt(i).getSensorProperties());
+ for (int i = 0; i < mFaceSensors.size(); ++i) {
+ props.add(mFaceSensors.valueAt(i).getSensorProperties());
}
return props;
}
@@ -299,7 +308,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
@NonNull
@Override
public FaceSensorPropertiesInternal getSensorProperties(int sensorId) {
- return mSensors.get(sensorId).getSensorProperties();
+ return mFaceSensors.get(sensorId).getSensorProperties();
}
@NonNull
@@ -318,11 +327,11 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
@NonNull IInvalidationCallback callback) {
mHandler.post(() -> {
final FaceInvalidationClient client = new FaceInvalidationClient(mContext,
- mSensors.get(sensorId).getLazySession(), userId, sensorId,
+ mFaceSensors.get(sensorId).getLazySession(), userId, sensorId,
createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
BiometricsProtoEnums.CLIENT_UNKNOWN),
mBiometricContext,
- mSensors.get(sensorId).getAuthenticatorIds(), callback);
+ mFaceSensors.get(sensorId).getAuthenticatorIds(), callback);
scheduleForSensor(sensorId, client);
});
}
@@ -335,7 +344,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
@Override
public long getAuthenticatorId(int sensorId, int userId) {
- return mSensors.get(sensorId).getAuthenticatorIds().getOrDefault(userId, 0L);
+ return mFaceSensors.get(sensorId).getAuthenticatorIds().getOrDefault(userId, 0L);
}
@Override
@@ -348,7 +357,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
@NonNull IFaceServiceReceiver receiver, String opPackageName) {
mHandler.post(() -> {
final FaceGenerateChallengeClient client = new FaceGenerateChallengeClient(mContext,
- mSensors.get(sensorId).getLazySession(), token,
+ mFaceSensors.get(sensorId).getLazySession(), token,
new ClientMonitorCallbackConverter(receiver), userId, opPackageName, sensorId,
createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
BiometricsProtoEnums.CLIENT_UNKNOWN),
@@ -362,7 +371,8 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
@NonNull String opPackageName, long challenge) {
mHandler.post(() -> {
final FaceRevokeChallengeClient client = new FaceRevokeChallengeClient(mContext,
- mSensors.get(sensorId).getLazySession(), token, userId, opPackageName, sensorId,
+ mFaceSensors.get(sensorId).getLazySession(), token, userId,
+ opPackageName, sensorId,
createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
BiometricsProtoEnums.CLIENT_UNKNOWN),
mBiometricContext, challenge);
@@ -377,10 +387,10 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
@Nullable Surface previewSurface, boolean debugConsent) {
final long id = mRequestCounter.incrementAndGet();
mHandler.post(() -> {
- final int maxTemplatesPerUser = mSensors.get(
+ final int maxTemplatesPerUser = mFaceSensors.get(
sensorId).getSensorProperties().maxEnrollmentsPerUser;
final FaceEnrollClient client = new FaceEnrollClient(mContext,
- mSensors.get(sensorId).getLazySession(), token,
+ mFaceSensors.get(sensorId).getLazySession(), token,
new ClientMonitorCallbackConverter(receiver), userId, hardwareAuthToken,
opPackageName, id, FaceUtils.getInstance(sensorId), disabledFeatures,
ENROLL_TIMEOUT_SEC, previewSurface, sensorId,
@@ -406,7 +416,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
@Override
public void cancelEnrollment(int sensorId, @NonNull IBinder token, long requestId) {
mHandler.post(() ->
- mSensors.get(sensorId).getScheduler().cancelEnrollment(token, requestId));
+ mFaceSensors.get(sensorId).getScheduler().cancelEnrollment(token, requestId));
}
@Override
@@ -419,7 +429,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
mHandler.post(() -> {
final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId);
final FaceDetectClient client = new FaceDetectClient(mContext,
- mSensors.get(sensorId).getLazySession(),
+ mFaceSensors.get(sensorId).getLazySession(),
token, id, callback, options,
createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient),
mBiometricContext, isStrongBiometric);
@@ -431,7 +441,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
@Override
public void cancelFaceDetect(int sensorId, @NonNull IBinder token, long requestId) {
- mHandler.post(() -> mSensors.get(sensorId).getScheduler()
+ mHandler.post(() -> mFaceSensors.get(sensorId).getScheduler()
.cancelAuthenticationOrDetection(token, requestId));
}
@@ -446,12 +456,12 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
final int sensorId = options.getSensorId();
final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId);
final FaceAuthenticationClient client = new FaceAuthenticationClient(
- mContext, mSensors.get(sensorId).getLazySession(), token, requestId, callback,
- operationId, restricted, options, cookie,
+ mContext, mFaceSensors.get(sensorId).getLazySession(), token, requestId,
+ callback, operationId, restricted, options, cookie,
false /* requireConfirmation */,
createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient),
mBiometricContext, isStrongBiometric,
- mUsageStats, mSensors.get(sensorId).getLockoutCache(),
+ mUsageStats, mFaceSensors.get(sensorId).getLockoutCache(),
allowBackgroundAuthentication, Utils.getCurrentStrength(sensorId));
scheduleForSensor(sensorId, client, new ClientMonitorCallback() {
@Override
@@ -486,7 +496,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
@Override
public void cancelAuthentication(int sensorId, @NonNull IBinder token, long requestId) {
- mHandler.post(() -> mSensors.get(sensorId).getScheduler()
+ mHandler.post(() -> mFaceSensors.get(sensorId).getScheduler()
.cancelAuthenticationOrDetection(token, requestId));
}
@@ -514,13 +524,13 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
int userId, @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName) {
mHandler.post(() -> {
final FaceRemovalClient client = new FaceRemovalClient(mContext,
- mSensors.get(sensorId).getLazySession(), token,
+ mFaceSensors.get(sensorId).getLazySession(), token,
new ClientMonitorCallbackConverter(receiver), faceIds, userId,
opPackageName, FaceUtils.getInstance(sensorId), sensorId,
createLogger(BiometricsProtoEnums.ACTION_REMOVE,
BiometricsProtoEnums.CLIENT_UNKNOWN),
mBiometricContext,
- mSensors.get(sensorId).getAuthenticatorIds());
+ mFaceSensors.get(sensorId).getAuthenticatorIds());
scheduleForSensor(sensorId, client, mBiometricStateCallback);
});
}
@@ -529,12 +539,12 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
public void scheduleResetLockout(int sensorId, int userId, @NonNull byte[] hardwareAuthToken) {
mHandler.post(() -> {
final FaceResetLockoutClient client = new FaceResetLockoutClient(
- mContext, mSensors.get(sensorId).getLazySession(), userId,
+ mContext, mFaceSensors.get(sensorId).getLazySession(), userId,
mContext.getOpPackageName(), sensorId,
createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
BiometricsProtoEnums.CLIENT_UNKNOWN),
mBiometricContext, hardwareAuthToken,
- mSensors.get(sensorId).getLockoutCache(), mLockoutResetDispatcher,
+ mFaceSensors.get(sensorId).getLockoutCache(), mLockoutResetDispatcher,
Utils.getCurrentStrength(sensorId));
scheduleForSensor(sensorId, client);
@@ -553,7 +563,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
return;
}
final FaceSetFeatureClient client = new FaceSetFeatureClient(mContext,
- mSensors.get(sensorId).getLazySession(), token,
+ mFaceSensors.get(sensorId).getLazySession(), token,
new ClientMonitorCallbackConverter(receiver), userId,
mContext.getOpPackageName(), sensorId,
BiometricLogger.ofUnknown(mContext), mBiometricContext,
@@ -573,7 +583,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
return;
}
final FaceGetFeatureClient client = new FaceGetFeatureClient(mContext,
- mSensors.get(sensorId).getLazySession(), token, callback, userId,
+ mFaceSensors.get(sensorId).getLazySession(), token, callback, userId,
mContext.getOpPackageName(), sensorId, BiometricLogger.ofUnknown(mContext),
mBiometricContext);
scheduleForSensor(sensorId, client);
@@ -583,7 +593,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
@Override
public void startPreparedClient(int sensorId, int cookie) {
mHandler.post(() -> {
- mSensors.get(sensorId).getScheduler().startPreparedClient(cookie);
+ mFaceSensors.get(sensorId).getScheduler().startPreparedClient(cookie);
});
}
@@ -599,13 +609,13 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
mHandler.post(() -> {
final FaceInternalCleanupClient client =
new FaceInternalCleanupClient(mContext,
- mSensors.get(sensorId).getLazySession(), userId,
+ mFaceSensors.get(sensorId).getLazySession(), userId,
mContext.getOpPackageName(), sensorId,
createLogger(BiometricsProtoEnums.ACTION_ENUMERATE,
BiometricsProtoEnums.CLIENT_UNKNOWN),
mBiometricContext,
FaceUtils.getInstance(sensorId),
- mSensors.get(sensorId).getAuthenticatorIds());
+ mFaceSensors.get(sensorId).getAuthenticatorIds());
if (favorHalEnrollments) {
client.setFavorHalEnrollments();
}
@@ -622,8 +632,8 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
@Override
public void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto,
boolean clearSchedulerBuffer) {
- if (mSensors.contains(sensorId)) {
- mSensors.get(sensorId).dumpProtoState(sensorId, proto, clearSchedulerBuffer);
+ if (mFaceSensors.contains(sensorId)) {
+ mFaceSensors.get(sensorId).dumpProtoState(sensorId, proto, clearSchedulerBuffer);
}
}
@@ -672,7 +682,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
pw.println(mBiometricContext.getAuthSessionCoordinator());
pw.println("---AuthSessionCoordinator logs end ---");
- mSensors.get(sensorId).getScheduler().dump(pw);
+ mFaceSensors.get(sensorId).getScheduler().dump(pw);
mUsageStats.print(pw);
}
@@ -680,7 +690,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
@Override
public ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback,
@NonNull String opPackageName) {
- return mSensors.get(sensorId).createTestSession(callback);
+ return mFaceSensors.get(sensorId).createTestSession(callback);
}
@Override
@@ -692,9 +702,9 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
Slog.e(getTag(), "HAL died");
mHandler.post(() -> {
mDaemon = null;
- for (int i = 0; i < mSensors.size(); i++) {
- final Sensor sensor = mSensors.valueAt(i);
- final int sensorId = mSensors.keyAt(i);
+ for (int i = 0; i < mFaceSensors.size(); i++) {
+ final Sensor sensor = mFaceSensors.valueAt(i);
+ final int sensorId = mFaceSensors.keyAt(i);
PerformanceTracker.getInstanceForSensorId(sensorId).incrementHALDeathCount();
sensor.onBinderDied();
}
@@ -708,7 +718,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
@Override
public void scheduleWatchdog(int sensorId) {
Slog.d(getTag(), "Starting watchdog for face");
- final BiometricScheduler biometricScheduler = mSensors.get(sensorId).getScheduler();
+ final BiometricScheduler biometricScheduler = mFaceSensors.get(sensorId).getScheduler();
if (biometricScheduler == null) {
return;
}
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 468bf5530d34..ffbf4e12f2ae 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
@@ -18,9 +18,6 @@ package com.android.server.biometrics.sensors.face.aidl;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.ActivityManager;
-import android.app.SynchronousUserSwitchObserver;
-import android.app.UserSwitchObserver;
import android.content.Context;
import android.content.pm.UserInfo;
import android.hardware.biometrics.BiometricsProtoEnums;
@@ -94,14 +91,6 @@ public class Sensor {
@NonNull private final Supplier<AidlSession> mLazySession;
@Nullable private AidlSession mCurrentSession;
- private final UserSwitchObserver mUserSwitchObserver = new SynchronousUserSwitchObserver() {
- @Override
- public void onUserSwitching(int newUserId) {
- mProvider.scheduleInternalCleanup(
- mSensorProperties.sensorId, newUserId, null /* callback */);
- }
- };
-
@VisibleForTesting
public static class HalSessionCallback extends ISessionCallback.Stub {
/**
@@ -558,12 +547,6 @@ public class Sensor {
mLockoutCache = new LockoutCache();
mAuthenticatorIds = new HashMap<>();
mLazySession = () -> mCurrentSession != null ? mCurrentSession : null;
-
- try {
- ActivityManager.getService().registerUserSwitchObserver(mUserSwitchObserver, mTag);
- } catch (RemoteException e) {
- Slog.e(mTag, "Unable to register user switch observer");
- }
}
@NonNull Supplier<AidlSession> getLazySession() {
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
index 23b6f84e6954..58ece898a9fe 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
@@ -22,6 +22,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
+import android.app.SynchronousUserSwitchObserver;
import android.app.TaskStackListener;
import android.content.Context;
import android.content.pm.UserInfo;
@@ -51,9 +52,9 @@ import android.os.Looper;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
+import android.os.UserHandle;
import android.os.UserManager;
import android.util.Slog;
-import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
@@ -71,6 +72,7 @@ import com.android.server.biometrics.sensors.ClientMonitorCompositeCallback;
import com.android.server.biometrics.sensors.InvalidationRequesterClient;
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
import com.android.server.biometrics.sensors.PerformanceTracker;
+import com.android.server.biometrics.sensors.SensorList;
import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils;
import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher;
import com.android.server.biometrics.sensors.fingerprint.PowerPressHandler;
@@ -99,7 +101,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
@NonNull
@VisibleForTesting
- final SparseArray<Sensor> mSensors; // Map of sensors that this HAL supports
+ final SensorList<Sensor> mFingerprintSensors;
@NonNull
private final Context mContext;
@NonNull
@@ -127,8 +129,8 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
@Override
public void onTaskStackChanged() {
mHandler.post(() -> {
- for (int i = 0; i < mSensors.size(); i++) {
- final BaseClientMonitor client = mSensors.valueAt(i).getScheduler()
+ for (int i = 0; i < mFingerprintSensors.size(); i++) {
+ final BaseClientMonitor client = mFingerprintSensors.valueAt(i).getScheduler()
.getCurrentClient();
if (!(client instanceof AuthenticationClient)) {
Slog.e(getTag(), "Task stack changed for client: " + client);
@@ -143,8 +145,9 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
&& !client.isAlreadyDone()) {
Slog.e(getTag(), "Stopping background authentication,"
+ " currentClient: " + client);
- mSensors.valueAt(i).getScheduler().cancelAuthenticationOrDetection(
- client.getToken(), client.getRequestId());
+ mFingerprintSensors.valueAt(i).getScheduler()
+ .cancelAuthenticationOrDetection(
+ client.getToken(), client.getRequestId());
}
}
});
@@ -160,7 +163,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
mContext = context;
mBiometricStateCallback = biometricStateCallback;
mHalInstanceName = halInstanceName;
- mSensors = new SparseArray<>();
+ mFingerprintSensors = new SensorList<>(ActivityManager.getService());
mHandler = new Handler(Looper.getMainLooper());
mLockoutResetDispatcher = lockoutResetDispatcher;
mActivityTaskManager = ActivityTaskManager.getInstance();
@@ -201,8 +204,15 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
final Sensor sensor = new Sensor(getTag() + "/" + sensorId, this, mContext, mHandler,
internalProp, lockoutResetDispatcher, gestureAvailabilityDispatcher,
mBiometricContext);
-
- mSensors.put(sensorId, sensor);
+ final int sessionUserId = sensor.getLazySession().get() == null ? UserHandle.USER_NULL :
+ sensor.getLazySession().get().getUserId();
+ mFingerprintSensors.addSensor(sensorId, sensor, sessionUserId,
+ new SynchronousUserSwitchObserver() {
+ @Override
+ public void onUserSwitching(int newUserId) {
+ scheduleInternalCleanup(sensorId, newUserId, null /* callback */);
+ }
+ });
Slog.d(getTag(), "Added: " + internalProp);
}
}
@@ -250,8 +260,8 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
Slog.e(getTag(), "Unable to linkToDeath", e);
}
- for (int i = 0; i < mSensors.size(); i++) {
- final int sensorId = mSensors.keyAt(i);
+ for (int i = 0; i < mFingerprintSensors.size(); i++) {
+ final int sensorId = mFingerprintSensors.keyAt(i);
scheduleLoadAuthenticatorIds(sensorId);
scheduleInternalCleanup(sensorId, ActivityManager.getCurrentUser(),
null /* callback */);
@@ -261,33 +271,33 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
}
private void scheduleForSensor(int sensorId, @NonNull BaseClientMonitor client) {
- if (!mSensors.contains(sensorId)) {
+ if (!mFingerprintSensors.contains(sensorId)) {
throw new IllegalStateException("Unable to schedule client: " + client
+ " for sensor: " + sensorId);
}
- mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client);
+ mFingerprintSensors.get(sensorId).getScheduler().scheduleClientMonitor(client);
}
private void scheduleForSensor(int sensorId, @NonNull BaseClientMonitor client,
ClientMonitorCallback callback) {
- if (!mSensors.contains(sensorId)) {
+ if (!mFingerprintSensors.contains(sensorId)) {
throw new IllegalStateException("Unable to schedule client: " + client
+ " for sensor: " + sensorId);
}
- mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client, callback);
+ mFingerprintSensors.get(sensorId).getScheduler().scheduleClientMonitor(client, callback);
}
@Override
public boolean containsSensor(int sensorId) {
- return mSensors.contains(sensorId);
+ return mFingerprintSensors.contains(sensorId);
}
@NonNull
@Override
public List<FingerprintSensorPropertiesInternal> getSensorProperties() {
final List<FingerprintSensorPropertiesInternal> props = new ArrayList<>();
- for (int i = 0; i < mSensors.size(); i++) {
- props.add(mSensors.valueAt(i).getSensorProperties());
+ for (int i = 0; i < mFingerprintSensors.size(); i++) {
+ props.add(mFingerprintSensors.valueAt(i).getSensorProperties());
}
return props;
}
@@ -295,12 +305,12 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
@Nullable
@Override
public FingerprintSensorPropertiesInternal getSensorProperties(int sensorId) {
- if (mSensors.size() == 0) {
+ if (mFingerprintSensors.size() == 0) {
return null;
} else if (sensorId == SENSOR_ID_ANY) {
- return mSensors.valueAt(0).getSensorProperties();
+ return mFingerprintSensors.valueAt(0).getSensorProperties();
} else {
- final Sensor sensor = mSensors.get(sensorId);
+ final Sensor sensor = mFingerprintSensors.get(sensorId);
return sensor != null ? sensor.getSensorProperties() : null;
}
}
@@ -315,12 +325,12 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
mHandler.post(() -> {
final FingerprintGetAuthenticatorIdClient client =
new FingerprintGetAuthenticatorIdClient(mContext,
- mSensors.get(sensorId).getLazySession(), userId,
+ mFingerprintSensors.get(sensorId).getLazySession(), userId,
mContext.getOpPackageName(), sensorId,
createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
BiometricsProtoEnums.CLIENT_UNKNOWN),
mBiometricContext,
- mSensors.get(sensorId).getAuthenticatorIds());
+ mFingerprintSensors.get(sensorId).getAuthenticatorIds());
scheduleForSensor(sensorId, client);
});
}
@@ -340,12 +350,12 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
public void scheduleResetLockout(int sensorId, int userId, @Nullable byte[] hardwareAuthToken) {
mHandler.post(() -> {
final FingerprintResetLockoutClient client = new FingerprintResetLockoutClient(
- mContext, mSensors.get(sensorId).getLazySession(), userId,
+ mContext, mFingerprintSensors.get(sensorId).getLazySession(), userId,
mContext.getOpPackageName(), sensorId,
createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
BiometricsProtoEnums.CLIENT_UNKNOWN),
mBiometricContext, hardwareAuthToken,
- mSensors.get(sensorId).getLockoutCache(), mLockoutResetDispatcher,
+ mFingerprintSensors.get(sensorId).getLockoutCache(), mLockoutResetDispatcher,
Utils.getCurrentStrength(sensorId));
scheduleForSensor(sensorId, client);
});
@@ -357,7 +367,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
mHandler.post(() -> {
final FingerprintGenerateChallengeClient client =
new FingerprintGenerateChallengeClient(mContext,
- mSensors.get(sensorId).getLazySession(), token,
+ mFingerprintSensors.get(sensorId).getLazySession(), token,
new ClientMonitorCallbackConverter(receiver), userId, opPackageName,
sensorId, createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
BiometricsProtoEnums.CLIENT_UNKNOWN),
@@ -372,7 +382,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
mHandler.post(() -> {
final FingerprintRevokeChallengeClient client =
new FingerprintRevokeChallengeClient(mContext,
- mSensors.get(sensorId).getLazySession(), token,
+ mFingerprintSensors.get(sensorId).getLazySession(), token,
userId, opPackageName, sensorId,
createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
BiometricsProtoEnums.CLIENT_UNKNOWN),
@@ -388,16 +398,16 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
@FingerprintManager.EnrollReason int enrollReason) {
final long id = mRequestCounter.incrementAndGet();
mHandler.post(() -> {
- final int maxTemplatesPerUser = mSensors.get(sensorId).getSensorProperties()
+ final int maxTemplatesPerUser = mFingerprintSensors.get(sensorId).getSensorProperties()
.maxEnrollmentsPerUser;
final FingerprintEnrollClient client = new FingerprintEnrollClient(mContext,
- mSensors.get(sensorId).getLazySession(), token, id,
+ mFingerprintSensors.get(sensorId).getLazySession(), token, id,
new ClientMonitorCallbackConverter(receiver), userId, hardwareAuthToken,
opPackageName, FingerprintUtils.getInstance(sensorId), sensorId,
createLogger(BiometricsProtoEnums.ACTION_ENROLL,
BiometricsProtoEnums.CLIENT_UNKNOWN),
mBiometricContext,
- mSensors.get(sensorId).getSensorProperties(),
+ mFingerprintSensors.get(sensorId).getSensorProperties(),
mUdfpsOverlayController, mSidefpsController, mUdfpsOverlay,
maxTemplatesPerUser, enrollReason);
scheduleForSensor(sensorId, client, new ClientMonitorCompositeCallback(
@@ -419,7 +429,8 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
@Override
public void cancelEnrollment(int sensorId, @NonNull IBinder token, long requestId) {
mHandler.post(() ->
- mSensors.get(sensorId).getScheduler().cancelEnrollment(token, requestId));
+ mFingerprintSensors.get(sensorId).getScheduler()
+ .cancelEnrollment(token, requestId));
}
@Override
@@ -432,7 +443,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
final int sensorId = options.getSensorId();
final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId);
final FingerprintDetectClient client = new FingerprintDetectClient(mContext,
- mSensors.get(sensorId).getLazySession(), token, id, callback,
+ mFingerprintSensors.get(sensorId).getLazySession(), token, id, callback,
options,
createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient),
mBiometricContext,
@@ -454,15 +465,15 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
final int sensorId = options.getSensorId();
final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId);
final FingerprintAuthenticationClient client = new FingerprintAuthenticationClient(
- mContext, mSensors.get(sensorId).getLazySession(), token, requestId, callback,
- operationId, restricted, options, cookie,
+ mContext, mFingerprintSensors.get(sensorId).getLazySession(), token, requestId,
+ callback, operationId, restricted, options, cookie,
false /* requireConfirmation */,
createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient),
mBiometricContext, isStrongBiometric,
- mTaskStackListener, mSensors.get(sensorId).getLockoutCache(),
+ mTaskStackListener, mFingerprintSensors.get(sensorId).getLockoutCache(),
mUdfpsOverlayController, mSidefpsController, mUdfpsOverlay,
allowBackgroundAuthentication,
- mSensors.get(sensorId).getSensorProperties(), mHandler,
+ mFingerprintSensors.get(sensorId).getSensorProperties(), mHandler,
Utils.getCurrentStrength(sensorId),
SystemClock.elapsedRealtimeClock());
scheduleForSensor(sensorId, client, new ClientMonitorCallback() {
@@ -505,12 +516,13 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
@Override
public void startPreparedClient(int sensorId, int cookie) {
- mHandler.post(() -> mSensors.get(sensorId).getScheduler().startPreparedClient(cookie));
+ mHandler.post(() -> mFingerprintSensors.get(sensorId).getScheduler()
+ .startPreparedClient(cookie));
}
@Override
public void cancelAuthentication(int sensorId, @NonNull IBinder token, long requestId) {
- mHandler.post(() -> mSensors.get(sensorId).getScheduler()
+ mHandler.post(() -> mFingerprintSensors.get(sensorId).getScheduler()
.cancelAuthenticationOrDetection(token, requestId));
}
@@ -541,13 +553,13 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
@NonNull String opPackageName) {
mHandler.post(() -> {
final FingerprintRemovalClient client = new FingerprintRemovalClient(mContext,
- mSensors.get(sensorId).getLazySession(), token,
+ mFingerprintSensors.get(sensorId).getLazySession(), token,
new ClientMonitorCallbackConverter(receiver), fingerprintIds, userId,
opPackageName, FingerprintUtils.getInstance(sensorId), sensorId,
createLogger(BiometricsProtoEnums.ACTION_REMOVE,
BiometricsProtoEnums.CLIENT_UNKNOWN),
mBiometricContext,
- mSensors.get(sensorId).getAuthenticatorIds());
+ mFingerprintSensors.get(sensorId).getAuthenticatorIds());
scheduleForSensor(sensorId, client, mBiometricStateCallback);
});
}
@@ -564,13 +576,13 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
mHandler.post(() -> {
final FingerprintInternalCleanupClient client =
new FingerprintInternalCleanupClient(mContext,
- mSensors.get(sensorId).getLazySession(), userId,
+ mFingerprintSensors.get(sensorId).getLazySession(), userId,
mContext.getOpPackageName(), sensorId,
createLogger(BiometricsProtoEnums.ACTION_ENUMERATE,
BiometricsProtoEnums.CLIENT_UNKNOWN),
mBiometricContext,
FingerprintUtils.getInstance(sensorId),
- mSensors.get(sensorId).getAuthenticatorIds());
+ mFingerprintSensors.get(sensorId).getAuthenticatorIds());
if (favorHalEnrollments) {
client.setFavorHalEnrollments();
}
@@ -612,11 +624,11 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
mHandler.post(() -> {
final FingerprintInvalidationClient client =
new FingerprintInvalidationClient(mContext,
- mSensors.get(sensorId).getLazySession(), userId, sensorId,
+ mFingerprintSensors.get(sensorId).getLazySession(), userId, sensorId,
createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
BiometricsProtoEnums.CLIENT_UNKNOWN),
mBiometricContext,
- mSensors.get(sensorId).getAuthenticatorIds(), callback);
+ mFingerprintSensors.get(sensorId).getAuthenticatorIds(), callback);
scheduleForSensor(sensorId, client);
});
}
@@ -629,40 +641,43 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
@Override
public long getAuthenticatorId(int sensorId, int userId) {
- return mSensors.get(sensorId).getAuthenticatorIds().getOrDefault(userId, 0L);
+ return mFingerprintSensors.get(sensorId).getAuthenticatorIds().getOrDefault(userId, 0L);
}
@Override
public void onPointerDown(long requestId, int sensorId, PointerContext pc) {
- mSensors.get(sensorId).getScheduler().getCurrentClientIfMatches(requestId, (client) -> {
- if (!(client instanceof Udfps)) {
- Slog.e(getTag(), "onPointerDown received during client: " + client);
- return;
- }
- ((Udfps) client).onPointerDown(pc);
- });
+ mFingerprintSensors.get(sensorId).getScheduler().getCurrentClientIfMatches(
+ requestId, (client) -> {
+ if (!(client instanceof Udfps)) {
+ Slog.e(getTag(), "onPointerDown received during client: " + client);
+ return;
+ }
+ ((Udfps) client).onPointerDown(pc);
+ });
}
@Override
public void onPointerUp(long requestId, int sensorId, PointerContext pc) {
- mSensors.get(sensorId).getScheduler().getCurrentClientIfMatches(requestId, (client) -> {
- if (!(client instanceof Udfps)) {
- Slog.e(getTag(), "onPointerUp received during client: " + client);
- return;
- }
- ((Udfps) client).onPointerUp(pc);
- });
+ mFingerprintSensors.get(sensorId).getScheduler().getCurrentClientIfMatches(
+ requestId, (client) -> {
+ if (!(client instanceof Udfps)) {
+ Slog.e(getTag(), "onPointerUp received during client: " + client);
+ return;
+ }
+ ((Udfps) client).onPointerUp(pc);
+ });
}
@Override
public void onUiReady(long requestId, int sensorId) {
- mSensors.get(sensorId).getScheduler().getCurrentClientIfMatches(requestId, (client) -> {
- if (!(client instanceof Udfps)) {
- Slog.e(getTag(), "onUiReady received during client: " + client);
- return;
- }
- ((Udfps) client).onUiReady();
- });
+ mFingerprintSensors.get(sensorId).getScheduler().getCurrentClientIfMatches(
+ requestId, (client) -> {
+ if (!(client instanceof Udfps)) {
+ Slog.e(getTag(), "onUiReady received during client: " + client);
+ return;
+ }
+ ((Udfps) client).onUiReady();
+ });
}
@Override
@@ -672,8 +687,8 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
@Override
public void onPowerPressed() {
- for (int i = 0; i < mSensors.size(); i++) {
- final Sensor sensor = mSensors.valueAt(i);
+ for (int i = 0; i < mFingerprintSensors.size(); i++) {
+ final Sensor sensor = mFingerprintSensors.valueAt(i);
BaseClientMonitor client = sensor.getScheduler().getCurrentClient();
if (client == null) {
return;
@@ -698,8 +713,8 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
@Override
public void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto,
boolean clearSchedulerBuffer) {
- if (mSensors.contains(sensorId)) {
- mSensors.get(sensorId).dumpProtoState(sensorId, proto, clearSchedulerBuffer);
+ if (mFingerprintSensors.contains(sensorId)) {
+ mFingerprintSensors.get(sensorId).dumpProtoState(sensorId, proto, clearSchedulerBuffer);
}
}
@@ -748,14 +763,15 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
pw.println(mBiometricContext.getAuthSessionCoordinator());
pw.println("---AuthSessionCoordinator logs end ---");
- mSensors.get(sensorId).getScheduler().dump(pw);
+ mFingerprintSensors.get(sensorId).getScheduler().dump(pw);
}
@NonNull
@Override
public ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback,
@NonNull String opPackageName) {
- return mSensors.get(sensorId).createTestSession(callback, mBiometricStateCallback);
+ return mFingerprintSensors.get(sensorId).createTestSession(callback,
+ mBiometricStateCallback);
}
@Override
@@ -764,9 +780,9 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
mHandler.post(() -> {
mDaemon = null;
- for (int i = 0; i < mSensors.size(); i++) {
- final Sensor sensor = mSensors.valueAt(i);
- final int sensorId = mSensors.keyAt(i);
+ for (int i = 0; i < mFingerprintSensors.size(); i++) {
+ final Sensor sensor = mFingerprintSensors.valueAt(i);
+ final int sensorId = mFingerprintSensors.keyAt(i);
PerformanceTracker.getInstanceForSensorId(sensorId).incrementHALDeathCount();
sensor.onBinderDied();
}
@@ -821,7 +837,8 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
@Override
public void scheduleWatchdog(int sensorId) {
Slog.d(getTag(), "Starting watchdog for fingerprint");
- final BiometricScheduler biometricScheduler = mSensors.get(sensorId).getScheduler();
+ final BiometricScheduler biometricScheduler = mFingerprintSensors.get(sensorId)
+ .getScheduler();
if (biometricScheduler == null) {
return;
}
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 22ca816ba56c..c0dde721b962 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
@@ -18,9 +18,6 @@ package com.android.server.biometrics.sensors.fingerprint.aidl;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.ActivityManager;
-import android.app.SynchronousUserSwitchObserver;
-import android.app.UserSwitchObserver;
import android.content.Context;
import android.content.pm.UserInfo;
import android.hardware.biometrics.BiometricsProtoEnums;
@@ -96,14 +93,6 @@ public class Sensor {
@Nullable private AidlSession mCurrentSession;
@NonNull private final Supplier<AidlSession> mLazySession;
- private final UserSwitchObserver mUserSwitchObserver = new SynchronousUserSwitchObserver() {
- @Override
- public void onUserSwitching(int newUserId) {
- mProvider.scheduleInternalCleanup(
- mSensorProperties.sensorId, newUserId, null /* callback */);
- }
- };
-
@VisibleForTesting
public static class HalSessionCallback extends ISessionCallback.Stub {
@@ -512,12 +501,6 @@ public class Sensor {
});
mAuthenticatorIds = new HashMap<>();
mLazySession = () -> mCurrentSession != null ? mCurrentSession : null;
-
- try {
- ActivityManager.getService().registerUserSwitchObserver(mUserSwitchObserver, mTag);
- } catch (RemoteException e) {
- Slog.e(mTag, "Unable to register user switch observer");
- }
}
@NonNull Supplier<AidlSession> getLazySession() {
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/SensorListTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/SensorListTest.java
new file mode 100644
index 000000000000..3d80916bd63e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/SensorListTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2023 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.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+
+import android.app.IActivityManager;
+import android.app.SynchronousUserSwitchObserver;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.server.biometrics.sensors.face.aidl.Sensor;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+@Presubmit
+@SmallTest
+public class SensorListTest {
+ @Rule
+ public MockitoRule mMockitoRule = MockitoJUnit.rule();
+ @Mock
+ Sensor mSensor;
+ @Mock
+ IActivityManager mActivityManager;
+ @Mock
+ SynchronousUserSwitchObserver mUserSwitchObserver;
+
+ SensorList<Sensor> mSensorList;
+
+ @Before
+ public void setUp() throws RemoteException {
+ mSensorList = new SensorList<>(mActivityManager);
+ }
+
+ @Test
+ public void testAddingSensor() throws RemoteException {
+ mSensorList.addSensor(0, mSensor, UserHandle.USER_NULL, mUserSwitchObserver);
+
+ verify(mUserSwitchObserver).onUserSwitching(UserHandle.USER_SYSTEM);
+ verify(mActivityManager).registerUserSwitchObserver(eq(mUserSwitchObserver), anyString());
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceProviderTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceProviderTest.java
index 41f743367aeb..31a58cd67d3e 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceProviderTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceProviderTest.java
@@ -16,6 +16,8 @@
package com.android.server.biometrics.sensors.face.aidl;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
@@ -30,6 +32,7 @@ import android.hardware.biometrics.face.IFace;
import android.hardware.biometrics.face.ISession;
import android.hardware.biometrics.face.SensorProps;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.os.UserManager;
import android.platform.test.annotations.Presubmit;
@@ -38,6 +41,7 @@ import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.sensors.BaseClientMonitor;
import com.android.server.biometrics.sensors.BiometricScheduler;
import com.android.server.biometrics.sensors.BiometricStateCallback;
import com.android.server.biometrics.sensors.HalClientMonitor;
@@ -98,16 +102,34 @@ public class FaceProviderTest {
mSensorProps, TAG, mLockoutResetDispatcher, mBiometricContext);
}
+ @Test
+ public void testAddingSensors() {
+ waitForIdle();
+
+ for (SensorProps prop : mSensorProps) {
+ final BiometricScheduler scheduler =
+ mFaceProvider.mFaceSensors.get(prop.commonProps.sensorId)
+ .getScheduler();
+ BaseClientMonitor currentClient = scheduler.getCurrentClient();
+
+ assertThat(currentClient).isInstanceOf(FaceInternalCleanupClient.class);
+ assertThat(currentClient.getSensorId()).isEqualTo(prop.commonProps.sensorId);
+ assertThat(currentClient.getTargetUserId()).isEqualTo(UserHandle.USER_SYSTEM);
+ }
+ }
+
@SuppressWarnings("rawtypes")
@Test
public void halServiceDied_resetsAllSchedulers() {
+ waitForIdle();
+
assertEquals(mSensorProps.length, mFaceProvider.getSensorProperties().size());
// Schedule N operations on each sensor
final int numFakeOperations = 10;
for (SensorProps prop : mSensorProps) {
final BiometricScheduler scheduler =
- mFaceProvider.mSensors.get(prop.commonProps.sensorId).getScheduler();
+ mFaceProvider.mFaceSensors.get(prop.commonProps.sensorId).getScheduler();
for (int i = 0; i < numFakeOperations; i++) {
final HalClientMonitor testMonitor = mock(HalClientMonitor.class);
when(testMonitor.getFreshDaemon()).thenReturn(new Object());
@@ -119,8 +141,8 @@ public class FaceProviderTest {
// The right amount of pending and current operations are scheduled
for (SensorProps prop : mSensorProps) {
final BiometricScheduler scheduler =
- mFaceProvider.mSensors.get(prop.commonProps.sensorId).getScheduler();
- assertEquals(numFakeOperations - 1, scheduler.getCurrentPendingCount());
+ mFaceProvider.mFaceSensors.get(prop.commonProps.sensorId).getScheduler();
+ assertEquals(numFakeOperations, scheduler.getCurrentPendingCount());
assertNotNull(scheduler.getCurrentClient());
}
@@ -132,7 +154,7 @@ public class FaceProviderTest {
// No pending operations, no current operation.
for (SensorProps prop : mSensorProps) {
final BiometricScheduler scheduler =
- mFaceProvider.mSensors.get(prop.commonProps.sensorId).getScheduler();
+ mFaceProvider.mFaceSensors.get(prop.commonProps.sensorId).getScheduler();
assertNull(scheduler.getCurrentClient());
assertEquals(0, scheduler.getCurrentPendingCount());
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/SensorTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/SensorTest.java
index 9c9d3f894d95..25bd9bcf8d5c 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/SensorTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/SensorTest.java
@@ -29,9 +29,9 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.hardware.biometrics.IBiometricService;
import android.hardware.biometrics.common.CommonProps;
-import android.hardware.biometrics.face.IFace;
import android.hardware.biometrics.face.ISession;
import android.hardware.biometrics.face.SensorProps;
+import android.hardware.face.FaceSensorPropertiesInternal;
import android.os.Handler;
import android.os.test.TestLooper;
import android.platform.test.annotations.Presubmit;
@@ -42,7 +42,6 @@ import com.android.server.biometrics.log.BiometricContext;
import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.AuthSessionCoordinator;
import com.android.server.biometrics.sensors.BiometricScheduler;
-import com.android.server.biometrics.sensors.BiometricStateCallback;
import com.android.server.biometrics.sensors.LockoutCache;
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
import com.android.server.biometrics.sensors.LockoutTracker;
@@ -82,17 +81,13 @@ public class SensorTest {
@Mock
private AuthSessionCoordinator mAuthSessionCoordinator;
@Mock
- private IFace mDaemon;
- @Mock
- private BiometricStateCallback mBiometricStateCallback;
+ FaceProvider mFaceProvider;
private final TestLooper mLooper = new TestLooper();
private final LockoutCache mLockoutCache = new LockoutCache();
private UserAwareBiometricScheduler mScheduler;
private Sensor.HalSessionCallback mHalCallback;
- private FaceProvider mFaceProvider;
- private SensorProps[] mSensorProps;
@Before
public void setUp() {
@@ -113,16 +108,6 @@ public class SensorTest {
TAG, mScheduler, SENSOR_ID,
USER_ID, mLockoutCache, mLockoutResetDispatcher, mAuthSessionCoordinator,
mHalSessionCallback);
-
- final SensorProps sensor1 = new SensorProps();
- sensor1.commonProps = new CommonProps();
- sensor1.commonProps.sensorId = 0;
- final SensorProps sensor2 = new SensorProps();
- sensor2.commonProps = new CommonProps();
- sensor2.commonProps.sensorId = 1;
- mSensorProps = new SensorProps[]{sensor1, sensor2};
- mFaceProvider = new FaceProvider(mContext, mBiometricStateCallback,
- mSensorProps, TAG, mLockoutResetDispatcher, mBiometricContext);
}
@Test
@@ -154,14 +139,26 @@ public class SensorTest {
@Test
public void onBinderDied_noErrorOnNullClient() {
+ mLooper.dispatchAll();
+
+ final SensorProps sensorProps = new SensorProps();
+ sensorProps.commonProps = new CommonProps();
+ sensorProps.commonProps.sensorId = 1;
+ final FaceSensorPropertiesInternal internalProp = new FaceSensorPropertiesInternal(
+ sensorProps.commonProps.sensorId, sensorProps.commonProps.sensorStrength,
+ sensorProps.commonProps.maxEnrollmentsPerUser, null,
+ sensorProps.sensorType, sensorProps.supportsDetectInteraction,
+ sensorProps.halControlsPreview, false /* resetLockoutRequiresChallenge */);
+ final Sensor sensor = new Sensor("SensorTest", mFaceProvider, mContext, null,
+ internalProp, mLockoutResetDispatcher, mBiometricContext);
+
mScheduler.reset();
+
assertNull(mScheduler.getCurrentClient());
- mFaceProvider.binderDied();
- for (int i = 0; i < mFaceProvider.mSensors.size(); i++) {
- final Sensor sensor = mFaceProvider.mSensors.valueAt(i);
- assertNull(sensor.getSessionForUser(USER_ID));
- }
+ sensor.onBinderDied();
+
+ assertNull(sensor.getSessionForUser(USER_ID));
}
private void verifyNotLocked() {
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java
index c6ddf27f96b2..9c01de6f0461 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java
@@ -16,6 +16,8 @@
package com.android.server.biometrics.sensors.fingerprint.aidl;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
@@ -33,6 +35,7 @@ import android.hardware.biometrics.fingerprint.ISession;
import android.hardware.biometrics.fingerprint.SensorLocation;
import android.hardware.biometrics.fingerprint.SensorProps;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.os.UserManager;
import android.platform.test.annotations.Presubmit;
@@ -41,6 +44,7 @@ import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.sensors.BaseClientMonitor;
import com.android.server.biometrics.sensors.BiometricScheduler;
import com.android.server.biometrics.sensors.BiometricStateCallback;
import com.android.server.biometrics.sensors.HalClientMonitor;
@@ -111,16 +115,38 @@ public class FingerprintProviderTest {
mGestureAvailabilityDispatcher, mBiometricContext);
}
+ @Test
+ public void testAddingSensors() {
+ mFingerprintProvider = new TestableFingerprintProvider(mDaemon, mContext,
+ mBiometricStateCallback, mSensorProps, TAG, mLockoutResetDispatcher,
+ mGestureAvailabilityDispatcher, mBiometricContext);
+
+ waitForIdle();
+
+ for (SensorProps prop : mSensorProps) {
+ final BiometricScheduler scheduler =
+ mFingerprintProvider.mFingerprintSensors.get(prop.commonProps.sensorId)
+ .getScheduler();
+ BaseClientMonitor currentClient = scheduler.getCurrentClient();
+
+ assertThat(currentClient).isInstanceOf(FingerprintInternalCleanupClient.class);
+ assertThat(currentClient.getSensorId()).isEqualTo(prop.commonProps.sensorId);
+ assertThat(currentClient.getTargetUserId()).isEqualTo(UserHandle.USER_SYSTEM);
+ }
+ }
+
@SuppressWarnings("rawtypes")
@Test
public void halServiceDied_resetsAllSchedulers() {
+ waitForIdle();
assertEquals(mSensorProps.length, mFingerprintProvider.getSensorProperties().size());
// Schedule N operations on each sensor
final int numFakeOperations = 10;
for (SensorProps prop : mSensorProps) {
final BiometricScheduler scheduler =
- mFingerprintProvider.mSensors.get(prop.commonProps.sensorId).getScheduler();
+ mFingerprintProvider.mFingerprintSensors.get(prop.commonProps.sensorId)
+ .getScheduler();
for (int i = 0; i < numFakeOperations; i++) {
final HalClientMonitor testMonitor = mock(HalClientMonitor.class);
when(testMonitor.getFreshDaemon()).thenReturn(new Object());
@@ -132,8 +158,9 @@ public class FingerprintProviderTest {
// The right amount of pending and current operations are scheduled
for (SensorProps prop : mSensorProps) {
final BiometricScheduler scheduler =
- mFingerprintProvider.mSensors.get(prop.commonProps.sensorId).getScheduler();
- assertEquals(numFakeOperations - 1, scheduler.getCurrentPendingCount());
+ mFingerprintProvider.mFingerprintSensors.get(prop.commonProps.sensorId)
+ .getScheduler();
+ assertEquals(numFakeOperations, scheduler.getCurrentPendingCount());
assertNotNull(scheduler.getCurrentClient());
}
@@ -145,7 +172,8 @@ public class FingerprintProviderTest {
// No pending operations, no current operation.
for (SensorProps prop : mSensorProps) {
final BiometricScheduler scheduler =
- mFingerprintProvider.mSensors.get(prop.commonProps.sensorId).getScheduler();
+ mFingerprintProvider.mFingerprintSensors.get(prop.commonProps.sensorId)
+ .getScheduler();
assertNull(scheduler.getCurrentClient());
assertEquals(0, scheduler.getCurrentPendingCount());
}