diff options
4 files changed, 120 insertions, 55 deletions
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index e4322c6..804f28a 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -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. */ @@ -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"; @@ -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 { diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 2548eb5..27fa8d4 100755 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -1300,8 +1300,8 @@ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_writeApnSettings">change/intercept network settings and traffic</string> <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> - <string name="permdesc_writeApnSettings">Allows an application to change network settings and to intercept and inspect all network traffic, - for example to change the proxy and port of any APN. Malicious applications could monitor, redirect, or modify network + <string name="permdesc_writeApnSettings">Allows an application to change network settings and to intercept and inspect all network traffic, + for example to change the proxy and port of any APN. Malicious applications could monitor, redirect, or modify network packets without your knowledge.</string> <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> @@ -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. @@ -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. @@ -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> diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java index b60bae7..adcc9c0 100644 --- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java +++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java @@ -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; @@ -294,22 +295,47 @@ 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)) { - showAlmostAtAccountLoginDialog(); - } else if (usingLockPattern && mEnableFallback - && failedAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET) { - mLockPatternUtils.setPermanentlyLocked(true); - updateScreen(mMode); - } else if ((failedAttempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) - == 0) { - showTimeoutDialog(); + + 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 (failedAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET) { + mLockPatternUtils.setPermanentlyLocked(true); + updateScreen(mMode); + } + } else { + final boolean showTimeout = + (failedAttempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) == 0; + if (showTimeout) { + showTimeoutDialog(); + } } mLockPatternUtils.reportFailedPasswordAttempt(); } @@ -727,10 +753,26 @@ public class LockPatternKeyguardView extends KeyguardViewBase { return currentMode; } + private void showDialog(String title, String message) { + final AlertDialog dialog = new AlertDialog.Builder(mContext) + .setTitle(title) + .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); + } + 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 (getUnlockMode() == UnlockMode.Password) { if(mLockPatternUtils.getKeyguardStoredPasswordQuality() == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) { messageId = R.string.lockscreen_too_many_failed_pin_attempts_dialog_message; @@ -738,46 +780,31 @@ public class LockPatternKeyguardView extends KeyguardViewBase { messageId = R.string.lockscreen_too_many_failed_password_attempts_dialog_message; } } - String message = mContext.getString( - messageId, - mUpdateMonitor.getFailedAttempts(), + String message = mContext.getString(messageId, mUpdateMonitor.getFailedAttempts(), 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); - } - dialog.show(); + 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); - } - dialog.show(); + R.string.lockscreen_failed_attempts_almost_at_wipe, attempts, remaining); + showDialog(null, message); + } + + private void showWipeDialog(int attempts) { + String message = mContext.getString( + R.string.lockscreen_failed_attempts_now_wiping, attempts); + showDialog(null, message); } /** diff --git a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java index d70b3bb..ee0a6e9 100644 --- a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java +++ b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java @@ -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; |