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;
|
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.
|
* 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
|
* attempt for it to be counted against the counts that affect
|
||||||
* {@link #FAILED_ATTEMPTS_BEFORE_TIMEOUT} and {@link #FAILED_ATTEMPTS_BEFORE_RESET}
|
* {@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_PERMANENT_KEY = "lockscreen.lockedoutpermanently";
|
||||||
private final static String LOCKOUT_ATTEMPT_DEADLINE = "lockscreen.lockoutattemptdeadline";
|
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 sHaveNonZeroPatternFile = new AtomicBoolean(false);
|
||||||
private static final AtomicBoolean sHaveNonZeroPasswordFile = new AtomicBoolean(false);
|
private static final AtomicBoolean sHaveNonZeroPasswordFile = new AtomicBoolean(false);
|
||||||
|
|
||||||
private static FileObserver sPasswordObserver;
|
private static FileObserver sPasswordObserver;
|
||||||
|
|
||||||
private static class PasswordFileObserver extends FileObserver {
|
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. -->
|
<!-- 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>
|
<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. -->
|
<!-- 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,
|
<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
|
for example to change the proxy and port of any APN. Malicious applications could monitor, redirect, or modify network
|
||||||
packets without your knowledge.</string>
|
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. -->
|
<!-- 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.
|
\n\nPlease try again in <xliff:g id="number">%d</xliff:g> seconds.
|
||||||
</string>
|
</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 -->
|
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">
|
<string name="lockscreen_failed_attempts_almost_glogin" product="tablet">
|
||||||
You have incorrectly drawn your unlock pattern <xliff:g id="number">%d</xliff:g> times.
|
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
|
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.
|
Please try again in <xliff:g id="number">%d</xliff:g> seconds.
|
||||||
</string>
|
</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 -->
|
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">
|
<string name="lockscreen_failed_attempts_almost_glogin" product="default">
|
||||||
You have incorrectly drawn your unlock pattern <xliff:g id="number">%d</xliff:g> times.
|
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.
|
Please try again in <xliff:g id="number">%d</xliff:g> seconds.
|
||||||
</string>
|
</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
|
<!-- On the unlock screen, countdown message shown while user is waiting to try again after too many
|
||||||
failed attempts -->
|
failed attempts -->
|
||||||
<string name="lockscreen_too_many_failed_attempts_countdown">Try again in <xliff:g id="number">%d</xliff:g> seconds.</string>
|
<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.telephony.TelephonyManager;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.util.Slog;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
@@ -294,22 +295,47 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
|
|||||||
public void reportFailedUnlockAttempt() {
|
public void reportFailedUnlockAttempt() {
|
||||||
mUpdateMonitor.reportFailedAttempt();
|
mUpdateMonitor.reportFailedAttempt();
|
||||||
final int failedAttempts = mUpdateMonitor.getFailedAttempts();
|
final int failedAttempts = mUpdateMonitor.getFailedAttempts();
|
||||||
if (DEBUG) Log.d(TAG,
|
if (DEBUG) Log.d(TAG, "reportFailedPatternAttempt: #" + failedAttempts +
|
||||||
"reportFailedPatternAttempt: #" + failedAttempts +
|
|
||||||
" (enableFallback=" + mEnableFallback + ")");
|
" (enableFallback=" + mEnableFallback + ")");
|
||||||
final boolean usingLockPattern = mLockPatternUtils.getKeyguardStoredPasswordQuality()
|
|
||||||
|
final boolean usingPattern = mLockPatternUtils.getKeyguardStoredPasswordQuality()
|
||||||
== DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
|
== DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
|
||||||
if (usingLockPattern && mEnableFallback && failedAttempts ==
|
|
||||||
(LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET
|
final int failedAttemptsBeforeWipe = mLockPatternUtils.getDevicePolicyManager()
|
||||||
- LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
|
.getMaximumFailedPasswordsForWipe(null);
|
||||||
showAlmostAtAccountLoginDialog();
|
|
||||||
} else if (usingLockPattern && mEnableFallback
|
final int failedAttemptWarning = LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET
|
||||||
&& failedAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET) {
|
- LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT;
|
||||||
mLockPatternUtils.setPermanentlyLocked(true);
|
|
||||||
updateScreen(mMode);
|
final int remainingBeforeWipe = failedAttemptsBeforeWipe > 0 ?
|
||||||
} else if ((failedAttempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)
|
(failedAttemptsBeforeWipe - failedAttempts)
|
||||||
== 0) {
|
: Integer.MAX_VALUE; // because DPM returns 0 if no restriction
|
||||||
showTimeoutDialog();
|
|
||||||
|
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();
|
mLockPatternUtils.reportFailedPasswordAttempt();
|
||||||
}
|
}
|
||||||
@@ -727,26 +753,12 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
|
|||||||
return currentMode;
|
return currentMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showTimeoutDialog() {
|
private void showDialog(String title, String message) {
|
||||||
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);
|
|
||||||
final AlertDialog dialog = new AlertDialog.Builder(mContext)
|
final AlertDialog dialog = new AlertDialog.Builder(mContext)
|
||||||
.setTitle(null)
|
.setTitle(title)
|
||||||
.setMessage(message)
|
.setMessage(message)
|
||||||
.setNeutralButton(R.string.ok, null)
|
.setNeutralButton(R.string.ok, null)
|
||||||
.create();
|
.create();
|
||||||
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
|
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
|
||||||
if (!mContext.getResources().getBoolean(
|
if (!mContext.getResources().getBoolean(
|
||||||
com.android.internal.R.bool.config_sf_slowBlur)) {
|
com.android.internal.R.bool.config_sf_slowBlur)) {
|
||||||
@@ -757,27 +769,42 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
|
|||||||
dialog.show();
|
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() {
|
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;
|
int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000;
|
||||||
String message = mContext.getString(
|
String message = mContext.getString(
|
||||||
R.string.lockscreen_failed_attempts_almost_glogin,
|
R.string.lockscreen_failed_attempts_almost_at_wipe, attempts, remaining);
|
||||||
LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET
|
showDialog(null, message);
|
||||||
- LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT,
|
}
|
||||||
LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT,
|
|
||||||
timeoutInSeconds);
|
private void showWipeDialog(int attempts) {
|
||||||
final AlertDialog dialog = new AlertDialog.Builder(mContext)
|
String message = mContext.getString(
|
||||||
.setTitle(null)
|
R.string.lockscreen_failed_attempts_now_wiping, attempts);
|
||||||
.setMessage(message)
|
showDialog(null, 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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ import android.view.inputmethod.EditorInfo;
|
|||||||
import android.view.inputmethod.InputMethodInfo;
|
import android.view.inputmethod.InputMethodInfo;
|
||||||
import android.view.inputmethod.InputMethodManager;
|
import android.view.inputmethod.InputMethodManager;
|
||||||
import android.view.inputmethod.InputMethodSubtype;
|
import android.view.inputmethod.InputMethodSubtype;
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|||||||
Reference in New Issue
Block a user