Loading core/res/AndroidManifest.xml +0 −4 Original line number Diff line number Diff line Loading @@ -4462,10 +4462,6 @@ <permission android:name="android.permission.MANAGE_BIOMETRIC_DIALOG" android:protectionLevel="signature" /> <!-- Allows an app to reset face authentication attempt counter. Reserved for the system. @hide --> <permission android:name="android.permission.RESET_FACE_LOCKOUT" android:protectionLevel="signature" /> <!-- Allows an application to control keyguard. Only allowed for system processes. @hide --> <permission android:name="android.permission.CONTROL_KEYGUARD" Loading services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java +4 −4 Original line number Diff line number Diff line Loading @@ -37,8 +37,8 @@ import java.util.ArrayList; */ public abstract class AuthenticationClient extends ClientMonitor { public abstract int handleFailedAttempt(); public void resetFailedAttempts() {} public abstract int handleFailedAttempt(int userId); public void resetFailedAttempts(int userId) {} public static final int LOCKOUT_NONE = 0; public static final int LOCKOUT_TIMED = 1; Loading Loading @@ -179,7 +179,7 @@ public abstract class AuthenticationClient extends ClientMonitor { } result = true; if (mShouldFrameworkHandleLockout) { resetFailedAttempts(); resetFailedAttempts(getTargetUserId()); } onStop(); Loading Loading @@ -222,7 +222,7 @@ public abstract class AuthenticationClient extends ClientMonitor { } // Allow system-defined limit of number of attempts before giving up final int lockoutMode = handleFailedAttempt(); final int lockoutMode = handleFailedAttempt(getTargetUserId()); if (lockoutMode != LOCKOUT_NONE && mShouldFrameworkHandleLockout) { Slog.w(getLogTag(), "Forcing lockout (driver code should do this!), mode(" + lockoutMode + ")"); Loading services/core/java/com/android/server/biometrics/sensors/BiometricServiceBase.java +7 −18 Original line number Diff line number Diff line Loading @@ -169,17 +169,6 @@ public abstract class BiometricServiceBase extends SystemService */ protected abstract void updateActiveGroup(int userId, String clientPackage); /** * @return The protected intent to reset lockout for a specific biometric. */ protected abstract String getLockoutResetIntent(); /** * @return The permission the sender is required to have in order for the lockout reset intent * to be received by the BiometricService implementation. */ protected abstract String getLockoutBroadcastPermission(); /** * @param userId * @return Returns true if the user has any enrolled biometrics. Loading Loading @@ -218,7 +207,7 @@ public abstract class BiometricServiceBase extends SystemService /** * @return one of the AuthenticationClient LOCKOUT constants */ protected abstract int getLockoutMode(); protected abstract int getLockoutMode(int userId); protected abstract class AuthenticationClientImpl extends AuthenticationClient { Loading @@ -235,8 +224,8 @@ public abstract class BiometricServiceBase extends SystemService } @Override public int handleFailedAttempt() { final int lockoutMode = getLockoutMode(); public int handleFailedAttempt(int userId) { final int lockoutMode = getLockoutMode(userId); if (lockoutMode == AuthenticationClient.LOCKOUT_PERMANENT) { mPerformanceStats.permanentLockout++; } else if (lockoutMode == AuthenticationClient.LOCKOUT_TIMED) { Loading Loading @@ -407,8 +396,7 @@ public abstract class BiometricServiceBase extends SystemService context.getResources().getString(R.string.config_keyguardComponent)); mKeyguardPackage = keyguardComponent != null ? keyguardComponent.getPackageName() : null; mAppOps = context.getSystemService(AppOpsManager.class); mActivityTaskManager = ((ActivityTaskManager) context.getSystemService( Context.ACTIVITY_TASK_SERVICE)).getService(); mActivityTaskManager = ActivityTaskManager.getService(); mPowerManager = mContext.getSystemService(PowerManager.class); mUserManager = UserManager.get(mContext); mMetricsLogger = new MetricsLogger(); Loading Loading @@ -476,7 +464,8 @@ public abstract class BiometricServiceBase extends SystemService if (client != null && client.onAcquired(acquiredInfo, vendorCode)) { removeClient(client); } if (mPerformanceStats != null && getLockoutMode() == AuthenticationClient.LOCKOUT_NONE if (mPerformanceStats != null && getLockoutMode(client.getTargetUserId()) == AuthenticationClient.LOCKOUT_NONE && client instanceof AuthenticationClient) { // ignore enrollment acquisitions or acquisitions when we're locked out mPerformanceStats.acquire++; Loading Loading @@ -692,7 +681,7 @@ public abstract class BiometricServiceBase extends SystemService private void startAuthentication(AuthenticationClientImpl client, String opPackageName) { if (DEBUG) Slog.v(getTag(), "startAuthentication(" + opPackageName + ")"); int lockoutMode = getLockoutMode(); int lockoutMode = getLockoutMode(client.getTargetUserId()); if (lockoutMode != AuthenticationClient.LOCKOUT_NONE) { Slog.v(getTag(), "In lockout mode(" + lockoutMode + ") ; disallowing authentication"); int errorCode = lockoutMode == AuthenticationClient.LOCKOUT_TIMED ? Loading services/core/java/com/android/server/biometrics/sensors/face/FaceService.java +1 −12 Original line number Diff line number Diff line Loading @@ -18,7 +18,6 @@ package com.android.server.biometrics.sensors.face; import static android.Manifest.permission.INTERACT_ACROSS_USERS; import static android.Manifest.permission.MANAGE_BIOMETRIC; import static android.Manifest.permission.RESET_FACE_LOCKOUT; import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL; import android.app.ActivityManager; Loading Loading @@ -1046,16 +1045,6 @@ public class FaceService extends BiometricServiceBase { } } @Override protected String getLockoutResetIntent() { return ACTION_LOCKOUT_RESET; } @Override protected String getLockoutBroadcastPermission() { return RESET_FACE_LOCKOUT; } @Override protected void handleUserSwitching(int userId) { super.handleUserSwitching(userId); Loading Loading @@ -1103,7 +1092,7 @@ public class FaceService extends BiometricServiceBase { } @Override protected int getLockoutMode() { protected int getLockoutMode(int userId) { return mCurrentUserLockoutMode; } Loading services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java +21 −118 Original line number Diff line number Diff line Loading @@ -25,13 +25,8 @@ import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL; import static android.Manifest.permission.USE_FINGERPRINT; import android.app.ActivityManager; import android.app.AlarmManager; import android.app.AppOpsManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.hardware.biometrics.BiometricConstants; Loading @@ -51,12 +46,9 @@ import android.os.IBinder; import android.os.NativeHandle; import android.os.RemoteException; import android.os.SELinux; import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; import android.util.Slog; import android.util.SparseBooleanArray; import android.util.SparseIntArray; import android.util.proto.ProtoOutputStream; import android.view.Surface; Loading @@ -64,16 +56,15 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.logging.MetricsLogger; import com.android.internal.util.DumpUtils; import com.android.server.SystemServerInitThreadPool; import com.android.server.biometrics.sensors.AuthenticationClient; import com.android.server.biometrics.fingerprint.FingerprintServiceDumpProto; import com.android.server.biometrics.fingerprint.FingerprintUserStatsProto; import com.android.server.biometrics.fingerprint.PerformanceStatsProto; import com.android.server.biometrics.sensors.BiometricServiceBase; import com.android.server.biometrics.sensors.BiometricUtils; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.Constants; import com.android.server.biometrics.sensors.EnrollClient; import com.android.server.biometrics.sensors.RemovalClient; import com.android.server.biometrics.fingerprint.FingerprintServiceDumpProto; import com.android.server.biometrics.fingerprint.FingerprintUserStatsProto; import com.android.server.biometrics.fingerprint.PerformanceStatsProto; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import org.json.JSONArray; import org.json.JSONException; Loading @@ -99,31 +90,6 @@ public class FingerprintService extends BiometricServiceBase { protected static final String TAG = "FingerprintService"; private static final boolean DEBUG = true; private static final String FP_DATA_DIR = "fpdata"; private static final String ACTION_LOCKOUT_RESET = "com.android.server.biometrics.fingerprint.ACTION_LOCKOUT_RESET"; private static final int MAX_FAILED_ATTEMPTS_LOCKOUT_TIMED = 5; private static final int MAX_FAILED_ATTEMPTS_LOCKOUT_PERMANENT = 20; private static final long FAIL_LOCKOUT_TIMEOUT_MS = 30 * 1000; private static final String KEY_LOCKOUT_RESET_USER = "lockout_reset_user"; private final class ResetFailedAttemptsForUserRunnable implements Runnable { @Override public void run() { resetFailedAttemptsForUser(true /* clearAttemptCounter */, ActivityManager.getCurrentUser()); } } private final class LockoutReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Slog.v(getTag(), "Resetting lockout: " + intent.getAction()); if (getLockoutResetIntent().equals(intent.getAction())) { final int user = intent.getIntExtra(KEY_LOCKOUT_RESET_USER, 0); resetFailedAttemptsForUser(false /* clearAttemptCounter */, user); } } } private final class FingerprintAuthClient extends AuthenticationClientImpl { public FingerprintAuthClient(Context context, Loading @@ -139,9 +105,8 @@ public class FingerprintService extends BiometricServiceBase { } @Override public void resetFailedAttempts() { resetFailedAttemptsForUser(true /* clearAttemptCounter */, ActivityManager.getCurrentUser()); public void resetFailedAttempts(int userId) { mLockoutTracker.resetFailedAttemptsForUser(true /* clearAttemptCounter */, userId); } @Override Loading @@ -151,16 +116,9 @@ public class FingerprintService extends BiometricServiceBase { } @Override public int handleFailedAttempt() { final int currentUser = ActivityManager.getCurrentUser(); mFailedAttempts.put(currentUser, mFailedAttempts.get(currentUser, 0) + 1); mTimedLockoutCleared.put(ActivityManager.getCurrentUser(), false); if (getLockoutMode() != AuthenticationClient.LOCKOUT_NONE) { scheduleLockoutResetForUser(currentUser); } return super.handleFailedAttempt(); public int handleFailedAttempt(int userId) { mLockoutTracker.addFailedAttemptForUser(userId); return super.handleFailedAttempt(userId); } } Loading Loading @@ -390,7 +348,10 @@ public class FingerprintService extends BiometricServiceBase { } // TODO: confirm security token when we move timeout management into the HAL layer. mHandler.post(mResetFailedAttemptsForCurrentUserRunnable); mHandler.post(() -> { mLockoutTracker.resetFailedAttemptsForUser(true /* clearAttemptCounter */, mCurrentUserId); }); } @Override Loading Loading @@ -420,18 +381,17 @@ public class FingerprintService extends BiometricServiceBase { } } private final LockoutTracker mLockoutTracker; private final FingerprintConstants mFingerprintConstants = new FingerprintConstants(); private final CopyOnWriteArrayList<IFingerprintClientActiveCallback> mClientActiveCallbacks = new CopyOnWriteArrayList<>(); @GuardedBy("this") private IBiometricsFingerprint mDaemon; private final SparseBooleanArray mTimedLockoutCleared; private final SparseIntArray mFailedAttempts; private final AlarmManager mAlarmManager; private final LockoutReceiver mLockoutReceiver = new LockoutReceiver(); protected final ResetFailedAttemptsForUserRunnable mResetFailedAttemptsForCurrentUserRunnable = new ResetFailedAttemptsForUserRunnable(); private final LockoutTracker.LockoutResetCallback mLockoutResetCallback = userId -> { notifyLockoutResetMonitors(); }; /** * Receives callbacks from the HAL. Loading Loading @@ -573,11 +533,7 @@ public class FingerprintService extends BiometricServiceBase { public FingerprintService(Context context) { super(context); mTimedLockoutCleared = new SparseBooleanArray(); mFailedAttempts = new SparseIntArray(); mAlarmManager = context.getSystemService(AlarmManager.class); context.registerReceiver(mLockoutReceiver, new IntentFilter(getLockoutResetIntent()), getLockoutBroadcastPermission(), null /* handler */); mLockoutTracker = new LockoutTracker(context, mLockoutResetCallback); } @Override Loading Loading @@ -671,16 +627,6 @@ public class FingerprintService extends BiometricServiceBase { } } @Override protected String getLockoutResetIntent() { return ACTION_LOCKOUT_RESET; } @Override protected String getLockoutBroadcastPermission() { return RESET_FINGERPRINT_LOCKOUT; } @Override protected boolean hasEnrolledBiometrics(int userId) { if (userId != UserHandle.getCallingUserId()) { Loading Loading @@ -742,17 +688,8 @@ public class FingerprintService extends BiometricServiceBase { } @Override protected int getLockoutMode() { final int currentUser = ActivityManager.getCurrentUser(); final int failedAttempts = mFailedAttempts.get(currentUser, 0); if (failedAttempts >= MAX_FAILED_ATTEMPTS_LOCKOUT_PERMANENT) { return AuthenticationClient.LOCKOUT_PERMANENT; } else if (failedAttempts > 0 && !mTimedLockoutCleared.get(currentUser, false) && (failedAttempts % MAX_FAILED_ATTEMPTS_LOCKOUT_TIMED == 0)) { return AuthenticationClient.LOCKOUT_TIMED; } return AuthenticationClient.LOCKOUT_NONE; protected int getLockoutMode(int userId) { return mLockoutTracker.getLockoutModeForUser(userId); } /** Gets the fingerprint daemon */ Loading Loading @@ -823,40 +760,6 @@ public class FingerprintService extends BiometricServiceBase { return 0; } // Attempt counter should only be cleared when Keyguard goes away or when // a biometric is successfully authenticated. Lockout should eventually be done below the HAL. // See AuthenticationClient#shouldFrameworkHandleLockout(). private void resetFailedAttemptsForUser(boolean clearAttemptCounter, int userId) { if (DEBUG && getLockoutMode() != AuthenticationClient.LOCKOUT_NONE) { Slog.v(getTag(), "Reset biometric lockout, clearAttemptCounter=" + clearAttemptCounter); } if (clearAttemptCounter) { mFailedAttempts.put(userId, 0); } mTimedLockoutCleared.put(userId, true); // If we're asked to reset failed attempts externally (i.e. from Keyguard), // the alarm might still be pending; remove it. cancelLockoutResetForUser(userId); notifyLockoutResetMonitors(); } private void cancelLockoutResetForUser(int userId) { mAlarmManager.cancel(getLockoutResetIntentForUser(userId)); } private void scheduleLockoutResetForUser(int userId) { mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + FAIL_LOCKOUT_TIMEOUT_MS, getLockoutResetIntentForUser(userId)); } private PendingIntent getLockoutResetIntentForUser(int userId) { return PendingIntent.getBroadcast(getContext(), userId, new Intent(getLockoutResetIntent()).putExtra(KEY_LOCKOUT_RESET_USER, userId), PendingIntent.FLAG_UPDATE_CURRENT); } private native NativeHandle convertSurfaceToNativeHandle(Surface surface); private void dumpInternal(PrintWriter pw) { Loading Loading
core/res/AndroidManifest.xml +0 −4 Original line number Diff line number Diff line Loading @@ -4462,10 +4462,6 @@ <permission android:name="android.permission.MANAGE_BIOMETRIC_DIALOG" android:protectionLevel="signature" /> <!-- Allows an app to reset face authentication attempt counter. Reserved for the system. @hide --> <permission android:name="android.permission.RESET_FACE_LOCKOUT" android:protectionLevel="signature" /> <!-- Allows an application to control keyguard. Only allowed for system processes. @hide --> <permission android:name="android.permission.CONTROL_KEYGUARD" Loading
services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java +4 −4 Original line number Diff line number Diff line Loading @@ -37,8 +37,8 @@ import java.util.ArrayList; */ public abstract class AuthenticationClient extends ClientMonitor { public abstract int handleFailedAttempt(); public void resetFailedAttempts() {} public abstract int handleFailedAttempt(int userId); public void resetFailedAttempts(int userId) {} public static final int LOCKOUT_NONE = 0; public static final int LOCKOUT_TIMED = 1; Loading Loading @@ -179,7 +179,7 @@ public abstract class AuthenticationClient extends ClientMonitor { } result = true; if (mShouldFrameworkHandleLockout) { resetFailedAttempts(); resetFailedAttempts(getTargetUserId()); } onStop(); Loading Loading @@ -222,7 +222,7 @@ public abstract class AuthenticationClient extends ClientMonitor { } // Allow system-defined limit of number of attempts before giving up final int lockoutMode = handleFailedAttempt(); final int lockoutMode = handleFailedAttempt(getTargetUserId()); if (lockoutMode != LOCKOUT_NONE && mShouldFrameworkHandleLockout) { Slog.w(getLogTag(), "Forcing lockout (driver code should do this!), mode(" + lockoutMode + ")"); Loading
services/core/java/com/android/server/biometrics/sensors/BiometricServiceBase.java +7 −18 Original line number Diff line number Diff line Loading @@ -169,17 +169,6 @@ public abstract class BiometricServiceBase extends SystemService */ protected abstract void updateActiveGroup(int userId, String clientPackage); /** * @return The protected intent to reset lockout for a specific biometric. */ protected abstract String getLockoutResetIntent(); /** * @return The permission the sender is required to have in order for the lockout reset intent * to be received by the BiometricService implementation. */ protected abstract String getLockoutBroadcastPermission(); /** * @param userId * @return Returns true if the user has any enrolled biometrics. Loading Loading @@ -218,7 +207,7 @@ public abstract class BiometricServiceBase extends SystemService /** * @return one of the AuthenticationClient LOCKOUT constants */ protected abstract int getLockoutMode(); protected abstract int getLockoutMode(int userId); protected abstract class AuthenticationClientImpl extends AuthenticationClient { Loading @@ -235,8 +224,8 @@ public abstract class BiometricServiceBase extends SystemService } @Override public int handleFailedAttempt() { final int lockoutMode = getLockoutMode(); public int handleFailedAttempt(int userId) { final int lockoutMode = getLockoutMode(userId); if (lockoutMode == AuthenticationClient.LOCKOUT_PERMANENT) { mPerformanceStats.permanentLockout++; } else if (lockoutMode == AuthenticationClient.LOCKOUT_TIMED) { Loading Loading @@ -407,8 +396,7 @@ public abstract class BiometricServiceBase extends SystemService context.getResources().getString(R.string.config_keyguardComponent)); mKeyguardPackage = keyguardComponent != null ? keyguardComponent.getPackageName() : null; mAppOps = context.getSystemService(AppOpsManager.class); mActivityTaskManager = ((ActivityTaskManager) context.getSystemService( Context.ACTIVITY_TASK_SERVICE)).getService(); mActivityTaskManager = ActivityTaskManager.getService(); mPowerManager = mContext.getSystemService(PowerManager.class); mUserManager = UserManager.get(mContext); mMetricsLogger = new MetricsLogger(); Loading Loading @@ -476,7 +464,8 @@ public abstract class BiometricServiceBase extends SystemService if (client != null && client.onAcquired(acquiredInfo, vendorCode)) { removeClient(client); } if (mPerformanceStats != null && getLockoutMode() == AuthenticationClient.LOCKOUT_NONE if (mPerformanceStats != null && getLockoutMode(client.getTargetUserId()) == AuthenticationClient.LOCKOUT_NONE && client instanceof AuthenticationClient) { // ignore enrollment acquisitions or acquisitions when we're locked out mPerformanceStats.acquire++; Loading Loading @@ -692,7 +681,7 @@ public abstract class BiometricServiceBase extends SystemService private void startAuthentication(AuthenticationClientImpl client, String opPackageName) { if (DEBUG) Slog.v(getTag(), "startAuthentication(" + opPackageName + ")"); int lockoutMode = getLockoutMode(); int lockoutMode = getLockoutMode(client.getTargetUserId()); if (lockoutMode != AuthenticationClient.LOCKOUT_NONE) { Slog.v(getTag(), "In lockout mode(" + lockoutMode + ") ; disallowing authentication"); int errorCode = lockoutMode == AuthenticationClient.LOCKOUT_TIMED ? Loading
services/core/java/com/android/server/biometrics/sensors/face/FaceService.java +1 −12 Original line number Diff line number Diff line Loading @@ -18,7 +18,6 @@ package com.android.server.biometrics.sensors.face; import static android.Manifest.permission.INTERACT_ACROSS_USERS; import static android.Manifest.permission.MANAGE_BIOMETRIC; import static android.Manifest.permission.RESET_FACE_LOCKOUT; import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL; import android.app.ActivityManager; Loading Loading @@ -1046,16 +1045,6 @@ public class FaceService extends BiometricServiceBase { } } @Override protected String getLockoutResetIntent() { return ACTION_LOCKOUT_RESET; } @Override protected String getLockoutBroadcastPermission() { return RESET_FACE_LOCKOUT; } @Override protected void handleUserSwitching(int userId) { super.handleUserSwitching(userId); Loading Loading @@ -1103,7 +1092,7 @@ public class FaceService extends BiometricServiceBase { } @Override protected int getLockoutMode() { protected int getLockoutMode(int userId) { return mCurrentUserLockoutMode; } Loading
services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java +21 −118 Original line number Diff line number Diff line Loading @@ -25,13 +25,8 @@ import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL; import static android.Manifest.permission.USE_FINGERPRINT; import android.app.ActivityManager; import android.app.AlarmManager; import android.app.AppOpsManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.hardware.biometrics.BiometricConstants; Loading @@ -51,12 +46,9 @@ import android.os.IBinder; import android.os.NativeHandle; import android.os.RemoteException; import android.os.SELinux; import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; import android.util.Slog; import android.util.SparseBooleanArray; import android.util.SparseIntArray; import android.util.proto.ProtoOutputStream; import android.view.Surface; Loading @@ -64,16 +56,15 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.logging.MetricsLogger; import com.android.internal.util.DumpUtils; import com.android.server.SystemServerInitThreadPool; import com.android.server.biometrics.sensors.AuthenticationClient; import com.android.server.biometrics.fingerprint.FingerprintServiceDumpProto; import com.android.server.biometrics.fingerprint.FingerprintUserStatsProto; import com.android.server.biometrics.fingerprint.PerformanceStatsProto; import com.android.server.biometrics.sensors.BiometricServiceBase; import com.android.server.biometrics.sensors.BiometricUtils; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.Constants; import com.android.server.biometrics.sensors.EnrollClient; import com.android.server.biometrics.sensors.RemovalClient; import com.android.server.biometrics.fingerprint.FingerprintServiceDumpProto; import com.android.server.biometrics.fingerprint.FingerprintUserStatsProto; import com.android.server.biometrics.fingerprint.PerformanceStatsProto; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import org.json.JSONArray; import org.json.JSONException; Loading @@ -99,31 +90,6 @@ public class FingerprintService extends BiometricServiceBase { protected static final String TAG = "FingerprintService"; private static final boolean DEBUG = true; private static final String FP_DATA_DIR = "fpdata"; private static final String ACTION_LOCKOUT_RESET = "com.android.server.biometrics.fingerprint.ACTION_LOCKOUT_RESET"; private static final int MAX_FAILED_ATTEMPTS_LOCKOUT_TIMED = 5; private static final int MAX_FAILED_ATTEMPTS_LOCKOUT_PERMANENT = 20; private static final long FAIL_LOCKOUT_TIMEOUT_MS = 30 * 1000; private static final String KEY_LOCKOUT_RESET_USER = "lockout_reset_user"; private final class ResetFailedAttemptsForUserRunnable implements Runnable { @Override public void run() { resetFailedAttemptsForUser(true /* clearAttemptCounter */, ActivityManager.getCurrentUser()); } } private final class LockoutReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Slog.v(getTag(), "Resetting lockout: " + intent.getAction()); if (getLockoutResetIntent().equals(intent.getAction())) { final int user = intent.getIntExtra(KEY_LOCKOUT_RESET_USER, 0); resetFailedAttemptsForUser(false /* clearAttemptCounter */, user); } } } private final class FingerprintAuthClient extends AuthenticationClientImpl { public FingerprintAuthClient(Context context, Loading @@ -139,9 +105,8 @@ public class FingerprintService extends BiometricServiceBase { } @Override public void resetFailedAttempts() { resetFailedAttemptsForUser(true /* clearAttemptCounter */, ActivityManager.getCurrentUser()); public void resetFailedAttempts(int userId) { mLockoutTracker.resetFailedAttemptsForUser(true /* clearAttemptCounter */, userId); } @Override Loading @@ -151,16 +116,9 @@ public class FingerprintService extends BiometricServiceBase { } @Override public int handleFailedAttempt() { final int currentUser = ActivityManager.getCurrentUser(); mFailedAttempts.put(currentUser, mFailedAttempts.get(currentUser, 0) + 1); mTimedLockoutCleared.put(ActivityManager.getCurrentUser(), false); if (getLockoutMode() != AuthenticationClient.LOCKOUT_NONE) { scheduleLockoutResetForUser(currentUser); } return super.handleFailedAttempt(); public int handleFailedAttempt(int userId) { mLockoutTracker.addFailedAttemptForUser(userId); return super.handleFailedAttempt(userId); } } Loading Loading @@ -390,7 +348,10 @@ public class FingerprintService extends BiometricServiceBase { } // TODO: confirm security token when we move timeout management into the HAL layer. mHandler.post(mResetFailedAttemptsForCurrentUserRunnable); mHandler.post(() -> { mLockoutTracker.resetFailedAttemptsForUser(true /* clearAttemptCounter */, mCurrentUserId); }); } @Override Loading Loading @@ -420,18 +381,17 @@ public class FingerprintService extends BiometricServiceBase { } } private final LockoutTracker mLockoutTracker; private final FingerprintConstants mFingerprintConstants = new FingerprintConstants(); private final CopyOnWriteArrayList<IFingerprintClientActiveCallback> mClientActiveCallbacks = new CopyOnWriteArrayList<>(); @GuardedBy("this") private IBiometricsFingerprint mDaemon; private final SparseBooleanArray mTimedLockoutCleared; private final SparseIntArray mFailedAttempts; private final AlarmManager mAlarmManager; private final LockoutReceiver mLockoutReceiver = new LockoutReceiver(); protected final ResetFailedAttemptsForUserRunnable mResetFailedAttemptsForCurrentUserRunnable = new ResetFailedAttemptsForUserRunnable(); private final LockoutTracker.LockoutResetCallback mLockoutResetCallback = userId -> { notifyLockoutResetMonitors(); }; /** * Receives callbacks from the HAL. Loading Loading @@ -573,11 +533,7 @@ public class FingerprintService extends BiometricServiceBase { public FingerprintService(Context context) { super(context); mTimedLockoutCleared = new SparseBooleanArray(); mFailedAttempts = new SparseIntArray(); mAlarmManager = context.getSystemService(AlarmManager.class); context.registerReceiver(mLockoutReceiver, new IntentFilter(getLockoutResetIntent()), getLockoutBroadcastPermission(), null /* handler */); mLockoutTracker = new LockoutTracker(context, mLockoutResetCallback); } @Override Loading Loading @@ -671,16 +627,6 @@ public class FingerprintService extends BiometricServiceBase { } } @Override protected String getLockoutResetIntent() { return ACTION_LOCKOUT_RESET; } @Override protected String getLockoutBroadcastPermission() { return RESET_FINGERPRINT_LOCKOUT; } @Override protected boolean hasEnrolledBiometrics(int userId) { if (userId != UserHandle.getCallingUserId()) { Loading Loading @@ -742,17 +688,8 @@ public class FingerprintService extends BiometricServiceBase { } @Override protected int getLockoutMode() { final int currentUser = ActivityManager.getCurrentUser(); final int failedAttempts = mFailedAttempts.get(currentUser, 0); if (failedAttempts >= MAX_FAILED_ATTEMPTS_LOCKOUT_PERMANENT) { return AuthenticationClient.LOCKOUT_PERMANENT; } else if (failedAttempts > 0 && !mTimedLockoutCleared.get(currentUser, false) && (failedAttempts % MAX_FAILED_ATTEMPTS_LOCKOUT_TIMED == 0)) { return AuthenticationClient.LOCKOUT_TIMED; } return AuthenticationClient.LOCKOUT_NONE; protected int getLockoutMode(int userId) { return mLockoutTracker.getLockoutModeForUser(userId); } /** Gets the fingerprint daemon */ Loading Loading @@ -823,40 +760,6 @@ public class FingerprintService extends BiometricServiceBase { return 0; } // Attempt counter should only be cleared when Keyguard goes away or when // a biometric is successfully authenticated. Lockout should eventually be done below the HAL. // See AuthenticationClient#shouldFrameworkHandleLockout(). private void resetFailedAttemptsForUser(boolean clearAttemptCounter, int userId) { if (DEBUG && getLockoutMode() != AuthenticationClient.LOCKOUT_NONE) { Slog.v(getTag(), "Reset biometric lockout, clearAttemptCounter=" + clearAttemptCounter); } if (clearAttemptCounter) { mFailedAttempts.put(userId, 0); } mTimedLockoutCleared.put(userId, true); // If we're asked to reset failed attempts externally (i.e. from Keyguard), // the alarm might still be pending; remove it. cancelLockoutResetForUser(userId); notifyLockoutResetMonitors(); } private void cancelLockoutResetForUser(int userId) { mAlarmManager.cancel(getLockoutResetIntentForUser(userId)); } private void scheduleLockoutResetForUser(int userId) { mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + FAIL_LOCKOUT_TIMEOUT_MS, getLockoutResetIntentForUser(userId)); } private PendingIntent getLockoutResetIntentForUser(int userId) { return PendingIntent.getBroadcast(getContext(), userId, new Intent(getLockoutResetIntent()).putExtra(KEY_LOCKOUT_RESET_USER, userId), PendingIntent.FLAG_UPDATE_CURRENT); } private native NativeHandle convertSurfaceToNativeHandle(Surface surface); private void dumpInternal(PrintWriter pw) { Loading