Merge "Make PIN/Password/Pattern check async" into mnc-dev
diff --git a/core/java/com/android/internal/widget/LockPatternChecker.java b/core/java/com/android/internal/widget/LockPatternChecker.java
new file mode 100644
index 0000000..ac0f5fe
--- /dev/null
+++ b/core/java/com/android/internal/widget/LockPatternChecker.java
@@ -0,0 +1,146 @@
+package com.android.internal.widget;
+
+import android.os.AsyncTask;
+
+import java.util.List;
+
+/**
+ * Helper class to check/verify PIN/Password/Pattern asynchronously.
+ */
+public final class LockPatternChecker {
+    /**
+     * Interface for a callback to be invoked after security check.
+     */
+    public interface OnCheckCallback {
+        /**
+         * Invoked when a security check is finished.
+         *
+         * @param matched Whether the PIN/Password/Pattern matches the stored one.
+         */
+        void onChecked(boolean matched);
+    }
+
+    /**
+     * Interface for a callback to be invoked after security verification.
+     */
+    public interface OnVerifyCallback {
+        /**
+         * Invoked when a security verification is finished.
+         *
+         * @param attestation The attestation that the challenge was verified, or null.
+         */
+        void onVerified(byte[] attestation);
+    }
+
+    /**
+     * Verify a pattern asynchronously.
+     *
+     * @param utils The LockPatternUtils instance to use.
+     * @param pattern The pattern to check.
+     * @param challenge The challenge to verify against the pattern.
+     * @param userId The user to check against the pattern.
+     * @param callback The callback to be invoked with the verification result.
+     */
+    public static AsyncTask<?, ?, ?> verifyPattern(final LockPatternUtils utils,
+            final List<LockPatternView.Cell> pattern,
+            final long challenge,
+            final int userId,
+            final OnVerifyCallback callback) {
+        AsyncTask<Void, Void, byte[]> task = new AsyncTask<Void, Void, byte[]>() {
+            @Override
+            protected byte[] doInBackground(Void... args) {
+                return utils.verifyPattern(pattern, challenge, userId);
+            }
+
+            @Override
+            protected void onPostExecute(byte[] result) {
+                callback.onVerified(result);
+            }
+        };
+        task.execute();
+        return task;
+    }
+
+    /**
+     * Checks a pattern asynchronously.
+     *
+     * @param utils The LockPatternUtils instance to use.
+     * @param pattern The pattern to check.
+     * @param userId The user to check against the pattern.
+     * @param callback The callback to be invoked with the check result.
+     */
+    public static AsyncTask<?, ?, ?> checkPattern(final LockPatternUtils utils,
+            final List<LockPatternView.Cell> pattern,
+            final int userId,
+            final OnCheckCallback callback) {
+        AsyncTask<Void, Void, Boolean> task = new AsyncTask<Void, Void, Boolean>() {
+            @Override
+            protected Boolean doInBackground(Void... args) {
+                return utils.checkPattern(pattern, userId);
+            }
+
+            @Override
+            protected void onPostExecute(Boolean result) {
+                callback.onChecked(result);
+            }
+        };
+        task.execute();
+        return task;
+    }
+
+    /**
+     * Verify a password asynchronously.
+     *
+     * @param utils The LockPatternUtils instance to use.
+     * @param password The password to check.
+     * @param challenge The challenge to verify against the pattern.
+     * @param userId The user to check against the pattern.
+     * @param callback The callback to be invoked with the verification result.
+     */
+    public static AsyncTask<?, ?, ?> verifyPassword(final LockPatternUtils utils,
+            final String password,
+            final long challenge,
+            final int userId,
+            final OnVerifyCallback callback) {
+        AsyncTask<Void, Void, byte[]> task = new AsyncTask<Void, Void, byte[]>() {
+            @Override
+            protected byte[] doInBackground(Void... args) {
+                return utils.verifyPassword(password, challenge, userId);
+            }
+
+            @Override
+            protected void onPostExecute(byte[] result) {
+                callback.onVerified(result);
+            }
+        };
+        task.execute();
+        return task;
+    }
+
+    /**
+     * Checks a password asynchronously.
+     *
+     * @param utils The LockPatternUtils instance to use.
+     * @param password The password to check.
+     * @param userId The user to check against the pattern.
+     * @param callback The callback to be invoked with the check result.
+     */
+    public static AsyncTask<?, ?, ?> checkPassword(final LockPatternUtils utils,
+            final String password,
+            final int userId,
+            final OnCheckCallback callback) {
+        AsyncTask<Void, Void, Boolean> task = new AsyncTask<Void, Void, Boolean>() {
+            @Override
+            protected Boolean doInBackground(Void... args) {
+                return utils.checkPassword(password, userId);
+            }
+
+            @Override
+            protected void onPostExecute(Boolean result) {
+                callback.onChecked(result);
+            }
+        };
+        task.execute();
+        return task;
+    }
+}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index c4f4b9a..db56161 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -17,6 +17,7 @@
 package com.android.keyguard;
 
 import android.content.Context;
+import android.os.AsyncTask;
 import android.os.CountDownTimer;
 import android.os.SystemClock;
 import android.util.AttributeSet;
@@ -25,6 +26,7 @@
 import android.view.View;
 import android.widget.LinearLayout;
 
+import com.android.internal.widget.LockPatternChecker;
 import com.android.internal.widget.LockPatternUtils;
 
 /**
@@ -34,6 +36,7 @@
         implements KeyguardSecurityView, EmergencyButton.EmergencyButtonCallback {
     protected KeyguardSecurityCallback mCallback;
     protected LockPatternUtils mLockPatternUtils;
+    protected AsyncTask<?, ?, ?> mPendingLockCheck;
     protected SecurityMessageDisplay mSecurityMessageDisplay;
     protected View mEcaView;
     protected boolean mEnableHaptics;
@@ -106,8 +109,27 @@
     }
 
     protected void verifyPasswordAndUnlock() {
-        String entry = getPasswordText();
-        if (mLockPatternUtils.checkPassword(entry, KeyguardUpdateMonitor.getCurrentUser())) {
+        final String entry = getPasswordText();
+        setPasswordEntryEnabled(false);
+        if (mPendingLockCheck != null) {
+            mPendingLockCheck.cancel(false);
+        }
+        mPendingLockCheck = LockPatternChecker.checkPassword(
+                mLockPatternUtils,
+                entry,
+                KeyguardUpdateMonitor.getCurrentUser(),
+                new LockPatternChecker.OnCheckCallback() {
+                    @Override
+                    public void onChecked(boolean matched) {
+                        setPasswordEntryEnabled(true);
+                        mPendingLockCheck = null;
+                        onPasswordChecked(entry, matched);
+                    }
+                });
+    }
+
+    private void onPasswordChecked(String entry, boolean matched) {
+        if (matched) {
             mCallback.reportUnlockAttempt(true);
             mCallback.dismiss(true);
         } else {
@@ -165,7 +187,10 @@
 
     @Override
     public void onPause() {
-
+        if (mPendingLockCheck != null) {
+            mPendingLockCheck.cancel(false);
+            mPendingLockCheck = null;
+        }
     }
 
     @Override
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
index 557cd13..f67b2e7 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
@@ -20,6 +20,7 @@
 import android.animation.ValueAnimator;
 import android.content.Context;
 import android.graphics.Rect;
+import android.os.AsyncTask;
 import android.os.CountDownTimer;
 import android.os.SystemClock;
 import android.text.TextUtils;
@@ -32,6 +33,7 @@
 import android.view.animation.Interpolator;
 import android.widget.LinearLayout;
 
+import com.android.internal.widget.LockPatternChecker;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.widget.LockPatternView;
 
@@ -59,6 +61,7 @@
 
     private CountDownTimer mCountdownTimer = null;
     private LockPatternUtils mLockPatternUtils;
+    private AsyncTask<?, ?, ?> mPendingLockCheck;
     private LockPatternView mLockPatternView;
     private KeyguardSecurityCallback mCallback;
 
@@ -214,8 +217,28 @@
             mCallback.userActivity();
         }
 
-        public void onPatternDetected(List<LockPatternView.Cell> pattern) {
-            if (mLockPatternUtils.checkPattern(pattern, KeyguardUpdateMonitor.getCurrentUser())) {
+        public void onPatternDetected(final List<LockPatternView.Cell> pattern) {
+            mLockPatternView.disableInput();
+            if (mPendingLockCheck != null) {
+                mPendingLockCheck.cancel(false);
+            }
+
+            mPendingLockCheck = LockPatternChecker.checkPattern(
+                    mLockPatternUtils,
+                    pattern,
+                    KeyguardUpdateMonitor.getCurrentUser(),
+                    new LockPatternChecker.OnCheckCallback() {
+                        @Override
+                        public void onChecked(boolean matched) {
+                            mLockPatternView.enableInput();
+                            mPendingLockCheck = null;
+                            onPatternChecked(pattern, matched);
+                        }
+                    });
+        }
+
+        private void onPatternChecked(List<LockPatternView.Cell> pattern, boolean matched) {
+            if (matched) {
                 mCallback.reportUnlockAttempt(true);
                 mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Correct);
                 mCallback.dismiss(true);
@@ -277,6 +300,10 @@
             mCountdownTimer.cancel();
             mCountdownTimer = null;
         }
+        if (mPendingLockCheck != null) {
+            mPendingLockCheck.cancel(false);
+            mPendingLockCheck = null;
+        }
     }
 
     @Override