Gray out confirm button on pattern/pin/password set dialog

Setting a pin/pattern/password can take a second. Gray out the confirm
button to avoid multiple submissions.

Note that this requires async tasks so that the button is shown as gray
in a timely way.

Also don't add another stage - this causes a11y to repeat the title.

Bug: 22882174
Change-Id: Ib8047fde9e12afa25e82ebfa3a1e799a4b7043f2
diff --git a/src/com/android/settings/ChooseLockPassword.java b/src/com/android/settings/ChooseLockPassword.java
index 64aaaca..cb924cb 100644
--- a/src/com/android/settings/ChooseLockPassword.java
+++ b/src/com/android/settings/ChooseLockPassword.java
@@ -128,6 +128,7 @@
         private static final String KEY_CURRENT_PASSWORD = "current_password";
 
         private String mCurrentPassword;
+        private String mChosenPassword;
         private boolean mHasChallenge;
         private long mChallenge;
         private TextView mPasswordEntry;
@@ -145,7 +146,6 @@
         private int mRequestedQuality = DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
         private ChooseLockSettingsHelper mChooseLockSettingsHelper;
         private Stage mUiStage = Stage.Introduction;
-        private boolean mDone = false;
         private TextView mHeaderText;
         private String mFirstPin;
         private KeyboardView mKeyboardView;
@@ -302,7 +302,6 @@
                     mCurrentPassword = savedInstanceState.getString(KEY_CURRENT_PASSWORD);
                 }
             }
-            mDone = false;
             if (activity instanceof SettingsActivity) {
                 final SettingsActivity sa = (SettingsActivity) activity;
                 int id = mIsAlphaMode ? R.string.lockpassword_choose_your_password_header
@@ -478,37 +477,54 @@
             return null;
         }
 
-        public void handleNext() {
-            if (mDone) return;
+        private class SaveChosenPasswordAndFinish extends AsyncTask<Void, Void, Void> {
+            boolean mWasSecureBefore;
 
-            final String pin = mPasswordEntry.getText().toString();
-            if (TextUtils.isEmpty(pin)) {
+            @Override
+            public void onPreExecute() {
+                mWasSecureBefore = mLockPatternUtils.isSecure(UserHandle.myUserId());
+                final boolean required = getActivity().getIntent().getBooleanExtra(
+                        EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true);
+                mLockPatternUtils.setCredentialRequiredToDecrypt(required);
+            }
+
+            @Override
+            public Void doInBackground(Void... v) {
+                mLockPatternUtils.saveLockPassword(mChosenPassword, mCurrentPassword, mRequestedQuality,
+                                                   UserHandle.myUserId());
+                return null;
+            }
+
+            @Override
+            public void onPostExecute(Void v) {
+                if (mHasChallenge) {
+                    startVerifyPassword(mChosenPassword, mWasSecureBefore);
+                    return;
+                } else {
+                    getActivity().setResult(RESULT_FINISHED);
+                }
+                finishConfirmStage(mWasSecureBefore);
+            }
+        }
+
+
+        public void handleNext() {
+            mChosenPassword = mPasswordEntry.getText().toString();
+            if (TextUtils.isEmpty(mChosenPassword)) {
                 return;
             }
             String errorMsg = null;
             if (mUiStage == Stage.Introduction) {
-                errorMsg = validatePassword(pin);
+                errorMsg = validatePassword(mChosenPassword);
                 if (errorMsg == null) {
-                    mFirstPin = pin;
+                    mFirstPin = mChosenPassword;
                     mPasswordEntry.setText("");
                     updateStage(Stage.NeedToConfirm);
                 }
             } else if (mUiStage == Stage.NeedToConfirm) {
-                if (mFirstPin.equals(pin)) {
-                    boolean wasSecureBefore = mLockPatternUtils.isSecure(UserHandle.myUserId());
-                    final boolean required = getActivity().getIntent().getBooleanExtra(
-                            EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true);
-                    mLockPatternUtils.setCredentialRequiredToDecrypt(required);
-                    mLockPatternUtils.saveLockPassword(pin, mCurrentPassword, mRequestedQuality,
-                            UserHandle.myUserId());
-
-                    if (mHasChallenge) {
-                        startVerifyPassword(pin, wasSecureBefore);
-                        return;
-                    } else {
-                        getActivity().setResult(RESULT_FINISHED);
-                    }
-                    finishConfirmStage(wasSecureBefore);
+                if (mFirstPin.equals(mChosenPassword)) {
+                    setNextEnabled(false);
+                    new SaveChosenPasswordAndFinish().execute();
                 } else {
                     CharSequence tmp = mPasswordEntry.getText();
                     if (tmp != null) {
@@ -557,7 +573,6 @@
 
         private void finishConfirmStage(boolean wasSecureBefore) {
             getActivity().finish();
-            mDone = true;
             if (!wasSecureBefore) {
                 Intent intent = getRedactionInterstitialIntent(getActivity());
                 if (intent != null) {
diff --git a/src/com/android/settings/ChooseLockPattern.java b/src/com/android/settings/ChooseLockPattern.java
index 087a23e..026fd46 100644
--- a/src/com/android/settings/ChooseLockPattern.java
+++ b/src/com/android/settings/ChooseLockPattern.java
@@ -346,7 +346,6 @@
         }
 
         private Stage mUiStage = Stage.Introduction;
-        private boolean mDone = false;
 
         private Runnable mClearPatternRunnable = new Runnable() {
             public void run() {
@@ -435,7 +434,6 @@
                 }
                 updateStage(Stage.values()[savedInstanceState.getInt(KEY_UI_STAGE)]);
             }
-            mDone = false;
         }
 
         @Override
@@ -483,7 +481,7 @@
                     throw new IllegalStateException("expected ui stage " + Stage.ChoiceConfirmed
                             + " when button is " + RightButtonMode.Confirm);
                 }
-                saveChosenPatternAndFinish();
+                new SaveChosenPatternAndFinish().execute();
             } else if (mUiStage.rightMode == RightButtonMode.Ok) {
                 if (mUiStage != Stage.HelpScreen) {
                     throw new IllegalStateException("Help screen is only mode with ok button, "
@@ -623,34 +621,49 @@
             mLockPatternView.postDelayed(mClearPatternRunnable, WRONG_PATTERN_CLEAR_TIMEOUT_MS);
         }
 
-        private void saveChosenPatternAndFinish() {
-            if (mDone) return;
-            LockPatternUtils utils = mChooseLockSettingsHelper.utils();
-            final boolean lockVirgin = !utils.isPatternEverChosen(UserHandle.myUserId());
+        private class SaveChosenPatternAndFinish extends AsyncTask<Void,Void,Void> {
+            boolean mLockVirgin;
+            LockPatternUtils mUtils;
+            boolean mWasSecureBefore;
 
-            boolean wasSecureBefore = utils.isSecure(UserHandle.myUserId());
+            @Override
+            protected void onPreExecute(){
+                setRightButtonEnabled(false);
+                mUtils = mChooseLockSettingsHelper.utils();
+                mLockVirgin = !mUtils.isPatternEverChosen(UserHandle.myUserId());
 
-            final boolean required = getActivity().getIntent().getBooleanExtra(
+                mWasSecureBefore = mUtils.isSecure(UserHandle.myUserId());
+
+                final boolean required = getActivity().getIntent().getBooleanExtra(
                     EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true);
 
-            utils.setCredentialRequiredToDecrypt(required);
-            utils.saveLockPattern(mChosenPattern, mCurrentPattern, UserHandle.myUserId());
-
-            if (lockVirgin) {
-                utils.setVisiblePatternEnabled(true, UserHandle.myUserId());
+                mUtils.setCredentialRequiredToDecrypt(required);
             }
 
-            if (mHasChallenge) {
-                startVerifyPattern(utils, wasSecureBefore);
-            } else {
-                if (!wasSecureBefore) {
-                    Intent intent = getRedactionInterstitialIntent(getActivity());
-                    if (intent != null) {
-                        startActivity(intent);
-                    }
+            @Override
+            protected Void doInBackground(Void... params){
+                mUtils.saveLockPattern(mChosenPattern, mCurrentPattern, UserHandle.myUserId());
+                return null;
+            }
+
+            @Override
+            protected void onPostExecute(Void param) {
+                if (mLockVirgin) {
+                    mUtils.setVisiblePatternEnabled(true, UserHandle.myUserId());
                 }
-                getActivity().setResult(RESULT_FINISHED);
-                doFinish();
+
+                if (mHasChallenge) {
+                    startVerifyPattern(mUtils, mWasSecureBefore);
+                } else {
+                    if (!mWasSecureBefore) {
+                        Intent intent = getRedactionInterstitialIntent(getActivity());
+                        if (intent != null) {
+                            startActivity(intent);
+                        }
+                    }
+                    getActivity().setResult(RESULT_FINISHED);
+                    doFinish();
+                }
             }
         }
 
@@ -693,7 +706,6 @@
 
         private void doFinish() {
             getActivity().finish();
-            mDone = true;
         }
     }
 }