Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5e82bc03 authored by Jim Miller's avatar Jim Miller Committed by Android (Google) Code Review
Browse files

Merge "Fix 5026428: Rework unlock attempt logic with active DPM to show better messages"

parents 666eb122 4f369957
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -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 {
+35 −4
Original line number Diff line number Diff line
@@ -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>
+76 −49
Original line number Diff line number Diff line
@@ -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,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();
            }

@@ -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();
@@ -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);
    }

    /**
+0 −1
Original line number Diff line number Diff line
@@ -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;