Loading services/core/java/com/android/server/biometrics/sensors/AuthResultCoordinator.java +15 −4 Original line number Diff line number Diff line Loading @@ -37,13 +37,17 @@ class AuthResultCoordinator { */ static final int AUTHENTICATOR_DEFAULT = 0; /** * Indicated this authenticator has received a lockout. * Indicated this authenticator has received a permanent lockout. */ static final int AUTHENTICATOR_LOCKED = 1 << 0; static final int AUTHENTICATOR_PERMANENT_LOCKED = 1 << 0; /** * Indicates this authenticator has received a timed unlock. */ static final int AUTHENTICATOR_TIMED_LOCKED = 1 << 1; /** * Indicates this authenticator has received a successful unlock. */ static final int AUTHENTICATOR_UNLOCKED = 1 << 1; static final int AUTHENTICATOR_UNLOCKED = 1 << 2; private static final String TAG = "AuthResultCoordinator"; private final Map<Integer, Integer> mAuthenticatorState; Loading Loading @@ -85,7 +89,14 @@ class AuthResultCoordinator { * Adds a lock out of a given strength to the current operation list. */ void lockedOutFor(@Authenticators.Types int strength) { updateState(strength, (old) -> AUTHENTICATOR_LOCKED | old); updateState(strength, (old) -> AUTHENTICATOR_PERMANENT_LOCKED | old); } /** * Adds a timed lock out of a given strength to the current operation list. */ void lockOutTimed(@Authenticators.Types int strength) { updateState(strength, (old) -> AUTHENTICATOR_TIMED_LOCKED | old); } /** Loading services/core/java/com/android/server/biometrics/sensors/AuthSessionCoordinator.java +21 −39 Original line number Diff line number Diff line Loading @@ -16,21 +16,19 @@ package com.android.server.biometrics.sensors; import static com.android.server.biometrics.sensors.AuthResultCoordinator.AUTHENTICATOR_LOCKED; import static com.android.server.biometrics.sensors.AuthResultCoordinator.AUTHENTICATOR_PERMANENT_LOCKED; import static com.android.server.biometrics.sensors.AuthResultCoordinator.AUTHENTICATOR_TIMED_LOCKED; import static com.android.server.biometrics.sensors.AuthResultCoordinator.AUTHENTICATOR_UNLOCKED; import android.hardware.biometrics.BiometricManager.Authenticators; import android.os.SystemClock; import android.util.Pair; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import java.time.Clock; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; Loading @@ -45,9 +43,7 @@ public class AuthSessionCoordinator implements AuthSessionListener { private final Set<Integer> mAuthOperations; private final MultiBiometricLockoutState mMultiBiometricLockoutState; private final List<Pair<Integer, Long>> mTimedLockouts; private final RingBuffer mRingBuffer; private final Clock mClock; private int mUserId; private boolean mIsAuthenticating; Loading @@ -63,8 +59,6 @@ public class AuthSessionCoordinator implements AuthSessionListener { mAuthResultCoordinator = new AuthResultCoordinator(); mMultiBiometricLockoutState = new MultiBiometricLockoutState(clock); mRingBuffer = new RingBuffer(100); mTimedLockouts = new ArrayList<>(); mClock = clock; } /** Loading @@ -74,8 +68,6 @@ public class AuthSessionCoordinator implements AuthSessionListener { mAuthOperations.clear(); mUserId = userId; mIsAuthenticating = true; mAuthOperations.clear(); mTimedLockouts.clear(); mAuthResultCoordinator = new AuthResultCoordinator(); mRingBuffer.addApiCall("internal : onAuthSessionStarted(" + userId + ")"); } Loading @@ -85,39 +77,30 @@ public class AuthSessionCoordinator implements AuthSessionListener { * * This can happen two ways. * 1. Manually calling this API * 2. If authStartedFor() was called, and all authentication attempts finish. * 2. If authStartedFor() was called, and any authentication attempts finish. */ void endAuthSession() { if (mIsAuthenticating) { final long currentTime = mClock.millis(); for (Pair<Integer, Long> timedLockouts : mTimedLockouts) { mMultiBiometricLockoutState.increaseLockoutTime(mUserId, timedLockouts.first, timedLockouts.second + currentTime); } // User unlocks can also unlock timed lockout Authenticator.Types final Map<Integer, Integer> result = mAuthResultCoordinator.getResult(); for (int authenticator : Arrays.asList(Authenticators.BIOMETRIC_CONVENIENCE, Authenticators.BIOMETRIC_WEAK, Authenticators.BIOMETRIC_STRONG)) { final Integer value = result.get(authenticator); if ((value & AUTHENTICATOR_UNLOCKED) == AUTHENTICATOR_UNLOCKED) { mMultiBiometricLockoutState.setAuthenticatorTo(mUserId, authenticator, true /* canAuthenticate */); mMultiBiometricLockoutState.clearLockoutTime(mUserId, authenticator); } else if ((value & AUTHENTICATOR_LOCKED) == AUTHENTICATOR_LOCKED) { mMultiBiometricLockoutState.setAuthenticatorTo(mUserId, authenticator, false /* canAuthenticate */); mMultiBiometricLockoutState.clearPermanentLockOut(mUserId, authenticator); mMultiBiometricLockoutState.clearTimedLockout(mUserId, authenticator); } else if ((value & AUTHENTICATOR_PERMANENT_LOCKED) == AUTHENTICATOR_PERMANENT_LOCKED) { mMultiBiometricLockoutState.setPermanentLockOut(mUserId, authenticator); } else if ((value & AUTHENTICATOR_TIMED_LOCKED) == AUTHENTICATOR_TIMED_LOCKED) { mMultiBiometricLockoutState.setTimedLockout(mUserId, authenticator); } } mRingBuffer.addApiCall("internal : onAuthSessionEnded(" + mUserId + ")"); clearSession(); } } private void clearSession() { mIsAuthenticating = false; mTimedLockouts.clear(); mAuthOperations.clear(); } Loading Loading @@ -171,7 +154,7 @@ public class AuthSessionCoordinator implements AuthSessionListener { + ", sensorId=" + sensorId + "time=" + time + ", requestId=" + requestId + ")"; mRingBuffer.addApiCall(lockedOutStr); mTimedLockouts.add(new Pair<>(biometricStrength, time)); mAuthResultCoordinator.lockOutTimed(biometricStrength); attemptToFinish(userId, sensorId, lockedOutStr); } Loading Loading @@ -202,9 +185,8 @@ public class AuthSessionCoordinator implements AuthSessionListener { // Lockouts cannot be reset by non-strong biometrics return; } mMultiBiometricLockoutState.setAuthenticatorTo(userId, biometricStrength, true /*canAuthenticate */); mMultiBiometricLockoutState.clearLockoutTime(userId, biometricStrength); mMultiBiometricLockoutState.clearPermanentLockOut(userId, biometricStrength); mMultiBiometricLockoutState.clearTimedLockout(userId, biometricStrength); } private void attemptToFinish(int userId, int sensorId, String description) { Loading services/core/java/com/android/server/biometrics/sensors/MultiBiometricLockoutState.java +40 −44 Original line number Diff line number Diff line Loading @@ -50,10 +50,11 @@ class MultiBiometricLockoutState { private Map<Integer, AuthenticatorState> createUnlockedMap() { Map<Integer, AuthenticatorState> lockOutMap = new HashMap<>(); lockOutMap.put(BIOMETRIC_STRONG, new AuthenticatorState(BIOMETRIC_STRONG, false, 0, mClock)); lockOutMap.put(BIOMETRIC_WEAK, new AuthenticatorState(BIOMETRIC_WEAK, false, 0, mClock)); new AuthenticatorState(BIOMETRIC_STRONG, false, false)); lockOutMap.put(BIOMETRIC_WEAK, new AuthenticatorState(BIOMETRIC_WEAK, false, false)); lockOutMap.put(BIOMETRIC_CONVENIENCE, new AuthenticatorState(BIOMETRIC_CONVENIENCE, false, 0, mClock)); new AuthenticatorState(BIOMETRIC_CONVENIENCE, false, false)); return lockOutMap; } Loading @@ -64,54 +65,71 @@ class MultiBiometricLockoutState { return mCanUserAuthenticate.get(userId); } void setAuthenticatorTo(int userId, @Authenticators.Types int strength, boolean canAuth) { void setPermanentLockOut(int userId, @Authenticators.Types int strength) { final Map<Integer, AuthenticatorState> authMap = getAuthMapForUser(userId); switch (strength) { case Authenticators.BIOMETRIC_STRONG: authMap.get(BIOMETRIC_STRONG).mPermanentlyLockedOut = !canAuth; authMap.get(BIOMETRIC_STRONG).mPermanentlyLockedOut = true; // fall through case Authenticators.BIOMETRIC_WEAK: authMap.get(BIOMETRIC_WEAK).mPermanentlyLockedOut = !canAuth; authMap.get(BIOMETRIC_WEAK).mPermanentlyLockedOut = true; // fall through case Authenticators.BIOMETRIC_CONVENIENCE: authMap.get(BIOMETRIC_CONVENIENCE).mPermanentlyLockedOut = !canAuth; authMap.get(BIOMETRIC_CONVENIENCE).mPermanentlyLockedOut = true; return; default: Slog.e(TAG, "increaseLockoutTime called for invalid strength : " + strength); } } void increaseLockoutTime(int userId, @Authenticators.Types int strength, long duration) { void clearPermanentLockOut(int userId, @Authenticators.Types int strength) { final Map<Integer, AuthenticatorState> authMap = getAuthMapForUser(userId); switch (strength) { case Authenticators.BIOMETRIC_STRONG: authMap.get(BIOMETRIC_STRONG).increaseLockoutTo(duration); authMap.get(BIOMETRIC_STRONG).mPermanentlyLockedOut = false; // fall through case Authenticators.BIOMETRIC_WEAK: authMap.get(BIOMETRIC_WEAK).increaseLockoutTo(duration); authMap.get(BIOMETRIC_WEAK).mPermanentlyLockedOut = false; // fall through case Authenticators.BIOMETRIC_CONVENIENCE: authMap.get(BIOMETRIC_CONVENIENCE).increaseLockoutTo(duration); authMap.get(BIOMETRIC_CONVENIENCE).mPermanentlyLockedOut = false; return; default: Slog.e(TAG, "increaseLockoutTime called for invalid strength : " + strength); } } void clearLockoutTime(int userId, @Authenticators.Types int strength) { void setTimedLockout(int userId, @Authenticators.Types int strength) { final Map<Integer, AuthenticatorState> authMap = getAuthMapForUser(userId); switch (strength) { case Authenticators.BIOMETRIC_STRONG: authMap.get(BIOMETRIC_STRONG).setTimedLockout(0); authMap.get(BIOMETRIC_STRONG).mTimedLockout = true; // fall through case Authenticators.BIOMETRIC_WEAK: authMap.get(BIOMETRIC_WEAK).setTimedLockout(0); authMap.get(BIOMETRIC_WEAK).mTimedLockout = true; // fall through case Authenticators.BIOMETRIC_CONVENIENCE: authMap.get(BIOMETRIC_CONVENIENCE).setTimedLockout(0); authMap.get(BIOMETRIC_CONVENIENCE).mTimedLockout = true; return; default: Slog.e(TAG, "clearLockoutTime called for invalid strength : " + strength); Slog.e(TAG, "increaseLockoutTime called for invalid strength : " + strength); } } void clearTimedLockout(int userId, @Authenticators.Types int strength) { final Map<Integer, AuthenticatorState> authMap = getAuthMapForUser(userId); switch (strength) { case Authenticators.BIOMETRIC_STRONG: authMap.get(BIOMETRIC_STRONG).mTimedLockout = false; // fall through case Authenticators.BIOMETRIC_WEAK: authMap.get(BIOMETRIC_WEAK).mTimedLockout = false; // fall through case Authenticators.BIOMETRIC_CONVENIENCE: authMap.get(BIOMETRIC_CONVENIENCE).mTimedLockout = false; return; default: Slog.e(TAG, "increaseLockoutTime called for invalid strength : " + strength); } } Loading @@ -132,7 +150,7 @@ class MultiBiometricLockoutState { final AuthenticatorState state = authMap.get(strength); if (state.mPermanentlyLockedOut) { return LockoutTracker.LOCKOUT_PERMANENT; } else if (state.isTimedLockout()) { } else if (state.mTimedLockout) { return LockoutTracker.LOCKOUT_TIMED; } else { return LockoutTracker.LOCKOUT_NONE; Loading @@ -158,43 +176,21 @@ class MultiBiometricLockoutState { private static class AuthenticatorState { private Integer mAuthenticatorType; private boolean mPermanentlyLockedOut; private long mTimedLockout; private Clock mClock; private boolean mTimedLockout; AuthenticatorState(Integer authenticatorId, boolean permanentlyLockedOut, long timedLockout, Clock clock) { boolean timedLockout) { mAuthenticatorType = authenticatorId; mPermanentlyLockedOut = permanentlyLockedOut; mTimedLockout = timedLockout; mClock = clock; } boolean canAuthenticate() { return !mPermanentlyLockedOut && !isTimedLockout(); } boolean isTimedLockout() { return mClock.millis() - mTimedLockout < 0; } void setTimedLockout(long duration) { mTimedLockout = duration; } /** * Either increases the lockout to duration, or leaves it as it, whichever is longer. */ void increaseLockoutTo(long duration) { mTimedLockout = Math.max(mTimedLockout, duration); } String toString(long currentTime) { final String duration = mTimedLockout - currentTime > 0 ? (mTimedLockout - currentTime) + "ms" : "none"; final String timedLockout = mTimedLockout ? "true" : "false"; final String permanentLockout = mPermanentlyLockedOut ? "true" : "false"; return String.format("(%s, permanentLockout=%s, timedLockoutRemaining=%s)", return String.format("(%s, permanentLockout=%s, timedLockout=%s)", BiometricManager.authenticatorToStr(mAuthenticatorType), permanentLockout, duration); timedLockout); } } } services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceResetLockoutClient.java +7 −4 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import com.android.server.biometrics.BiometricsProto; import com.android.server.biometrics.HardwareAuthTokenUtils; 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.ClientMonitorCallback; import com.android.server.biometrics.sensors.ErrorConsumer; import com.android.server.biometrics.sensors.HalClientMonitor; Loading Loading @@ -88,10 +89,9 @@ public class FaceResetLockoutClient extends HalClientMonitor<AidlSession> implem void onLockoutCleared() { resetLocalLockoutStateToNone(getSensorId(), getTargetUserId(), mLockoutCache, mLockoutResetDispatcher); mLockoutResetDispatcher, getBiometricContext().getAuthSessionCoordinator(), mBiometricStrength, getRequestId()); mCallback.onClientFinished(this, true /* success */); getBiometricContext().getAuthSessionCoordinator() .resetLockoutFor(getTargetUserId(), mBiometricStrength, getRequestId()); } public boolean interruptsPrecedingClients() { Loading @@ -108,7 +108,10 @@ public class FaceResetLockoutClient extends HalClientMonitor<AidlSession> implem */ static void resetLocalLockoutStateToNone(int sensorId, int userId, @NonNull LockoutCache lockoutTracker, @NonNull LockoutResetDispatcher lockoutResetDispatcher) { @NonNull LockoutResetDispatcher lockoutResetDispatcher, @NonNull AuthSessionCoordinator authSessionCoordinator, @Authenticators.Types int biometricStrength, long requestId) { authSessionCoordinator.resetLockoutFor(userId, biometricStrength, requestId); lockoutTracker.setLockoutModeForUser(userId, LockoutTracker.LOCKOUT_NONE); lockoutResetDispatcher.notifyLockoutResetCallbacks(sensorId); } Loading services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java +13 −2 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ import com.android.server.biometrics.UserStateProto; import com.android.server.biometrics.Utils; 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.AuthenticationConsumer; import com.android.server.biometrics.sensors.BaseClientMonitor; import com.android.server.biometrics.sensors.BiometricScheduler; Loading Loading @@ -127,6 +128,9 @@ public class Sensor { private final LockoutCache mLockoutCache; @NonNull private final LockoutResetDispatcher mLockoutResetDispatcher; @NonNull private AuthSessionCoordinator mAuthSessionCoordinator; @NonNull private final Callback mCallback; Loading @@ -134,6 +138,7 @@ public class Sensor { @NonNull UserAwareBiometricScheduler scheduler, int sensorId, int userId, @NonNull LockoutCache lockoutTracker, @NonNull LockoutResetDispatcher lockoutResetDispatcher, @NonNull AuthSessionCoordinator authSessionCoordinator, @NonNull Callback callback) { mContext = context; mHandler = handler; Loading @@ -143,6 +148,7 @@ public class Sensor { mUserId = userId; mLockoutCache = lockoutTracker; mLockoutResetDispatcher = lockoutResetDispatcher; mAuthSessionCoordinator = authSessionCoordinator; mCallback = callback; } Loading Loading @@ -346,8 +352,12 @@ public class Sensor { final BaseClientMonitor client = mScheduler.getCurrentClient(); if (!(client instanceof FaceResetLockoutClient)) { Slog.d(mTag, "onLockoutCleared outside of resetLockout by HAL"); // Given that onLockoutCleared() can happen at any time, and is not necessarily // coming from a specific client, set this to -1 to indicate it wasn't for a // specific request. FaceResetLockoutClient.resetLocalLockoutStateToNone(mSensorId, mUserId, mLockoutCache, mLockoutResetDispatcher); mLockoutCache, mLockoutResetDispatcher, mAuthSessionCoordinator, Utils.getCurrentStrength(mSensorId), -1 /* requestId */); } else { Slog.d(mTag, "onLockoutCleared after resetLockout"); final FaceResetLockoutClient resetLockoutClient = Loading Loading @@ -514,7 +524,8 @@ public class Sensor { final HalSessionCallback resultController = new HalSessionCallback(mContext, mHandler, mTag, mScheduler, sensorId, newUserId, mLockoutCache, lockoutResetDispatcher, () -> { lockoutResetDispatcher, biometricContext.getAuthSessionCoordinator(), () -> { Slog.e(mTag, "Got ERROR_HW_UNAVAILABLE"); mCurrentSession = null; }); Loading Loading
services/core/java/com/android/server/biometrics/sensors/AuthResultCoordinator.java +15 −4 Original line number Diff line number Diff line Loading @@ -37,13 +37,17 @@ class AuthResultCoordinator { */ static final int AUTHENTICATOR_DEFAULT = 0; /** * Indicated this authenticator has received a lockout. * Indicated this authenticator has received a permanent lockout. */ static final int AUTHENTICATOR_LOCKED = 1 << 0; static final int AUTHENTICATOR_PERMANENT_LOCKED = 1 << 0; /** * Indicates this authenticator has received a timed unlock. */ static final int AUTHENTICATOR_TIMED_LOCKED = 1 << 1; /** * Indicates this authenticator has received a successful unlock. */ static final int AUTHENTICATOR_UNLOCKED = 1 << 1; static final int AUTHENTICATOR_UNLOCKED = 1 << 2; private static final String TAG = "AuthResultCoordinator"; private final Map<Integer, Integer> mAuthenticatorState; Loading Loading @@ -85,7 +89,14 @@ class AuthResultCoordinator { * Adds a lock out of a given strength to the current operation list. */ void lockedOutFor(@Authenticators.Types int strength) { updateState(strength, (old) -> AUTHENTICATOR_LOCKED | old); updateState(strength, (old) -> AUTHENTICATOR_PERMANENT_LOCKED | old); } /** * Adds a timed lock out of a given strength to the current operation list. */ void lockOutTimed(@Authenticators.Types int strength) { updateState(strength, (old) -> AUTHENTICATOR_TIMED_LOCKED | old); } /** Loading
services/core/java/com/android/server/biometrics/sensors/AuthSessionCoordinator.java +21 −39 Original line number Diff line number Diff line Loading @@ -16,21 +16,19 @@ package com.android.server.biometrics.sensors; import static com.android.server.biometrics.sensors.AuthResultCoordinator.AUTHENTICATOR_LOCKED; import static com.android.server.biometrics.sensors.AuthResultCoordinator.AUTHENTICATOR_PERMANENT_LOCKED; import static com.android.server.biometrics.sensors.AuthResultCoordinator.AUTHENTICATOR_TIMED_LOCKED; import static com.android.server.biometrics.sensors.AuthResultCoordinator.AUTHENTICATOR_UNLOCKED; import android.hardware.biometrics.BiometricManager.Authenticators; import android.os.SystemClock; import android.util.Pair; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import java.time.Clock; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; Loading @@ -45,9 +43,7 @@ public class AuthSessionCoordinator implements AuthSessionListener { private final Set<Integer> mAuthOperations; private final MultiBiometricLockoutState mMultiBiometricLockoutState; private final List<Pair<Integer, Long>> mTimedLockouts; private final RingBuffer mRingBuffer; private final Clock mClock; private int mUserId; private boolean mIsAuthenticating; Loading @@ -63,8 +59,6 @@ public class AuthSessionCoordinator implements AuthSessionListener { mAuthResultCoordinator = new AuthResultCoordinator(); mMultiBiometricLockoutState = new MultiBiometricLockoutState(clock); mRingBuffer = new RingBuffer(100); mTimedLockouts = new ArrayList<>(); mClock = clock; } /** Loading @@ -74,8 +68,6 @@ public class AuthSessionCoordinator implements AuthSessionListener { mAuthOperations.clear(); mUserId = userId; mIsAuthenticating = true; mAuthOperations.clear(); mTimedLockouts.clear(); mAuthResultCoordinator = new AuthResultCoordinator(); mRingBuffer.addApiCall("internal : onAuthSessionStarted(" + userId + ")"); } Loading @@ -85,39 +77,30 @@ public class AuthSessionCoordinator implements AuthSessionListener { * * This can happen two ways. * 1. Manually calling this API * 2. If authStartedFor() was called, and all authentication attempts finish. * 2. If authStartedFor() was called, and any authentication attempts finish. */ void endAuthSession() { if (mIsAuthenticating) { final long currentTime = mClock.millis(); for (Pair<Integer, Long> timedLockouts : mTimedLockouts) { mMultiBiometricLockoutState.increaseLockoutTime(mUserId, timedLockouts.first, timedLockouts.second + currentTime); } // User unlocks can also unlock timed lockout Authenticator.Types final Map<Integer, Integer> result = mAuthResultCoordinator.getResult(); for (int authenticator : Arrays.asList(Authenticators.BIOMETRIC_CONVENIENCE, Authenticators.BIOMETRIC_WEAK, Authenticators.BIOMETRIC_STRONG)) { final Integer value = result.get(authenticator); if ((value & AUTHENTICATOR_UNLOCKED) == AUTHENTICATOR_UNLOCKED) { mMultiBiometricLockoutState.setAuthenticatorTo(mUserId, authenticator, true /* canAuthenticate */); mMultiBiometricLockoutState.clearLockoutTime(mUserId, authenticator); } else if ((value & AUTHENTICATOR_LOCKED) == AUTHENTICATOR_LOCKED) { mMultiBiometricLockoutState.setAuthenticatorTo(mUserId, authenticator, false /* canAuthenticate */); mMultiBiometricLockoutState.clearPermanentLockOut(mUserId, authenticator); mMultiBiometricLockoutState.clearTimedLockout(mUserId, authenticator); } else if ((value & AUTHENTICATOR_PERMANENT_LOCKED) == AUTHENTICATOR_PERMANENT_LOCKED) { mMultiBiometricLockoutState.setPermanentLockOut(mUserId, authenticator); } else if ((value & AUTHENTICATOR_TIMED_LOCKED) == AUTHENTICATOR_TIMED_LOCKED) { mMultiBiometricLockoutState.setTimedLockout(mUserId, authenticator); } } mRingBuffer.addApiCall("internal : onAuthSessionEnded(" + mUserId + ")"); clearSession(); } } private void clearSession() { mIsAuthenticating = false; mTimedLockouts.clear(); mAuthOperations.clear(); } Loading Loading @@ -171,7 +154,7 @@ public class AuthSessionCoordinator implements AuthSessionListener { + ", sensorId=" + sensorId + "time=" + time + ", requestId=" + requestId + ")"; mRingBuffer.addApiCall(lockedOutStr); mTimedLockouts.add(new Pair<>(biometricStrength, time)); mAuthResultCoordinator.lockOutTimed(biometricStrength); attemptToFinish(userId, sensorId, lockedOutStr); } Loading Loading @@ -202,9 +185,8 @@ public class AuthSessionCoordinator implements AuthSessionListener { // Lockouts cannot be reset by non-strong biometrics return; } mMultiBiometricLockoutState.setAuthenticatorTo(userId, biometricStrength, true /*canAuthenticate */); mMultiBiometricLockoutState.clearLockoutTime(userId, biometricStrength); mMultiBiometricLockoutState.clearPermanentLockOut(userId, biometricStrength); mMultiBiometricLockoutState.clearTimedLockout(userId, biometricStrength); } private void attemptToFinish(int userId, int sensorId, String description) { Loading
services/core/java/com/android/server/biometrics/sensors/MultiBiometricLockoutState.java +40 −44 Original line number Diff line number Diff line Loading @@ -50,10 +50,11 @@ class MultiBiometricLockoutState { private Map<Integer, AuthenticatorState> createUnlockedMap() { Map<Integer, AuthenticatorState> lockOutMap = new HashMap<>(); lockOutMap.put(BIOMETRIC_STRONG, new AuthenticatorState(BIOMETRIC_STRONG, false, 0, mClock)); lockOutMap.put(BIOMETRIC_WEAK, new AuthenticatorState(BIOMETRIC_WEAK, false, 0, mClock)); new AuthenticatorState(BIOMETRIC_STRONG, false, false)); lockOutMap.put(BIOMETRIC_WEAK, new AuthenticatorState(BIOMETRIC_WEAK, false, false)); lockOutMap.put(BIOMETRIC_CONVENIENCE, new AuthenticatorState(BIOMETRIC_CONVENIENCE, false, 0, mClock)); new AuthenticatorState(BIOMETRIC_CONVENIENCE, false, false)); return lockOutMap; } Loading @@ -64,54 +65,71 @@ class MultiBiometricLockoutState { return mCanUserAuthenticate.get(userId); } void setAuthenticatorTo(int userId, @Authenticators.Types int strength, boolean canAuth) { void setPermanentLockOut(int userId, @Authenticators.Types int strength) { final Map<Integer, AuthenticatorState> authMap = getAuthMapForUser(userId); switch (strength) { case Authenticators.BIOMETRIC_STRONG: authMap.get(BIOMETRIC_STRONG).mPermanentlyLockedOut = !canAuth; authMap.get(BIOMETRIC_STRONG).mPermanentlyLockedOut = true; // fall through case Authenticators.BIOMETRIC_WEAK: authMap.get(BIOMETRIC_WEAK).mPermanentlyLockedOut = !canAuth; authMap.get(BIOMETRIC_WEAK).mPermanentlyLockedOut = true; // fall through case Authenticators.BIOMETRIC_CONVENIENCE: authMap.get(BIOMETRIC_CONVENIENCE).mPermanentlyLockedOut = !canAuth; authMap.get(BIOMETRIC_CONVENIENCE).mPermanentlyLockedOut = true; return; default: Slog.e(TAG, "increaseLockoutTime called for invalid strength : " + strength); } } void increaseLockoutTime(int userId, @Authenticators.Types int strength, long duration) { void clearPermanentLockOut(int userId, @Authenticators.Types int strength) { final Map<Integer, AuthenticatorState> authMap = getAuthMapForUser(userId); switch (strength) { case Authenticators.BIOMETRIC_STRONG: authMap.get(BIOMETRIC_STRONG).increaseLockoutTo(duration); authMap.get(BIOMETRIC_STRONG).mPermanentlyLockedOut = false; // fall through case Authenticators.BIOMETRIC_WEAK: authMap.get(BIOMETRIC_WEAK).increaseLockoutTo(duration); authMap.get(BIOMETRIC_WEAK).mPermanentlyLockedOut = false; // fall through case Authenticators.BIOMETRIC_CONVENIENCE: authMap.get(BIOMETRIC_CONVENIENCE).increaseLockoutTo(duration); authMap.get(BIOMETRIC_CONVENIENCE).mPermanentlyLockedOut = false; return; default: Slog.e(TAG, "increaseLockoutTime called for invalid strength : " + strength); } } void clearLockoutTime(int userId, @Authenticators.Types int strength) { void setTimedLockout(int userId, @Authenticators.Types int strength) { final Map<Integer, AuthenticatorState> authMap = getAuthMapForUser(userId); switch (strength) { case Authenticators.BIOMETRIC_STRONG: authMap.get(BIOMETRIC_STRONG).setTimedLockout(0); authMap.get(BIOMETRIC_STRONG).mTimedLockout = true; // fall through case Authenticators.BIOMETRIC_WEAK: authMap.get(BIOMETRIC_WEAK).setTimedLockout(0); authMap.get(BIOMETRIC_WEAK).mTimedLockout = true; // fall through case Authenticators.BIOMETRIC_CONVENIENCE: authMap.get(BIOMETRIC_CONVENIENCE).setTimedLockout(0); authMap.get(BIOMETRIC_CONVENIENCE).mTimedLockout = true; return; default: Slog.e(TAG, "clearLockoutTime called for invalid strength : " + strength); Slog.e(TAG, "increaseLockoutTime called for invalid strength : " + strength); } } void clearTimedLockout(int userId, @Authenticators.Types int strength) { final Map<Integer, AuthenticatorState> authMap = getAuthMapForUser(userId); switch (strength) { case Authenticators.BIOMETRIC_STRONG: authMap.get(BIOMETRIC_STRONG).mTimedLockout = false; // fall through case Authenticators.BIOMETRIC_WEAK: authMap.get(BIOMETRIC_WEAK).mTimedLockout = false; // fall through case Authenticators.BIOMETRIC_CONVENIENCE: authMap.get(BIOMETRIC_CONVENIENCE).mTimedLockout = false; return; default: Slog.e(TAG, "increaseLockoutTime called for invalid strength : " + strength); } } Loading @@ -132,7 +150,7 @@ class MultiBiometricLockoutState { final AuthenticatorState state = authMap.get(strength); if (state.mPermanentlyLockedOut) { return LockoutTracker.LOCKOUT_PERMANENT; } else if (state.isTimedLockout()) { } else if (state.mTimedLockout) { return LockoutTracker.LOCKOUT_TIMED; } else { return LockoutTracker.LOCKOUT_NONE; Loading @@ -158,43 +176,21 @@ class MultiBiometricLockoutState { private static class AuthenticatorState { private Integer mAuthenticatorType; private boolean mPermanentlyLockedOut; private long mTimedLockout; private Clock mClock; private boolean mTimedLockout; AuthenticatorState(Integer authenticatorId, boolean permanentlyLockedOut, long timedLockout, Clock clock) { boolean timedLockout) { mAuthenticatorType = authenticatorId; mPermanentlyLockedOut = permanentlyLockedOut; mTimedLockout = timedLockout; mClock = clock; } boolean canAuthenticate() { return !mPermanentlyLockedOut && !isTimedLockout(); } boolean isTimedLockout() { return mClock.millis() - mTimedLockout < 0; } void setTimedLockout(long duration) { mTimedLockout = duration; } /** * Either increases the lockout to duration, or leaves it as it, whichever is longer. */ void increaseLockoutTo(long duration) { mTimedLockout = Math.max(mTimedLockout, duration); } String toString(long currentTime) { final String duration = mTimedLockout - currentTime > 0 ? (mTimedLockout - currentTime) + "ms" : "none"; final String timedLockout = mTimedLockout ? "true" : "false"; final String permanentLockout = mPermanentlyLockedOut ? "true" : "false"; return String.format("(%s, permanentLockout=%s, timedLockoutRemaining=%s)", return String.format("(%s, permanentLockout=%s, timedLockout=%s)", BiometricManager.authenticatorToStr(mAuthenticatorType), permanentLockout, duration); timedLockout); } } }
services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceResetLockoutClient.java +7 −4 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import com.android.server.biometrics.BiometricsProto; import com.android.server.biometrics.HardwareAuthTokenUtils; 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.ClientMonitorCallback; import com.android.server.biometrics.sensors.ErrorConsumer; import com.android.server.biometrics.sensors.HalClientMonitor; Loading Loading @@ -88,10 +89,9 @@ public class FaceResetLockoutClient extends HalClientMonitor<AidlSession> implem void onLockoutCleared() { resetLocalLockoutStateToNone(getSensorId(), getTargetUserId(), mLockoutCache, mLockoutResetDispatcher); mLockoutResetDispatcher, getBiometricContext().getAuthSessionCoordinator(), mBiometricStrength, getRequestId()); mCallback.onClientFinished(this, true /* success */); getBiometricContext().getAuthSessionCoordinator() .resetLockoutFor(getTargetUserId(), mBiometricStrength, getRequestId()); } public boolean interruptsPrecedingClients() { Loading @@ -108,7 +108,10 @@ public class FaceResetLockoutClient extends HalClientMonitor<AidlSession> implem */ static void resetLocalLockoutStateToNone(int sensorId, int userId, @NonNull LockoutCache lockoutTracker, @NonNull LockoutResetDispatcher lockoutResetDispatcher) { @NonNull LockoutResetDispatcher lockoutResetDispatcher, @NonNull AuthSessionCoordinator authSessionCoordinator, @Authenticators.Types int biometricStrength, long requestId) { authSessionCoordinator.resetLockoutFor(userId, biometricStrength, requestId); lockoutTracker.setLockoutModeForUser(userId, LockoutTracker.LOCKOUT_NONE); lockoutResetDispatcher.notifyLockoutResetCallbacks(sensorId); } Loading
services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java +13 −2 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ import com.android.server.biometrics.UserStateProto; import com.android.server.biometrics.Utils; 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.AuthenticationConsumer; import com.android.server.biometrics.sensors.BaseClientMonitor; import com.android.server.biometrics.sensors.BiometricScheduler; Loading Loading @@ -127,6 +128,9 @@ public class Sensor { private final LockoutCache mLockoutCache; @NonNull private final LockoutResetDispatcher mLockoutResetDispatcher; @NonNull private AuthSessionCoordinator mAuthSessionCoordinator; @NonNull private final Callback mCallback; Loading @@ -134,6 +138,7 @@ public class Sensor { @NonNull UserAwareBiometricScheduler scheduler, int sensorId, int userId, @NonNull LockoutCache lockoutTracker, @NonNull LockoutResetDispatcher lockoutResetDispatcher, @NonNull AuthSessionCoordinator authSessionCoordinator, @NonNull Callback callback) { mContext = context; mHandler = handler; Loading @@ -143,6 +148,7 @@ public class Sensor { mUserId = userId; mLockoutCache = lockoutTracker; mLockoutResetDispatcher = lockoutResetDispatcher; mAuthSessionCoordinator = authSessionCoordinator; mCallback = callback; } Loading Loading @@ -346,8 +352,12 @@ public class Sensor { final BaseClientMonitor client = mScheduler.getCurrentClient(); if (!(client instanceof FaceResetLockoutClient)) { Slog.d(mTag, "onLockoutCleared outside of resetLockout by HAL"); // Given that onLockoutCleared() can happen at any time, and is not necessarily // coming from a specific client, set this to -1 to indicate it wasn't for a // specific request. FaceResetLockoutClient.resetLocalLockoutStateToNone(mSensorId, mUserId, mLockoutCache, mLockoutResetDispatcher); mLockoutCache, mLockoutResetDispatcher, mAuthSessionCoordinator, Utils.getCurrentStrength(mSensorId), -1 /* requestId */); } else { Slog.d(mTag, "onLockoutCleared after resetLockout"); final FaceResetLockoutClient resetLockoutClient = Loading Loading @@ -514,7 +524,8 @@ public class Sensor { final HalSessionCallback resultController = new HalSessionCallback(mContext, mHandler, mTag, mScheduler, sensorId, newUserId, mLockoutCache, lockoutResetDispatcher, () -> { lockoutResetDispatcher, biometricContext.getAuthSessionCoordinator(), () -> { Slog.e(mTag, "Got ERROR_HW_UNAVAILABLE"); mCurrentSession = null; }); Loading