Merge "Fix 5026428: Rework unlock attempt logic with active DPM to show better messages"
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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,26 +753,12 @@ 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)
|
||||
.setMessage(message)
|
||||
.setNeutralButton(R.string.ok, null)
|
||||
.create();
|
||||
.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)) {
|
||||
@@ -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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user