Loading core/java/com/android/internal/widget/LockPatternUtils.java +9 −1 Original line number Diff line number Diff line Loading @@ -83,6 +83,13 @@ public class LockPatternUtils { */ public static final long FAILED_ATTEMPT_COUNTDOWN_INTERVAL_MS = 1000L; /** * This dictates when we start telling the user that continued failed attempts will wipe * their device. */ public static final int FAILED_ATTEMPTS_BEFORE_WIPE_GRACE = 5; /** * The minimum number of dots in a valid pattern. */ Loading @@ -93,7 +100,7 @@ public class LockPatternUtils { * attempt for it to be counted against the counts that affect * {@link #FAILED_ATTEMPTS_BEFORE_TIMEOUT} and {@link #FAILED_ATTEMPTS_BEFORE_RESET} */ public static final int MIN_PATTERN_REGISTER_FAIL = 3; public static final int MIN_PATTERN_REGISTER_FAIL = MIN_LOCK_PATTERN_SIZE; private final static String LOCKOUT_PERMANENT_KEY = "lockscreen.lockedoutpermanently"; private final static String LOCKOUT_ATTEMPT_DEADLINE = "lockscreen.lockoutattemptdeadline"; Loading @@ -112,6 +119,7 @@ public class LockPatternUtils { private static final AtomicBoolean sHaveNonZeroPatternFile = new AtomicBoolean(false); private static final AtomicBoolean sHaveNonZeroPasswordFile = new AtomicBoolean(false); private static FileObserver sPasswordObserver; private static class PasswordFileObserver extends FileObserver { Loading core/res/res/values/strings.xml +35 −4 Original line number Diff line number Diff line Loading @@ -1857,7 +1857,7 @@ \n\nPlease try again in <xliff:g id="number">%d</xliff:g> seconds. </string> <!-- For the unlock screen, Information message shown in dialog when user is almost at the limit <!-- For the unlock screen, informational message shown in dialog when user is almost at the limit where they will be locked out and may have to enter an alternate username/password to unlock the phone --> <string name="lockscreen_failed_attempts_almost_glogin" product="tablet"> You have incorrectly drawn your unlock pattern <xliff:g id="number">%d</xliff:g> times. Loading @@ -1865,7 +1865,8 @@ you will be asked to unlock your tablet using your Google sign-in.\n\n Please try again in <xliff:g id="number">%d</xliff:g> seconds. </string> <!-- For the unlock screen, Information message shown in dialog when user is almost at the limit <!-- For the unlock screen, informational message shown in dialog when user is almost at the limit where they will be locked out and may have to enter an alternate username/password to unlock the phone --> <string name="lockscreen_failed_attempts_almost_glogin" product="default"> You have incorrectly drawn your unlock pattern <xliff:g id="number">%d</xliff:g> times. Loading @@ -1874,6 +1875,36 @@ Please try again in <xliff:g id="number">%d</xliff:g> seconds. </string> <!-- For the unlock screen, informational message shown in dialog when user is almost at the limit where the device will be wiped. --> <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet"> You have incorrectly attempted to unlock the tablet <xliff:g id="number">%d</xliff:g> times. After <xliff:g id="number">%d</xliff:g> more unsuccessful attempts, the tablet will be reset to factory default and all user data will be lost. </string> <!-- For the unlock screen, informational message shown in dialog when user is almost at the limit where the device will be wiped. --> <string name="lockscreen_failed_attempts_almost_at_wipe" product="default"> You have incorrectly attempted to unlock the phone <xliff:g id="number">%d</xliff:g> times. After <xliff:g id="number">%d</xliff:g> more unsuccessful attempts, the phone will be reset to factory default and all user data will be lost. </string> <!-- For the unlock screen, informational message shown in dialog when user has exceeded the maximum attempts and the device will now be wiped --> <string name="lockscreen_failed_attempts_now_wiping" product="tablet"> You have incorrectly attempted to unlock the tablet <xliff:g id="number">%d</xliff:g> times. The tablet will now be reset to factory default. </string> <!-- For the unlock screen, informational message shown in dialog when user has exceeded the maximum attempts and the device will now be wiped --> <string name="lockscreen_failed_attempts_now_wiping" product="default"> You have incorrectly attempted to unlock the phone <xliff:g id="number">%d</xliff:g> times. The phone will now be reset to factory default. </string> <!-- On the unlock screen, countdown message shown while user is waiting to try again after too many failed attempts --> <string name="lockscreen_too_many_failed_attempts_countdown">Try again in <xliff:g id="number">%d</xliff:g> seconds.</string> Loading policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java +76 −49 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import android.os.SystemProperties; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Log; import android.util.Slog; import android.view.KeyEvent; import android.view.View; import android.view.WindowManager; Loading Loading @@ -294,23 +295,48 @@ public class LockPatternKeyguardView extends KeyguardViewBase { public void reportFailedUnlockAttempt() { mUpdateMonitor.reportFailedAttempt(); final int failedAttempts = mUpdateMonitor.getFailedAttempts(); if (DEBUG) Log.d(TAG, "reportFailedPatternAttempt: #" + failedAttempts + if (DEBUG) Log.d(TAG, "reportFailedPatternAttempt: #" + failedAttempts + " (enableFallback=" + mEnableFallback + ")"); final boolean usingLockPattern = mLockPatternUtils.getKeyguardStoredPasswordQuality() final boolean usingPattern = mLockPatternUtils.getKeyguardStoredPasswordQuality() == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; if (usingLockPattern && mEnableFallback && failedAttempts == (LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) { final int failedAttemptsBeforeWipe = mLockPatternUtils.getDevicePolicyManager() .getMaximumFailedPasswordsForWipe(null); final int failedAttemptWarning = LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT; final int remainingBeforeWipe = failedAttemptsBeforeWipe > 0 ? (failedAttemptsBeforeWipe - failedAttempts) : Integer.MAX_VALUE; // because DPM returns 0 if no restriction if (remainingBeforeWipe < LockPatternUtils.FAILED_ATTEMPTS_BEFORE_WIPE_GRACE) { // If we reach this code, it means the user has installed a DevicePolicyManager // that requests device wipe after N attempts. Once we get below the grace // period, we'll post this dialog every time as a clear warning until the // bombshell hits and the device is wiped. if (remainingBeforeWipe > 0) { showAlmostAtWipeDialog(failedAttempts, remainingBeforeWipe); } else { // Too many attempts. The device will be wiped shortly. Slog.i(TAG, "Too many unlock attempts; device will be wiped!"); showWipeDialog(failedAttempts); } } else if (usingPattern && mEnableFallback) { if (failedAttempts == failedAttemptWarning) { showAlmostAtAccountLoginDialog(); } else if (usingLockPattern && mEnableFallback && failedAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET) { } else if (failedAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET) { mLockPatternUtils.setPermanentlyLocked(true); updateScreen(mMode); } else if ((failedAttempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) == 0) { } } else { final boolean showTimeout = (failedAttempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) == 0; if (showTimeout) { showTimeoutDialog(); } } mLockPatternUtils.reportFailedPasswordAttempt(); } Loading Loading @@ -727,23 +753,9 @@ public class LockPatternKeyguardView extends KeyguardViewBase { return currentMode; } private void showTimeoutDialog() { int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000; int messageId = R.string.lockscreen_too_many_failed_attempts_dialog_message; if(getUnlockMode() == UnlockMode.Password) { if(mLockPatternUtils.getKeyguardStoredPasswordQuality() == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) { messageId = R.string.lockscreen_too_many_failed_pin_attempts_dialog_message; } else { messageId = R.string.lockscreen_too_many_failed_password_attempts_dialog_message; } } String message = mContext.getString( messageId, mUpdateMonitor.getFailedAttempts(), timeoutInSeconds); private void showDialog(String title, String message) { final AlertDialog dialog = new AlertDialog.Builder(mContext) .setTitle(null) .setTitle(title) .setMessage(message) .setNeutralButton(R.string.ok, null) .create(); Loading @@ -757,27 +769,42 @@ public class LockPatternKeyguardView extends KeyguardViewBase { dialog.show(); } private void showTimeoutDialog() { int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000; int messageId = R.string.lockscreen_too_many_failed_attempts_dialog_message; if (getUnlockMode() == UnlockMode.Password) { if(mLockPatternUtils.getKeyguardStoredPasswordQuality() == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) { messageId = R.string.lockscreen_too_many_failed_pin_attempts_dialog_message; } else { messageId = R.string.lockscreen_too_many_failed_password_attempts_dialog_message; } } String message = mContext.getString(messageId, mUpdateMonitor.getFailedAttempts(), timeoutInSeconds); showDialog(null, message); } private void showAlmostAtAccountLoginDialog() { final int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000; final int count = LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT; String message = mContext.getString(R.string.lockscreen_failed_attempts_almost_glogin, count, LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT, timeoutInSeconds); showDialog(null, message); } private void showAlmostAtWipeDialog(int attempts, int remaining) { int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000; String message = mContext.getString( R.string.lockscreen_failed_attempts_almost_glogin, LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT, LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT, timeoutInSeconds); final AlertDialog dialog = new AlertDialog.Builder(mContext) .setTitle(null) .setMessage(message) .setNeutralButton(R.string.ok, null) .create(); dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); if (!mContext.getResources().getBoolean( com.android.internal.R.bool.config_sf_slowBlur)) { dialog.getWindow().setFlags( WindowManager.LayoutParams.FLAG_BLUR_BEHIND, WindowManager.LayoutParams.FLAG_BLUR_BEHIND); R.string.lockscreen_failed_attempts_almost_at_wipe, attempts, remaining); showDialog(null, message); } dialog.show(); private void showWipeDialog(int attempts) { String message = mContext.getString( R.string.lockscreen_failed_attempts_now_wiping, attempts); showDialog(null, message); } /** Loading policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java +0 −1 Original line number Diff line number Diff line Loading @@ -41,7 +41,6 @@ import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.TextView; Loading Loading
core/java/com/android/internal/widget/LockPatternUtils.java +9 −1 Original line number Diff line number Diff line Loading @@ -83,6 +83,13 @@ public class LockPatternUtils { */ public static final long FAILED_ATTEMPT_COUNTDOWN_INTERVAL_MS = 1000L; /** * This dictates when we start telling the user that continued failed attempts will wipe * their device. */ public static final int FAILED_ATTEMPTS_BEFORE_WIPE_GRACE = 5; /** * The minimum number of dots in a valid pattern. */ Loading @@ -93,7 +100,7 @@ public class LockPatternUtils { * attempt for it to be counted against the counts that affect * {@link #FAILED_ATTEMPTS_BEFORE_TIMEOUT} and {@link #FAILED_ATTEMPTS_BEFORE_RESET} */ public static final int MIN_PATTERN_REGISTER_FAIL = 3; public static final int MIN_PATTERN_REGISTER_FAIL = MIN_LOCK_PATTERN_SIZE; private final static String LOCKOUT_PERMANENT_KEY = "lockscreen.lockedoutpermanently"; private final static String LOCKOUT_ATTEMPT_DEADLINE = "lockscreen.lockoutattemptdeadline"; Loading @@ -112,6 +119,7 @@ public class LockPatternUtils { private static final AtomicBoolean sHaveNonZeroPatternFile = new AtomicBoolean(false); private static final AtomicBoolean sHaveNonZeroPasswordFile = new AtomicBoolean(false); private static FileObserver sPasswordObserver; private static class PasswordFileObserver extends FileObserver { Loading
core/res/res/values/strings.xml +35 −4 Original line number Diff line number Diff line Loading @@ -1857,7 +1857,7 @@ \n\nPlease try again in <xliff:g id="number">%d</xliff:g> seconds. </string> <!-- For the unlock screen, Information message shown in dialog when user is almost at the limit <!-- For the unlock screen, informational message shown in dialog when user is almost at the limit where they will be locked out and may have to enter an alternate username/password to unlock the phone --> <string name="lockscreen_failed_attempts_almost_glogin" product="tablet"> You have incorrectly drawn your unlock pattern <xliff:g id="number">%d</xliff:g> times. Loading @@ -1865,7 +1865,8 @@ you will be asked to unlock your tablet using your Google sign-in.\n\n Please try again in <xliff:g id="number">%d</xliff:g> seconds. </string> <!-- For the unlock screen, Information message shown in dialog when user is almost at the limit <!-- For the unlock screen, informational message shown in dialog when user is almost at the limit where they will be locked out and may have to enter an alternate username/password to unlock the phone --> <string name="lockscreen_failed_attempts_almost_glogin" product="default"> You have incorrectly drawn your unlock pattern <xliff:g id="number">%d</xliff:g> times. Loading @@ -1874,6 +1875,36 @@ Please try again in <xliff:g id="number">%d</xliff:g> seconds. </string> <!-- For the unlock screen, informational message shown in dialog when user is almost at the limit where the device will be wiped. --> <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet"> You have incorrectly attempted to unlock the tablet <xliff:g id="number">%d</xliff:g> times. After <xliff:g id="number">%d</xliff:g> more unsuccessful attempts, the tablet will be reset to factory default and all user data will be lost. </string> <!-- For the unlock screen, informational message shown in dialog when user is almost at the limit where the device will be wiped. --> <string name="lockscreen_failed_attempts_almost_at_wipe" product="default"> You have incorrectly attempted to unlock the phone <xliff:g id="number">%d</xliff:g> times. After <xliff:g id="number">%d</xliff:g> more unsuccessful attempts, the phone will be reset to factory default and all user data will be lost. </string> <!-- For the unlock screen, informational message shown in dialog when user has exceeded the maximum attempts and the device will now be wiped --> <string name="lockscreen_failed_attempts_now_wiping" product="tablet"> You have incorrectly attempted to unlock the tablet <xliff:g id="number">%d</xliff:g> times. The tablet will now be reset to factory default. </string> <!-- For the unlock screen, informational message shown in dialog when user has exceeded the maximum attempts and the device will now be wiped --> <string name="lockscreen_failed_attempts_now_wiping" product="default"> You have incorrectly attempted to unlock the phone <xliff:g id="number">%d</xliff:g> times. The phone will now be reset to factory default. </string> <!-- On the unlock screen, countdown message shown while user is waiting to try again after too many failed attempts --> <string name="lockscreen_too_many_failed_attempts_countdown">Try again in <xliff:g id="number">%d</xliff:g> seconds.</string> Loading
policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java +76 −49 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import android.os.SystemProperties; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Log; import android.util.Slog; import android.view.KeyEvent; import android.view.View; import android.view.WindowManager; Loading Loading @@ -294,23 +295,48 @@ public class LockPatternKeyguardView extends KeyguardViewBase { public void reportFailedUnlockAttempt() { mUpdateMonitor.reportFailedAttempt(); final int failedAttempts = mUpdateMonitor.getFailedAttempts(); if (DEBUG) Log.d(TAG, "reportFailedPatternAttempt: #" + failedAttempts + if (DEBUG) Log.d(TAG, "reportFailedPatternAttempt: #" + failedAttempts + " (enableFallback=" + mEnableFallback + ")"); final boolean usingLockPattern = mLockPatternUtils.getKeyguardStoredPasswordQuality() final boolean usingPattern = mLockPatternUtils.getKeyguardStoredPasswordQuality() == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; if (usingLockPattern && mEnableFallback && failedAttempts == (LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) { final int failedAttemptsBeforeWipe = mLockPatternUtils.getDevicePolicyManager() .getMaximumFailedPasswordsForWipe(null); final int failedAttemptWarning = LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT; final int remainingBeforeWipe = failedAttemptsBeforeWipe > 0 ? (failedAttemptsBeforeWipe - failedAttempts) : Integer.MAX_VALUE; // because DPM returns 0 if no restriction if (remainingBeforeWipe < LockPatternUtils.FAILED_ATTEMPTS_BEFORE_WIPE_GRACE) { // If we reach this code, it means the user has installed a DevicePolicyManager // that requests device wipe after N attempts. Once we get below the grace // period, we'll post this dialog every time as a clear warning until the // bombshell hits and the device is wiped. if (remainingBeforeWipe > 0) { showAlmostAtWipeDialog(failedAttempts, remainingBeforeWipe); } else { // Too many attempts. The device will be wiped shortly. Slog.i(TAG, "Too many unlock attempts; device will be wiped!"); showWipeDialog(failedAttempts); } } else if (usingPattern && mEnableFallback) { if (failedAttempts == failedAttemptWarning) { showAlmostAtAccountLoginDialog(); } else if (usingLockPattern && mEnableFallback && failedAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET) { } else if (failedAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET) { mLockPatternUtils.setPermanentlyLocked(true); updateScreen(mMode); } else if ((failedAttempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) == 0) { } } else { final boolean showTimeout = (failedAttempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) == 0; if (showTimeout) { showTimeoutDialog(); } } mLockPatternUtils.reportFailedPasswordAttempt(); } Loading Loading @@ -727,23 +753,9 @@ public class LockPatternKeyguardView extends KeyguardViewBase { return currentMode; } private void showTimeoutDialog() { int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000; int messageId = R.string.lockscreen_too_many_failed_attempts_dialog_message; if(getUnlockMode() == UnlockMode.Password) { if(mLockPatternUtils.getKeyguardStoredPasswordQuality() == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) { messageId = R.string.lockscreen_too_many_failed_pin_attempts_dialog_message; } else { messageId = R.string.lockscreen_too_many_failed_password_attempts_dialog_message; } } String message = mContext.getString( messageId, mUpdateMonitor.getFailedAttempts(), timeoutInSeconds); private void showDialog(String title, String message) { final AlertDialog dialog = new AlertDialog.Builder(mContext) .setTitle(null) .setTitle(title) .setMessage(message) .setNeutralButton(R.string.ok, null) .create(); Loading @@ -757,27 +769,42 @@ public class LockPatternKeyguardView extends KeyguardViewBase { dialog.show(); } private void showTimeoutDialog() { int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000; int messageId = R.string.lockscreen_too_many_failed_attempts_dialog_message; if (getUnlockMode() == UnlockMode.Password) { if(mLockPatternUtils.getKeyguardStoredPasswordQuality() == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) { messageId = R.string.lockscreen_too_many_failed_pin_attempts_dialog_message; } else { messageId = R.string.lockscreen_too_many_failed_password_attempts_dialog_message; } } String message = mContext.getString(messageId, mUpdateMonitor.getFailedAttempts(), timeoutInSeconds); showDialog(null, message); } private void showAlmostAtAccountLoginDialog() { final int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000; final int count = LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT; String message = mContext.getString(R.string.lockscreen_failed_attempts_almost_glogin, count, LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT, timeoutInSeconds); showDialog(null, message); } private void showAlmostAtWipeDialog(int attempts, int remaining) { int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000; String message = mContext.getString( R.string.lockscreen_failed_attempts_almost_glogin, LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT, LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT, timeoutInSeconds); final AlertDialog dialog = new AlertDialog.Builder(mContext) .setTitle(null) .setMessage(message) .setNeutralButton(R.string.ok, null) .create(); dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); if (!mContext.getResources().getBoolean( com.android.internal.R.bool.config_sf_slowBlur)) { dialog.getWindow().setFlags( WindowManager.LayoutParams.FLAG_BLUR_BEHIND, WindowManager.LayoutParams.FLAG_BLUR_BEHIND); R.string.lockscreen_failed_attempts_almost_at_wipe, attempts, remaining); showDialog(null, message); } dialog.show(); private void showWipeDialog(int attempts) { String message = mContext.getString( R.string.lockscreen_failed_attempts_now_wiping, attempts); showDialog(null, message); } /** Loading
policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java +0 −1 Original line number Diff line number Diff line Loading @@ -41,7 +41,6 @@ import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.TextView; Loading