diff options
| author | 2023-05-01 18:25:44 +0000 | |
|---|---|---|
| committer | 2023-05-01 18:25:44 +0000 | |
| commit | dc661b7ccbd8f4f1eb2a2f4104daa174d2940b98 (patch) | |
| tree | 768241f6a4aa5b8ad5f9eaea98ac6e894863b31b | |
| parent | d67eaa8483a3af25f1596ab61944d9afd8ae6c77 (diff) | |
| parent | c6ba932666bd1d7a45aa52a2d4f0f947054ee18e (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>
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()); } |