Loading services/core/java/com/android/server/locksettings/LockSettingsService.java +9 −1 Original line number Diff line number Diff line Loading @@ -260,7 +260,10 @@ public class LockSettingsService extends ILockSettings.Stub { private static final int HEADLESS_VENDOR_AUTH_SECRET_LENGTH = 32; // Order of holding lock: mSeparateChallengeLock -> mSpManager -> this // Order of holding lock: // mSeparateChallengeLock -> mSpManager // mSpManager -> this // mSpManager -> mSoftwareRateLimiter // Do not call into ActivityManager while holding mSpManager lock. private final Object mSeparateChallengeLock = new Object(); Loading Loading @@ -681,6 +684,11 @@ public class LockSettingsService extends ILockSettings.Stub { public void postDelayed(Runnable runnable, Object token, long delayMillis) { Handler.getMain().postDelayed(runnable, token, delayMillis); } @Override public int getHardwareRateLimiter(LskfIdentifier id) { return mSpManager.getHardwareRateLimiter(id); } } public LockSettingsService(Context context) { Loading services/core/java/com/android/server/locksettings/SoftwareRateLimiter.java +8 −5 Original line number Diff line number Diff line Loading @@ -252,7 +252,7 @@ class SoftwareRateLimiter { } state.savedWrongGuesses[0] = wrongGuess; state.numDuplicateWrongGuesses++; writeStats(state, /* success= */ false); writeStats(id, state, /* success= */ false); return mEnforcing ? SoftwareRateLimiterResult.duplicateWrongGuess() : SoftwareRateLimiterResult.continueToHardware(); Loading @@ -269,7 +269,7 @@ class SoftwareRateLimiter { */ synchronized void reportSuccess(LskfIdentifier id) { RateLimiterState state = getExistingState(id); writeStats(state, /* success= */ true); writeStats(id, state, /* success= */ true); // If the wrong guess counter is still 0, then there is no need to write it. Nor can there // be any saved wrong guesses, so there is no need to forget them. This optimizes for the // common case where the first guess is correct. Loading Loading @@ -327,7 +327,7 @@ class SoftwareRateLimiter { // its containing directory. This minimizes the risk of the counter being rolled back. writeWrongGuessCounter(id, state); writeStats(state, /* success= */ false); writeStats(id, state, /* success= */ false); insertNewWrongGuess(state, newWrongGuess); Loading Loading @@ -369,14 +369,15 @@ class SoftwareRateLimiter { } @GuardedBy("this") private void writeStats(RateLimiterState state, boolean success) { private void writeStats(LskfIdentifier id, RateLimiterState state, boolean success) { FrameworkStatsLog.write( FrameworkStatsLog.LSKF_AUTHENTICATION_ATTEMPTED, /* success= */ success, /* num_unique_guesses= */ state.numWrongGuesses + (success ? 1 : 0), /* num_duplicate_guesses= */ state.numDuplicateWrongGuesses, /* credential_type= */ state.statsCredentialType, /* software_rate_limiter_enforcing= */ mEnforcing); /* software_rate_limiter_enforcing= */ mEnforcing, /* hardware_rate_limiter= */ mInjector.getHardwareRateLimiter(id)); } @GuardedBy("this") Loading Loading @@ -492,5 +493,7 @@ class SoftwareRateLimiter { void removeCallbacksAndMessages(Object token); void postDelayed(Runnable runnable, Object token, long delayMillis); int getHardwareRateLimiter(LskfIdentifier id); } } services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java +19 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.Preconditions; import com.android.internal.widget.ICheckCredentialProgressCallback; import com.android.internal.widget.IWeakEscrowTokenRemovedListener; Loading Loading @@ -2173,4 +2174,22 @@ class SyntheticPasswordManager { saveState(WRONG_GUESS_COUNTER_NAME, buffer.array(), id.protectorId, id.userId); syncState(id.userId); } /** Retrieves the type of hardware rate-limiter used by a particular LSKF. */ public int getHardwareRateLimiter(LskfIdentifier id) { if (id.isSpecialCredential()) { return switch (getSpecialUserPersistentData(id.userId).type) { case PersistentData.TYPE_SP_GATEKEEPER -> FrameworkStatsLog .LSKF_AUTHENTICATION_ATTEMPTED__HARDWARE_RATE_LIMITER__GATEKEEPER; case PersistentData.TYPE_SP_WEAVER -> FrameworkStatsLog .LSKF_AUTHENTICATION_ATTEMPTED__HARDWARE_RATE_LIMITER__WEAVER; default -> FrameworkStatsLog .LSKF_AUTHENTICATION_ATTEMPTED__HARDWARE_RATE_LIMITER__UNSPECIFIED_RATELIMITER; }; } if (hasState(WEAVER_SLOT_NAME, id.protectorId, id.userId)) { return FrameworkStatsLog.LSKF_AUTHENTICATION_ATTEMPTED__HARDWARE_RATE_LIMITER__WEAVER; } return FrameworkStatsLog.LSKF_AUTHENTICATION_ATTEMPTED__HARDWARE_RATE_LIMITER__GATEKEEPER; } } services/tests/servicestests/src/com/android/server/locksettings/SoftwareRateLimiterTest.java +6 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import android.platform.test.annotations.Presubmit; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockscreenCredential; Loading Loading @@ -529,6 +530,11 @@ public class SoftwareRateLimiterTest { public void postDelayed(Runnable runnable, Object token, long delayMillis) { mWorkList.add(new WorkItem(runnable, token, delayMillis)); } @Override public int getHardwareRateLimiter(LskfIdentifier id) { return FrameworkStatsLog.LSKF_AUTHENTICATION_ATTEMPTED__HARDWARE_RATE_LIMITER__WEAVER; } } private static class WorkItem { Loading Loading
services/core/java/com/android/server/locksettings/LockSettingsService.java +9 −1 Original line number Diff line number Diff line Loading @@ -260,7 +260,10 @@ public class LockSettingsService extends ILockSettings.Stub { private static final int HEADLESS_VENDOR_AUTH_SECRET_LENGTH = 32; // Order of holding lock: mSeparateChallengeLock -> mSpManager -> this // Order of holding lock: // mSeparateChallengeLock -> mSpManager // mSpManager -> this // mSpManager -> mSoftwareRateLimiter // Do not call into ActivityManager while holding mSpManager lock. private final Object mSeparateChallengeLock = new Object(); Loading Loading @@ -681,6 +684,11 @@ public class LockSettingsService extends ILockSettings.Stub { public void postDelayed(Runnable runnable, Object token, long delayMillis) { Handler.getMain().postDelayed(runnable, token, delayMillis); } @Override public int getHardwareRateLimiter(LskfIdentifier id) { return mSpManager.getHardwareRateLimiter(id); } } public LockSettingsService(Context context) { Loading
services/core/java/com/android/server/locksettings/SoftwareRateLimiter.java +8 −5 Original line number Diff line number Diff line Loading @@ -252,7 +252,7 @@ class SoftwareRateLimiter { } state.savedWrongGuesses[0] = wrongGuess; state.numDuplicateWrongGuesses++; writeStats(state, /* success= */ false); writeStats(id, state, /* success= */ false); return mEnforcing ? SoftwareRateLimiterResult.duplicateWrongGuess() : SoftwareRateLimiterResult.continueToHardware(); Loading @@ -269,7 +269,7 @@ class SoftwareRateLimiter { */ synchronized void reportSuccess(LskfIdentifier id) { RateLimiterState state = getExistingState(id); writeStats(state, /* success= */ true); writeStats(id, state, /* success= */ true); // If the wrong guess counter is still 0, then there is no need to write it. Nor can there // be any saved wrong guesses, so there is no need to forget them. This optimizes for the // common case where the first guess is correct. Loading Loading @@ -327,7 +327,7 @@ class SoftwareRateLimiter { // its containing directory. This minimizes the risk of the counter being rolled back. writeWrongGuessCounter(id, state); writeStats(state, /* success= */ false); writeStats(id, state, /* success= */ false); insertNewWrongGuess(state, newWrongGuess); Loading Loading @@ -369,14 +369,15 @@ class SoftwareRateLimiter { } @GuardedBy("this") private void writeStats(RateLimiterState state, boolean success) { private void writeStats(LskfIdentifier id, RateLimiterState state, boolean success) { FrameworkStatsLog.write( FrameworkStatsLog.LSKF_AUTHENTICATION_ATTEMPTED, /* success= */ success, /* num_unique_guesses= */ state.numWrongGuesses + (success ? 1 : 0), /* num_duplicate_guesses= */ state.numDuplicateWrongGuesses, /* credential_type= */ state.statsCredentialType, /* software_rate_limiter_enforcing= */ mEnforcing); /* software_rate_limiter_enforcing= */ mEnforcing, /* hardware_rate_limiter= */ mInjector.getHardwareRateLimiter(id)); } @GuardedBy("this") Loading Loading @@ -492,5 +493,7 @@ class SoftwareRateLimiter { void removeCallbacksAndMessages(Object token); void postDelayed(Runnable runnable, Object token, long delayMillis); int getHardwareRateLimiter(LskfIdentifier id); } }
services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java +19 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.Preconditions; import com.android.internal.widget.ICheckCredentialProgressCallback; import com.android.internal.widget.IWeakEscrowTokenRemovedListener; Loading Loading @@ -2173,4 +2174,22 @@ class SyntheticPasswordManager { saveState(WRONG_GUESS_COUNTER_NAME, buffer.array(), id.protectorId, id.userId); syncState(id.userId); } /** Retrieves the type of hardware rate-limiter used by a particular LSKF. */ public int getHardwareRateLimiter(LskfIdentifier id) { if (id.isSpecialCredential()) { return switch (getSpecialUserPersistentData(id.userId).type) { case PersistentData.TYPE_SP_GATEKEEPER -> FrameworkStatsLog .LSKF_AUTHENTICATION_ATTEMPTED__HARDWARE_RATE_LIMITER__GATEKEEPER; case PersistentData.TYPE_SP_WEAVER -> FrameworkStatsLog .LSKF_AUTHENTICATION_ATTEMPTED__HARDWARE_RATE_LIMITER__WEAVER; default -> FrameworkStatsLog .LSKF_AUTHENTICATION_ATTEMPTED__HARDWARE_RATE_LIMITER__UNSPECIFIED_RATELIMITER; }; } if (hasState(WEAVER_SLOT_NAME, id.protectorId, id.userId)) { return FrameworkStatsLog.LSKF_AUTHENTICATION_ATTEMPTED__HARDWARE_RATE_LIMITER__WEAVER; } return FrameworkStatsLog.LSKF_AUTHENTICATION_ATTEMPTED__HARDWARE_RATE_LIMITER__GATEKEEPER; } }
services/tests/servicestests/src/com/android/server/locksettings/SoftwareRateLimiterTest.java +6 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import android.platform.test.annotations.Presubmit; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockscreenCredential; Loading Loading @@ -529,6 +530,11 @@ public class SoftwareRateLimiterTest { public void postDelayed(Runnable runnable, Object token, long delayMillis) { mWorkList.add(new WorkItem(runnable, token, delayMillis)); } @Override public int getHardwareRateLimiter(LskfIdentifier id) { return FrameworkStatsLog.LSKF_AUTHENTICATION_ATTEMPTED__HARDWARE_RATE_LIMITER__WEAVER; } } private static class WorkItem { Loading