Merge "Start fingerprint user client on reboot" into udc-dev

This commit is contained in:
Diya Bera
2023-05-01 16:13:33 +00:00
committed by Android (Google) Code Review
9 changed files with 396 additions and 193 deletions

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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() {

View File

@@ -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;
}

View File

@@ -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() {

View File

@@ -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());
}
}

View File

@@ -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());
}

View File

@@ -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() {
mScheduler.reset();
assertNull(mScheduler.getCurrentClient());
mFaceProvider.binderDied();
mLooper.dispatchAll();
for (int i = 0; i < mFaceProvider.mSensors.size(); i++) {
final Sensor sensor = mFaceProvider.mSensors.valueAt(i);
assertNull(sensor.getSessionForUser(USER_ID));
}
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());
sensor.onBinderDied();
assertNull(sensor.getSessionForUser(USER_ID));
}
private void verifyNotLocked() {

View File

@@ -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());
}