From eab24acdb4eb158c24cc3b78e64e0b9f04d19af0 Mon Sep 17 00:00:00 2001 From: Joe Bolinger Date: Fri, 25 Mar 2022 17:48:48 -0700 Subject: [PATCH] Run biometric cleanup on user switch. This will force the new to user start on the scheduler, open a new session, and close the old user's session in the HAL. Add a similar user swtich hook to keyguard to refresh the lockout state. Note that lockout behavior is still ill-defined (b/225986544) and HALs may not support a lockout state per user. Bug: 205908931 Test: manual (unlock, cause lockout, & switch users) Test: atest KeyguardUpdateMonitorTest Change-Id: I89d3d7454894bc5caa0cac33e96d7fd0d61e9083 --- .../biometrics/BiometricConstants.java | 23 +++++ .../android/hardware/face/FaceManager.java | 17 ++++ .../fingerprint/FingerprintManager.java | 18 ++++ .../keyguard/KeyguardUpdateMonitor.java | 61 ++++++++++---- .../keyguard/KeyguardUpdateMonitorTest.java | 84 ++++++++++++++++++- .../biometrics/sensors/LockoutCache.java | 3 + .../biometrics/sensors/LockoutTracker.java | 7 +- .../biometrics/sensors/face/aidl/Sensor.java | 17 ++++ .../sensors/fingerprint/aidl/Sensor.java | 17 ++++ 9 files changed, 227 insertions(+), 20 deletions(-) diff --git a/core/java/android/hardware/biometrics/BiometricConstants.java b/core/java/android/hardware/biometrics/BiometricConstants.java index 28046c56b9f8..99e4febe205d 100644 --- a/core/java/android/hardware/biometrics/BiometricConstants.java +++ b/core/java/android/hardware/biometrics/BiometricConstants.java @@ -268,4 +268,27 @@ public interface BiometricConstants { */ int BIOMETRIC_SYSTEM_EVENT_EARLY_USER_CANCEL = 1; + /** + * No lockout. + * @hide + */ + int BIOMETRIC_LOCKOUT_NONE = 0; + /** + * The biometric is in a temporary lockout state that will expire after some time. + * @hide + */ + int BIOMETRIC_LOCKOUT_TIMED = 1; + /** + * The biometric is locked out until a reset occurs. Resets are typically triggered by + * successfully authenticating via a stronger method than the one that is locked out. + * @hide + */ + int BIOMETRIC_LOCKOUT_PERMANENT = 2; + + /** + * @hide + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({BIOMETRIC_LOCKOUT_NONE, BIOMETRIC_LOCKOUT_TIMED, BIOMETRIC_LOCKOUT_PERMANENT}) + @interface LockoutMode {} } diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java index b97055976e3e..31f3b6aef251 100644 --- a/core/java/android/hardware/face/FaceManager.java +++ b/core/java/android/hardware/face/FaceManager.java @@ -19,6 +19,7 @@ package android.hardware.face; import static android.Manifest.permission.INTERACT_ACROSS_USERS; import static android.Manifest.permission.MANAGE_BIOMETRIC; import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL; +import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_LOCKOUT_NONE; import android.annotation.NonNull; import android.annotation.Nullable; @@ -672,6 +673,22 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan return new ArrayList<>(); } + /** + * @hide + */ + @RequiresPermission(USE_BIOMETRIC_INTERNAL) + @BiometricConstants.LockoutMode + public int getLockoutModeForUser(int sensorId, int userId) { + if (mService != null) { + try { + return mService.getLockoutModeForUser(sensorId, userId); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + return BIOMETRIC_LOCKOUT_NONE; + } + /** * @hide */ diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java index 29221b801ef6..eda3583a8034 100644 --- a/core/java/android/hardware/fingerprint/FingerprintManager.java +++ b/core/java/android/hardware/fingerprint/FingerprintManager.java @@ -23,6 +23,7 @@ import static android.Manifest.permission.TEST_BIOMETRIC; import static android.Manifest.permission.USE_BIOMETRIC; import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL; import static android.Manifest.permission.USE_FINGERPRINT; +import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_LOCKOUT_NONE; import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_POWER_BUTTON; import static com.android.internal.util.FrameworkStatsLog.AUTH_DEPRECATED_APIUSED__DEPRECATED_API__API_FINGERPRINT_MANAGER_AUTHENTICATE; @@ -41,6 +42,7 @@ import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.pm.PackageManager; import android.hardware.biometrics.BiometricAuthenticator; +import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.BiometricFingerprintConstants; import android.hardware.biometrics.BiometricPrompt; import android.hardware.biometrics.BiometricTestSession; @@ -1083,6 +1085,22 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing } } + /** + * @hide + */ + @RequiresPermission(USE_BIOMETRIC_INTERNAL) + @BiometricConstants.LockoutMode + public int getLockoutModeForUser(int sensorId, int userId) { + if (mService != null) { + try { + return mService.getLockoutModeForUser(sensorId, userId); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + return BIOMETRIC_LOCKOUT_NONE; + } + /** * @hide */ diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index fcabbbca6e34..c123712c8915 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -21,6 +21,10 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.content.Intent.ACTION_USER_REMOVED; import static android.content.Intent.ACTION_USER_STOPPED; import static android.content.Intent.ACTION_USER_UNLOCKED; +import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_LOCKOUT_NONE; +import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_LOCKOUT_PERMANENT; +import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_LOCKOUT_TIMED; +import static android.hardware.biometrics.BiometricConstants.LockoutMode; import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT; @@ -61,6 +65,7 @@ import android.hardware.face.FaceSensorPropertiesInternal; import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback; import android.hardware.fingerprint.FingerprintManager.AuthenticationResult; +import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.nfc.NfcAdapter; import android.os.Build; import android.os.CancellationSignal; @@ -864,10 +869,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } } - private void handleFingerprintLockoutReset() { - boolean changed = mFingerprintLockedOut || mFingerprintLockedOutPermanent; - mFingerprintLockedOut = false; - mFingerprintLockedOutPermanent = false; + private void handleFingerprintLockoutReset(@LockoutMode int mode) { + Log.d(TAG, "handleFingerprintLockoutReset: " + mode); + final boolean wasLockout = mFingerprintLockedOut; + final boolean wasLockoutPermanent = mFingerprintLockedOutPermanent; + mFingerprintLockedOut = (mode == BIOMETRIC_LOCKOUT_TIMED) + || mode == BIOMETRIC_LOCKOUT_PERMANENT; + mFingerprintLockedOutPermanent = (mode == BIOMETRIC_LOCKOUT_PERMANENT); + final boolean changed = (mFingerprintLockedOut != wasLockout) + || (mFingerprintLockedOutPermanent != wasLockoutPermanent); if (isUdfpsEnrolled()) { // TODO(b/194825098): update the reset signal(s) @@ -877,7 +887,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab // be noticeable. mHandler.postDelayed(() -> { updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE); - }, BIOMETRIC_LOCKOUT_RESET_DELAY_MS); + }, getBiometricLockoutDelay()); } else { updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE); } @@ -1075,13 +1085,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } } - private void handleFaceLockoutReset() { - boolean changed = mFaceLockedOutPermanent; - mFaceLockedOutPermanent = false; + private void handleFaceLockoutReset(@LockoutMode int mode) { + Log.d(TAG, "handleFaceLockoutReset: " + mode); + final boolean wasLockoutPermanent = mFaceLockedOutPermanent; + mFaceLockedOutPermanent = (mode == BIOMETRIC_LOCKOUT_PERMANENT); + final boolean changed = (mFaceLockedOutPermanent != wasLockoutPermanent); mHandler.postDelayed(() -> { updateFaceListeningState(BIOMETRIC_ACTION_UPDATE); - }, BIOMETRIC_LOCKOUT_RESET_DELAY_MS); + }, getBiometricLockoutDelay()); if (changed) { notifyLockedOutStateChanged(BiometricSourceType.FACE); @@ -1461,7 +1473,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab = new FingerprintManager.LockoutResetCallback() { @Override public void onLockoutReset(int sensorId) { - handleFingerprintLockoutReset(); + handleFingerprintLockoutReset(BIOMETRIC_LOCKOUT_NONE); } }; @@ -1469,7 +1481,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab = new FaceManager.LockoutResetCallback() { @Override public void onLockoutReset(int sensorId) { - handleFaceLockoutReset(); + handleFaceLockoutReset(BIOMETRIC_LOCKOUT_NONE); } }; @@ -1579,10 +1591,13 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } }; - private CancellationSignal mFingerprintCancelSignal; - private CancellationSignal mFaceCancelSignal; + @VisibleForTesting + CancellationSignal mFingerprintCancelSignal; + @VisibleForTesting + CancellationSignal mFaceCancelSignal; private FingerprintManager mFpm; private FaceManager mFaceManager; + private List mFingerprintSensorProperties; private List mFaceSensorProperties; private boolean mFingerprintLockedOut; private boolean mFingerprintLockedOutPermanent; @@ -2017,6 +2032,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) { mFpm = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE); + mFingerprintSensorProperties = mFpm.getSensorPropertiesInternal(); } if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FACE)) { mFaceManager = (FaceManager) context.getSystemService(Context.FACE_SERVICE); @@ -2381,11 +2397,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab final boolean shouldListenUdfpsState = !isUdfps || (!userCanSkipBouncer && !isEncryptedOrLockdownForUser - && userDoesNotHaveTrust - && !mFingerprintLockedOut); + && userDoesNotHaveTrust); final boolean shouldListen = shouldListenKeyguardState && shouldListenUserState - && shouldListenBouncerState && shouldListenUdfpsState; + && shouldListenBouncerState && shouldListenUdfpsState && !isFingerprintLockedOut(); if (DEBUG_FINGERPRINT || DEBUG_SPEW) { maybeLogListenerModelData( @@ -2771,6 +2786,16 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab cb.onUserSwitchComplete(userId); } } + + if (mFaceManager != null && !mFaceSensorProperties.isEmpty()) { + handleFaceLockoutReset(mFaceManager.getLockoutModeForUser( + mFaceSensorProperties.get(0).sensorId, userId)); + } + if (mFpm != null && !mFingerprintSensorProperties.isEmpty()) { + handleFingerprintLockoutReset(mFpm.getLockoutModeForUser( + mFingerprintSensorProperties.get(0).sensorId, userId)); + } + mInteractionJankMonitor.end(InteractionJankMonitor.CUJ_USER_SWITCH); mLatencyTracker.onActionEnd(LatencyTracker.ACTION_USER_SWITCH); } @@ -3480,6 +3505,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } } + protected int getBiometricLockoutDelay() { + return BIOMETRIC_LOCKOUT_RESET_DELAY_MS; + } + /** * Unregister all listeners. */ diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index 42e15c4fb7d9..c582136e8833 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -35,10 +35,12 @@ import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.Activity; +import android.app.ActivityManager; import android.app.admin.DevicePolicyManager; import android.app.trust.IStrongAuthTracker; import android.app.trust.TrustManager; @@ -50,15 +52,20 @@ import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; +import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.BiometricManager; +import android.hardware.biometrics.BiometricSourceType; import android.hardware.biometrics.ComponentInfoInternal; import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback; import android.hardware.face.FaceManager; import android.hardware.face.FaceSensorProperties; import android.hardware.face.FaceSensorPropertiesInternal; import android.hardware.fingerprint.FingerprintManager; +import android.hardware.fingerprint.FingerprintSensorProperties; +import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.nfc.NfcAdapter; import android.os.Bundle; +import android.os.CancellationSignal; import android.os.Handler; import android.os.IRemoteCallback; import android.os.UserHandle; @@ -121,6 +128,9 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { TEST_CARRIER, TEST_CARRIER_2, NAME_SOURCE_CARRIER_ID, 0xFFFFFF, "", DATA_ROAMING_DISABLE, null, null, null, null, false, null, "", true, TEST_GROUP_UUID, TEST_CARRIER_ID, 0); + private static final int FACE_SENSOR_ID = 0; + private static final int FINGERPRINT_SENSOR_ID = 1; + @Mock private DumpManager mDumpManager; @Mock @@ -212,6 +222,16 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { when(mFingerprintManager.isHardwareDetected()).thenReturn(true); when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(true); + when(mFingerprintManager.getSensorPropertiesInternal()).thenReturn(List.of( + new FingerprintSensorPropertiesInternal(1 /* sensorId */, + FingerprintSensorProperties.STRENGTH_STRONG, + 1 /* maxEnrollmentsPerUser */, + List.of(new ComponentInfoInternal("fingerprintSensor" /* componentId */, + "vendor/model/revision" /* hardwareVersion */, + "1.01" /* firmwareVersion */, + "00000001" /* serialNumber */, "" /* softwareVersion */)), + FingerprintSensorProperties.TYPE_UDFPS_OPTICAL, + false /* resetLockoutRequiresHAT */))); when(mUserManager.isUserUnlocked(anyInt())).thenReturn(true); when(mUserManager.isPrimaryUser()).thenReturn(true); when(mStrongAuthTracker.getStub()).thenReturn(mock(IStrongAuthTracker.Stub.class)); @@ -232,9 +252,13 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { mSpiedContext.addMockSystemService(TelephonyManager.class, mTelephonyManager); mMockitoSession = ExtendedMockito.mockitoSession() - .spyStatic(SubscriptionManager.class).startMocking(); + .spyStatic(SubscriptionManager.class) + .spyStatic(ActivityManager.class) + .startMocking(); ExtendedMockito.doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID) .when(SubscriptionManager::getDefaultSubscriptionId); + ExtendedMockito.doReturn(KeyguardUpdateMonitor.getCurrentUser()) + .when(ActivityManager::getCurrentUser); mTestableLooper = TestableLooper.get(this); allowTestableLooperAsMainThread(); @@ -756,6 +780,59 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { verify(mLatencyTracker).onActionEnd(LatencyTracker.ACTION_USER_SWITCH); } + @Test + public void testMultiUserLockoutChanged_whenUserSwitches() { + testMultiUserLockout_whenUserSwitches(BiometricConstants.BIOMETRIC_LOCKOUT_PERMANENT, + BiometricConstants.BIOMETRIC_LOCKOUT_PERMANENT); + } + + @Test + public void testMultiUserLockoutNotChanged_whenUserSwitches() { + testMultiUserLockout_whenUserSwitches(BiometricConstants.BIOMETRIC_LOCKOUT_NONE, + BiometricConstants.BIOMETRIC_LOCKOUT_NONE); + } + + private void testMultiUserLockout_whenUserSwitches( + @BiometricConstants.LockoutMode int fingerprintLockoutMode, + @BiometricConstants.LockoutMode int faceLockoutMode) { + final int newUser = 12; + final boolean faceLocked = + faceLockoutMode != BiometricConstants.BIOMETRIC_LOCKOUT_NONE; + final boolean fpLocked = + fingerprintLockoutMode != BiometricConstants.BIOMETRIC_LOCKOUT_NONE; + when(mFingerprintManager.getLockoutModeForUser(eq(FINGERPRINT_SENSOR_ID), eq(newUser))) + .thenReturn(fingerprintLockoutMode); + when(mFaceManager.getLockoutModeForUser(eq(FACE_SENSOR_ID), eq(newUser))) + .thenReturn(faceLockoutMode); + + mKeyguardUpdateMonitor.dispatchStartedWakingUp(); + mTestableLooper.processAllMessages(); + mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true); + + verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean()); + verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(), + anyInt()); + + final CancellationSignal faceCancel = spy(mKeyguardUpdateMonitor.mFaceCancelSignal); + final CancellationSignal fpCancel = spy(mKeyguardUpdateMonitor.mFingerprintCancelSignal); + mKeyguardUpdateMonitor.mFaceCancelSignal = faceCancel; + mKeyguardUpdateMonitor.mFingerprintCancelSignal = fpCancel; + KeyguardUpdateMonitorCallback callback = mock(KeyguardUpdateMonitorCallback.class); + mKeyguardUpdateMonitor.registerCallback(callback); + + mKeyguardUpdateMonitor.handleUserSwitchComplete(newUser); + mTestableLooper.processAllMessages(); + + verify(faceCancel, faceLocked ? times(1) : never()).cancel(); + verify(fpCancel, fpLocked ? times(1) : never()).cancel(); + verify(callback, faceLocked ? times(1) : never()).onBiometricRunningStateChanged( + eq(false), eq(BiometricSourceType.FACE)); + verify(callback, fpLocked ? times(1) : never()).onBiometricRunningStateChanged( + eq(false), eq(BiometricSourceType.FINGERPRINT)); + assertThat(mKeyguardUpdateMonitor.isFingerprintLockedOut()).isEqualTo(fpLocked); + assertThat(mKeyguardUpdateMonitor.isFaceLockedOut()).isEqualTo(faceLocked); + } + @Test public void testGetUserCanSkipBouncer_whenTrust() { int user = KeyguardUpdateMonitor.getCurrentUser(); @@ -1115,5 +1192,10 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { mSimStateChanged.set(true); super.handleSimStateChange(subId, slotId, state); } + + @Override + protected int getBiometricLockoutDelay() { + return 0; + } } } diff --git a/services/core/java/com/android/server/biometrics/sensors/LockoutCache.java b/services/core/java/com/android/server/biometrics/sensors/LockoutCache.java index 0aba29557b20..95c49032c029 100644 --- a/services/core/java/com/android/server/biometrics/sensors/LockoutCache.java +++ b/services/core/java/com/android/server/biometrics/sensors/LockoutCache.java @@ -16,12 +16,14 @@ package com.android.server.biometrics.sensors; +import android.util.Slog; import android.util.SparseIntArray; /** * For a single sensor, caches lockout states for all users. */ public class LockoutCache implements LockoutTracker { + private static final String TAG = "LockoutCache"; // Map of userId to LockoutMode private final SparseIntArray mUserLockoutStates; @@ -31,6 +33,7 @@ public class LockoutCache implements LockoutTracker { } public void setLockoutModeForUser(int userId, @LockoutMode int mode) { + Slog.d(TAG, "Lockout for user: " + userId + " is " + mode); synchronized (this) { mUserLockoutStates.put(userId, mode); } diff --git a/services/core/java/com/android/server/biometrics/sensors/LockoutTracker.java b/services/core/java/com/android/server/biometrics/sensors/LockoutTracker.java index fa386d073035..4a59c9df9bef 100644 --- a/services/core/java/com/android/server/biometrics/sensors/LockoutTracker.java +++ b/services/core/java/com/android/server/biometrics/sensors/LockoutTracker.java @@ -17,6 +17,7 @@ package com.android.server.biometrics.sensors; import android.annotation.IntDef; +import android.hardware.biometrics.BiometricConstants; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -25,9 +26,9 @@ import java.lang.annotation.RetentionPolicy; * Interface for retrieval of current user's lockout state. */ public interface LockoutTracker { - int LOCKOUT_NONE = 0; - int LOCKOUT_TIMED = 1; - int LOCKOUT_PERMANENT = 2; + int LOCKOUT_NONE = BiometricConstants.BIOMETRIC_LOCKOUT_NONE; + int LOCKOUT_TIMED = BiometricConstants.BIOMETRIC_LOCKOUT_TIMED; + int LOCKOUT_PERMANENT = BiometricConstants.BIOMETRIC_LOCKOUT_PERMANENT; @Retention(RetentionPolicy.SOURCE) @IntDef({LOCKOUT_NONE, LOCKOUT_TIMED, LOCKOUT_PERMANENT}) 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 b69c7600e75a..800d4b8acf61 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,6 +18,9 @@ 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; @@ -91,6 +94,14 @@ public class Sensor { @NonNull private final Supplier 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 { /** @@ -537,6 +548,12 @@ 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 getLazySession() { 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 63e345e40ad7..024d611732c1 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,6 +18,9 @@ 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; @@ -92,6 +95,14 @@ public class Sensor { @Nullable private AidlSession mCurrentSession; @NonNull private final Supplier 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 { @@ -491,6 +502,12 @@ 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 getLazySession() {