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

Commit ee9ca3cd authored by Xiyuan Xia's avatar Xiyuan Xia Committed by Android (Google) Code Review
Browse files

Merge "Fix a race condition during async credential check"

parents 4d0f5ee2 ce64cea3
Loading
Loading
Loading
Loading
+15 −9
Original line number Diff line number Diff line
@@ -123,39 +123,45 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout
            mPendingLockCheck.cancel(false);
        }

        final int userId = KeyguardUpdateMonitor.getCurrentUser();
        if (entry.length() <= MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT) {
            // to avoid accidental lockout, only count attempts that are long enough to be a
            // real password. This may require some tweaking.
            setPasswordEntryInputEnabled(true);
            onPasswordChecked(false /* matched */, 0, false /* not valid - too short */);
            onPasswordChecked(userId, false /* matched */, 0, false /* not valid - too short */);
            return;
        }

        mPendingLockCheck = LockPatternChecker.checkPassword(
                mLockPatternUtils,
                entry,
                KeyguardUpdateMonitor.getCurrentUser(),
                userId,
                new LockPatternChecker.OnCheckCallback() {
                    @Override
                    public void onChecked(boolean matched, int timeoutMs) {
                        setPasswordEntryInputEnabled(true);
                        mPendingLockCheck = null;
                        onPasswordChecked(matched, timeoutMs, true /* isValidPassword */);
                        onPasswordChecked(userId, matched, timeoutMs,
                                true /* isValidPassword */);
                    }
                });
    }

    private void onPasswordChecked(boolean matched, int timeoutMs, boolean isValidPassword) {
    private void onPasswordChecked(int userId, boolean matched, int timeoutMs,
            boolean isValidPassword) {
        boolean dismissKeyguard = KeyguardUpdateMonitor.getCurrentUser() == userId;
        if (matched) {
            mCallback.reportUnlockAttempt(userId, true, 0);
            if (dismissKeyguard) {
                mDismissing = true;
            mCallback.reportUnlockAttempt(true, 0);
                mCallback.dismiss(true);
            }
        } else {
            if (isValidPassword) {
                mCallback.reportUnlockAttempt(false, timeoutMs);
                mCallback.reportUnlockAttempt(userId, false, timeoutMs);
                if (timeoutMs > 0) {
                    long deadline = mLockPatternUtils.setLockoutAttemptDeadline(
                            KeyguardUpdateMonitor.getCurrentUser(), timeoutMs);
                            userId, timeoutMs);
                    handleAttemptLockout(deadline);
                }
            }
+14 −9
Original line number Diff line number Diff line
@@ -227,22 +227,23 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit
                mPendingLockCheck.cancel(false);
            }

            final int userId = KeyguardUpdateMonitor.getCurrentUser();
            if (pattern.size() < LockPatternUtils.MIN_PATTERN_REGISTER_FAIL) {
                mLockPatternView.enableInput();
                onPatternChecked(false, 0, false /* not valid - too short */);
                onPatternChecked(userId, false, 0, false /* not valid - too short */);
                return;
            }

            mPendingLockCheck = LockPatternChecker.checkPattern(
                    mLockPatternUtils,
                    pattern,
                    KeyguardUpdateMonitor.getCurrentUser(),
                    userId,
                    new LockPatternChecker.OnCheckCallback() {
                        @Override
                        public void onChecked(boolean matched, int timeoutMs) {
                            mLockPatternView.enableInput();
                            mPendingLockCheck = null;
                            onPatternChecked(matched, timeoutMs, true);
                            onPatternChecked(userId, matched, timeoutMs, true);
                        }
                    });
            if (pattern.size() > MIN_PATTERN_BEFORE_POKE_WAKELOCK) {
@@ -250,18 +251,22 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit
            }
        }

        private void onPatternChecked(boolean matched, int timeoutMs, boolean isValidPattern) {
        private void onPatternChecked(int userId, boolean matched, int timeoutMs,
                boolean isValidPattern) {
            boolean dismissKeyguard = KeyguardUpdateMonitor.getCurrentUser() == userId;
            if (matched) {
                mCallback.reportUnlockAttempt(true, 0);
                mCallback.reportUnlockAttempt(userId, true, 0);
                if (dismissKeyguard) {
                    mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Correct);
                    mCallback.dismiss(true);
                }
            } else {
                mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Wrong);
                if (isValidPattern) {
                    mCallback.reportUnlockAttempt(false, timeoutMs);
                    mCallback.reportUnlockAttempt(userId, false, timeoutMs);
                    if (timeoutMs > 0) {
                        long deadline = mLockPatternUtils.setLockoutAttemptDeadline(
                                KeyguardUpdateMonitor.getCurrentUser(), timeoutMs);
                                userId, timeoutMs);
                        handleAttemptLockout(deadline);
                    }
                }
+2 −1
Original line number Diff line number Diff line
@@ -36,11 +36,12 @@ public interface KeyguardSecurityCallback {

    /**
     * Call to report an unlock attempt.
     * @param userId id of the user whose unlock attempt is recorded.
     * @param success set to 'true' if user correctly entered security credentials.
     * @param timeoutMs timeout in milliseconds to wait before reattempting an unlock.
     *                  Only nonzero if 'success' is false
     */
    void reportUnlockAttempt(boolean success, int timeoutMs);
    void reportUnlockAttempt(int userId, boolean success, int timeoutMs);

    /**
     * Resets the keyguard view.
+13 −14
Original line number Diff line number Diff line
@@ -205,7 +205,8 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe

        if (messageId != 0) {
            final String message = mContext.getString(messageId,
                    KeyguardUpdateMonitor.getInstance(mContext).getFailedUnlockAttempts(),
                    KeyguardUpdateMonitor.getInstance(mContext).getFailedUnlockAttempts(
                            KeyguardUpdateMonitor.getCurrentUser()),
                    timeoutInSeconds);
            showDialog(null, message);
        }
@@ -249,16 +250,15 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe
        showDialog(null, message);
    }

    private void reportFailedUnlockAttempt(int timeoutMs) {
    private void reportFailedUnlockAttempt(int userId, int timeoutMs) {
        final KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
        final int failedAttempts = monitor.getFailedUnlockAttempts() + 1; // +1 for this time
        final int failedAttempts = monitor.getFailedUnlockAttempts(userId) + 1; // +1 for this time

        if (DEBUG) Log.d(TAG, "reportFailedPatternAttempt: #" + failedAttempts);

        final int currentUser = KeyguardUpdateMonitor.getCurrentUser();
        final DevicePolicyManager dpm = mLockPatternUtils.getDevicePolicyManager();
        final int failedAttemptsBeforeWipe =
                dpm.getMaximumFailedPasswordsForWipe(null, currentUser);
                dpm.getMaximumFailedPasswordsForWipe(null, userId);

        final int remainingBeforeWipe = failedAttemptsBeforeWipe > 0 ?
                (failedAttemptsBeforeWipe - failedAttempts)
@@ -268,9 +268,9 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe
            // N attempts. Once we get below the grace period, we post this dialog every time as a
            // clear warning until the deletion fires.
            // Check which profile has the strictest policy for failed password attempts
            final int expiringUser = dpm.getProfileWithMinimumFailedPasswordsForWipe(currentUser);
            final int expiringUser = dpm.getProfileWithMinimumFailedPasswordsForWipe(userId);
            int userType = USER_TYPE_PRIMARY;
            if (expiringUser == currentUser) {
            if (expiringUser == userId) {
                // TODO: http://b/23522538
                if (expiringUser != UserHandle.USER_SYSTEM) {
                    userType = USER_TYPE_SECONDARY_USER;
@@ -286,8 +286,8 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe
                showWipeDialog(failedAttempts, userType);
            }
        }
        monitor.reportFailedStrongAuthUnlockAttempt();
        mLockPatternUtils.reportFailedPasswordAttempt(KeyguardUpdateMonitor.getCurrentUser());
        monitor.reportFailedStrongAuthUnlockAttempt(userId);
        mLockPatternUtils.reportFailedPasswordAttempt(userId);
        if (timeoutMs > 0) {
            showTimeoutDialog(timeoutMs);
        }
@@ -422,14 +422,13 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe
            return mIsVerifyUnlockOnly;
        }

        public void reportUnlockAttempt(boolean success, int timeoutMs) {
        public void reportUnlockAttempt(int userId, boolean success, int timeoutMs) {
            KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
            if (success) {
                monitor.clearFailedUnlockAttempts();
                mLockPatternUtils.reportSuccessfulPasswordAttempt(
                        KeyguardUpdateMonitor.getCurrentUser());
                mLockPatternUtils.reportSuccessfulPasswordAttempt(userId);
            } else {
                KeyguardSecurityContainer.this.reportFailedUnlockAttempt(timeoutMs);
                KeyguardSecurityContainer.this.reportFailedUnlockAttempt(userId, timeoutMs);
            }
        }

@@ -445,7 +444,7 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe
        @Override
        public void userActivity() { }
        @Override
        public void reportUnlockAttempt(boolean success, int timeoutMs) { }
        public void reportUnlockAttempt(int userId, boolean success, int timeoutMs) { }
        @Override
        public boolean isVerifyUnlockOnly() { return false; }
        @Override
+4 −4
Original line number Diff line number Diff line
@@ -1552,12 +1552,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
        mFailedAttempts.delete(sCurrentUser);
    }

    public int getFailedUnlockAttempts() {
        return mFailedAttempts.get(sCurrentUser, 0);
    public int getFailedUnlockAttempts(int userId) {
        return mFailedAttempts.get(userId, 0);
    }

    public void reportFailedStrongAuthUnlockAttempt() {
        mFailedAttempts.put(sCurrentUser, getFailedUnlockAttempts() + 1);
    public void reportFailedStrongAuthUnlockAttempt(int userId) {
        mFailedAttempts.put(userId, getFailedUnlockAttempts(userId) + 1);
    }

    public void clearFingerprintRecognized() {