Fix ChoosePat/Pin/Pwd crash from async task

Use a retained worker fragment to track the asynchronous
save-and-finish task so that ChoosePattern/Password activity
is properly dismissed after a configuration change.

Bug:23424884
Bug:23521530
Change-Id: I328022c1603cfb0f6812cd8aa7916ae7b72c9950
diff --git a/src/com/android/settings/ChooseLockPassword.java b/src/com/android/settings/ChooseLockPassword.java
index bc370c9..54c3620 100644
--- a/src/com/android/settings/ChooseLockPassword.java
+++ b/src/com/android/settings/ChooseLockPassword.java
@@ -17,11 +17,11 @@
 package com.android.settings;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.widget.LockPatternChecker;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.widget.PasswordEntryKeyboardHelper;
 import com.android.internal.widget.PasswordEntryKeyboardView;
 import com.android.internal.widget.TextViewInputDisabler;
+import com.android.internal.widget.LockPatternUtils.RequestThrottledException;
 import com.android.settings.notification.RedactionInterstitial;
 
 import android.app.Activity;
@@ -30,7 +30,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.inputmethodservice.KeyboardView;
-import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
@@ -122,10 +121,12 @@
     }
 
     public static class ChooseLockPasswordFragment extends InstrumentedFragment
-            implements OnClickListener, OnEditorActionListener,  TextWatcher {
+            implements OnClickListener, OnEditorActionListener,  TextWatcher,
+            SaveAndFinishWorker.Listener {
         private static final String KEY_FIRST_PIN = "first_pin";
         private static final String KEY_UI_STAGE = "ui_stage";
         private static final String KEY_CURRENT_PASSWORD = "current_password";
+        private static final String FRAGMENT_TAG_SAVE_AND_FINISH = "save_and_finish_worker";
 
         private String mCurrentPassword;
         private String mChosenPassword;
@@ -142,14 +143,11 @@
         private int mPasswordMinNumeric = 0;
         private int mPasswordMinNonLetter = 0;
         private LockPatternUtils mLockPatternUtils;
-        private AsyncTask<?, ?, ?> mPendingLockCheck;
+        private SaveAndFinishWorker mSaveAndFinishWorker;
         private int mRequestedQuality = DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
         private ChooseLockSettingsHelper mChooseLockSettingsHelper;
         private Stage mUiStage = Stage.Introduction;
 
-        // True once we have confirmed new PIN/password to prevent virtual keyboard
-        // re-entries of the same PIN
-        private boolean mDone = false;
         private TextView mHeaderText;
         private String mFirstPin;
         private KeyboardView mKeyboardView;
@@ -305,8 +303,11 @@
                 if (mCurrentPassword == null) {
                     mCurrentPassword = savedInstanceState.getString(KEY_CURRENT_PASSWORD);
                 }
+
+                // Re-attach to the exiting worker if there is one.
+                mSaveAndFinishWorker = (SaveAndFinishWorker) getFragmentManager().findFragmentByTag(
+                        FRAGMENT_TAG_SAVE_AND_FINISH);
             }
-            mDone = false;
             if (activity instanceof SettingsActivity) {
                 final SettingsActivity sa = (SettingsActivity) activity;
                 int id = mIsAlphaMode ? R.string.lockpassword_choose_your_password_header
@@ -325,16 +326,18 @@
         public void onResume() {
             super.onResume();
             updateStage(mUiStage);
-            mPasswordEntryInputDisabler.setInputEnabled(true);
-            mKeyboardView.requestFocus();
+            if (mSaveAndFinishWorker != null) {
+                mSaveAndFinishWorker.setListener(this);
+            } else {
+                mKeyboardView.requestFocus();
+            }
         }
 
         @Override
         public void onPause() {
             mHandler.removeMessages(MSG_SHOW_ERROR);
-            if (mPendingLockCheck != null) {
-                mPendingLockCheck.cancel(false);
-                mPendingLockCheck = null;
+            if (mSaveAndFinishWorker != null) {
+                mSaveAndFinishWorker.setListener(null);
             }
 
             super.onPause();
@@ -482,39 +485,8 @@
             return null;
         }
 
-        private class SaveChosenPasswordAndFinish extends AsyncTask<Void, Void, Void> {
-            boolean mWasSecureBefore;
-
-            @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() {
-            if (mDone) return;
+            if (mSaveAndFinishWorker != null) return;
             mChosenPassword = mPasswordEntry.getText().toString();
             if (TextUtils.isEmpty(mChosenPassword)) {
                 return;
@@ -529,9 +501,7 @@
                 }
             } else if (mUiStage == Stage.NeedToConfirm) {
                 if (mFirstPin.equals(mChosenPassword)) {
-                    setNextEnabled(false);
-                    mDone = true;
-                    new SaveChosenPasswordAndFinish().execute();
+                    startSaveAndFinish();
                 } else {
                     CharSequence tmp = mPasswordEntry.getText();
                     if (tmp != null) {
@@ -545,49 +515,6 @@
             }
         }
 
-        private void startVerifyPassword(final String pin, final boolean wasSecureBefore) {
-            mPasswordEntryInputDisabler.setInputEnabled(false);
-            setNextEnabled(false);
-            if (mPendingLockCheck != null) {
-                mPendingLockCheck.cancel(false);
-            }
-
-            mPendingLockCheck = LockPatternChecker.verifyPassword(
-                    mLockPatternUtils,
-                    pin,
-                    mChallenge,
-                    UserHandle.myUserId(),
-                    new LockPatternChecker.OnVerifyCallback() {
-                        @Override
-                        public void onVerified(byte[] token, int timeoutMs) {
-                            if (token == null) {
-                                Log.e(TAG, "critical: no token returned from known good password");
-                            }
-
-                            mPasswordEntryInputDisabler.setInputEnabled(true);
-                            setNextEnabled(true);
-                            mPendingLockCheck = null;
-
-                            Intent intent = new Intent();
-                            intent.putExtra(
-                                    ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN,
-                                    token);
-                            getActivity().setResult(RESULT_FINISHED, intent);
-                            finishConfirmStage(wasSecureBefore);
-                        }
-                    });
-        }
-
-        private void finishConfirmStage(boolean wasSecureBefore) {
-            getActivity().finish();
-            if (!wasSecureBefore) {
-                Intent intent = getRedactionInterstitialIntent(getActivity());
-                if (intent != null) {
-                    startActivity(intent);
-                }
-            }
-        }
-
         protected void setNextEnabled(boolean enabled) {
             mNextButton.setEnabled(enabled);
         }
@@ -631,6 +558,7 @@
          * Update the hint based on current Stage and length of password entry
          */
         private void updateUi() {
+            final boolean canInput = mSaveAndFinishWorker == null;
             String password = mPasswordEntry.getText().toString();
             final int length = password.length();
             if (mUiStage == Stage.Introduction) {
@@ -651,9 +579,10 @@
                 }
             } else {
                 mHeaderText.setText(mIsAlphaMode ? mUiStage.alphaHint : mUiStage.numericHint);
-                setNextEnabled(length > 0);
+                setNextEnabled(canInput && length > 0);
             }
             setNextText(mUiStage.buttonText);
+            mPasswordEntryInputDisabler.setInputEnabled(canInput);
         }
 
         public void afterTextChanged(Editable s) {
@@ -671,5 +600,83 @@
         public void onTextChanged(CharSequence s, int start, int before, int count) {
 
         }
+
+        private void startSaveAndFinish() {
+            if (mSaveAndFinishWorker != null) {
+                Log.w(TAG, "startSaveAndFinish with an existing SaveAndFinishWorker.");
+                return;
+            }
+
+            mPasswordEntryInputDisabler.setInputEnabled(false);
+            setNextEnabled(false);
+
+            mSaveAndFinishWorker = new SaveAndFinishWorker();
+            getFragmentManager().beginTransaction().add(mSaveAndFinishWorker,
+                    FRAGMENT_TAG_SAVE_AND_FINISH).commit();
+            mSaveAndFinishWorker.setListener(this);
+
+            final boolean required = getActivity().getIntent().getBooleanExtra(
+                    EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true);
+            mSaveAndFinishWorker.start(mLockPatternUtils, required, mHasChallenge, mChallenge,
+                    mChosenPassword, mCurrentPassword, mRequestedQuality);
+        }
+
+        @Override
+        public void onChosenLockSaveFinished(boolean wasSecureBefore, Intent resultData) {
+            getActivity().setResult(RESULT_FINISHED, resultData);
+            getActivity().finish();
+
+            if (!wasSecureBefore) {
+                Intent intent = getRedactionInterstitialIntent(getActivity());
+                if (intent != null) {
+                    startActivity(intent);
+                }
+            }
+        }
+    }
+
+    private static class SaveAndFinishWorker extends SaveChosenLockWorkerBase {
+
+        private String mChosenPassword;
+        private String mCurrentPassword;
+        private int mRequestedQuality;
+
+        public void start(LockPatternUtils utils, boolean required,
+                boolean hasChallenge, long challenge,
+                String chosenPassword, String currentPassword, int requestedQuality) {
+            prepare(utils, required, hasChallenge, challenge);
+
+            mChosenPassword = chosenPassword;
+            mCurrentPassword = currentPassword;
+            mRequestedQuality = requestedQuality;
+
+            start();
+        }
+
+        @Override
+        protected Intent saveAndVerifyInBackground() {
+            Intent result = null;
+            final int userId = UserHandle.myUserId();
+            mUtils.saveLockPassword(mChosenPassword, mCurrentPassword, mRequestedQuality,
+                    userId);
+
+            if (mHasChallenge) {
+                byte[] token;
+                try {
+                    token = mUtils.verifyPassword(mChosenPassword, mChallenge, userId);
+                } catch (RequestThrottledException e) {
+                    token = null;
+                }
+
+                if (token == null) {
+                    Log.e(TAG, "critical: no token returned for known good password.");
+                }
+
+                result = new Intent();
+                result.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
+            }
+
+            return result;
+        }
     }
 }
diff --git a/src/com/android/settings/ChooseLockPattern.java b/src/com/android/settings/ChooseLockPattern.java
index 026fd46..641cc7f 100644
--- a/src/com/android/settings/ChooseLockPattern.java
+++ b/src/com/android/settings/ChooseLockPattern.java
@@ -19,8 +19,8 @@
 import com.android.internal.logging.MetricsLogger;
 import com.google.android.collect.Lists;
 import com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient;
-import com.android.internal.widget.LockPatternChecker;
 import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockPatternUtils.RequestThrottledException;
 import com.android.internal.widget.LockPatternView;
 import com.android.internal.widget.LockPatternView.Cell;
 import com.android.settings.notification.RedactionInterstitial;
@@ -31,7 +31,6 @@
 import android.app.Fragment;
 import android.content.Context;
 import android.content.Intent;
-import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.util.Log;
@@ -125,7 +124,7 @@
     }
 
     public static class ChooseLockPatternFragment extends InstrumentedFragment
-            implements View.OnClickListener {
+            implements View.OnClickListener, SaveAndFinishWorker.Listener {
 
         public static final int CONFIRM_EXISTING_REQUEST = 55;
 
@@ -137,6 +136,8 @@
 
         private static final int ID_EMPTY_MESSAGE = -1;
 
+        private static final String FRAGMENT_TAG_SAVE_AND_FINISH = "save_and_finish_worker";
+
         private String mCurrentPattern;
         private boolean mHasChallenge;
         private long mChallenge;
@@ -354,7 +355,7 @@
         };
 
         private ChooseLockSettingsHelper mChooseLockSettingsHelper;
-        private AsyncTask<?, ?, ?> mPendingLockCheck;
+        private SaveAndFinishWorker mSaveAndFinishWorker;
 
         private static final String KEY_UI_STAGE = "uiStage";
         private static final String KEY_PATTERN_CHOICE = "chosenPattern";
@@ -433,21 +434,29 @@
                     mCurrentPattern = savedInstanceState.getString(KEY_CURRENT_PATTERN);
                 }
                 updateStage(Stage.values()[savedInstanceState.getInt(KEY_UI_STAGE)]);
+
+                // Re-attach to the exiting worker if there is one.
+                mSaveAndFinishWorker = (SaveAndFinishWorker) getFragmentManager().findFragmentByTag(
+                        FRAGMENT_TAG_SAVE_AND_FINISH);
             }
         }
 
         @Override
         public void onResume() {
             super.onResume();
-            mLockPatternView.enableInput();
+            if (mSaveAndFinishWorker != null) {
+                setRightButtonEnabled(false);
+                mSaveAndFinishWorker.setListener(this);
+            } else {
+                mLockPatternView.enableInput();
+            }
         }
 
         @Override
         public void onPause() {
             super.onPause();
-            if (mPendingLockCheck != null) {
-                mPendingLockCheck.cancel(false);
-                mPendingLockCheck = null;
+            if (mSaveAndFinishWorker != null) {
+                mSaveAndFinishWorker.setListener(null);
             }
         }
 
@@ -481,7 +490,7 @@
                     throw new IllegalStateException("expected ui stage " + Stage.ChoiceConfirmed
                             + " when button is " + RightButtonMode.Confirm);
                 }
-                new SaveChosenPatternAndFinish().execute();
+                startSaveAndFinish();
             } else if (mUiStage.rightMode == RightButtonMode.Ok) {
                 if (mUiStage != Stage.HelpScreen) {
                     throw new IllegalStateException("Help screen is only mode with ok button, "
@@ -568,7 +577,7 @@
             setRightButtonText(stage.rightMode.text);
             setRightButtonEnabled(stage.rightMode.enabled);
 
-            // same for whether the patten is enabled
+            // same for whether the pattern is enabled
             if (stage.patternEnabled) {
                 mLockPatternView.enableInput();
             } else {
@@ -613,7 +622,6 @@
             }
         }
 
-
         // clear the wrong pattern unless they have started a new one
         // already
         private void postClearPatternRunnable() {
@@ -621,91 +629,90 @@
             mLockPatternView.postDelayed(mClearPatternRunnable, WRONG_PATTERN_CLEAR_TIMEOUT_MS);
         }
 
-        private class SaveChosenPatternAndFinish extends AsyncTask<Void,Void,Void> {
-            boolean mLockVirgin;
-            LockPatternUtils mUtils;
-            boolean mWasSecureBefore;
+        private void startSaveAndFinish() {
+            if (mSaveAndFinishWorker != null) {
+                Log.w(TAG, "startSaveAndFinish with an existing SaveAndFinishWorker.");
+                return;
+            }
 
-            @Override
-            protected void onPreExecute(){
-                setRightButtonEnabled(false);
-                mUtils = mChooseLockSettingsHelper.utils();
-                mLockVirgin = !mUtils.isPatternEverChosen(UserHandle.myUserId());
+            setRightButtonEnabled(false);
 
-                mWasSecureBefore = mUtils.isSecure(UserHandle.myUserId());
+            mSaveAndFinishWorker = new SaveAndFinishWorker();
+            getFragmentManager().beginTransaction().add(mSaveAndFinishWorker,
+                    FRAGMENT_TAG_SAVE_AND_FINISH).commit();
+            mSaveAndFinishWorker.setListener(this);
 
-                final boolean required = getActivity().getIntent().getBooleanExtra(
+            final boolean required = getActivity().getIntent().getBooleanExtra(
                     EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true);
-
-                mUtils.setCredentialRequiredToDecrypt(required);
-            }
-
-            @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());
-                }
-
-                if (mHasChallenge) {
-                    startVerifyPattern(mUtils, mWasSecureBefore);
-                } else {
-                    if (!mWasSecureBefore) {
-                        Intent intent = getRedactionInterstitialIntent(getActivity());
-                        if (intent != null) {
-                            startActivity(intent);
-                        }
-                    }
-                    getActivity().setResult(RESULT_FINISHED);
-                    doFinish();
-                }
-            }
+            mSaveAndFinishWorker.start(mChooseLockSettingsHelper.utils(), required,
+                    mHasChallenge, mChallenge, mChosenPattern, mCurrentPattern);
         }
 
-        private void startVerifyPattern(LockPatternUtils utils, final boolean wasSecureBefore) {
-            mLockPatternView.disableInput();
-            if (mPendingLockCheck != null) {
-                mPendingLockCheck.cancel(false);
-            }
-
-            mPendingLockCheck = LockPatternChecker.verifyPattern(
-                    utils,
-                    mChosenPattern,
-                    mChallenge,
-                    UserHandle.myUserId(),
-                    new LockPatternChecker.OnVerifyCallback() {
-                        @Override
-                        public void onVerified(byte[] token, int timeoutMs) {
-                            if (token == null) {
-                                Log.e(TAG, "critical: no token returned for known good pattern");
-                            }
-
-                            mLockPatternView.enableInput();
-                            mPendingLockCheck = null;
-
-                            if (!wasSecureBefore) {
-                                Intent intent = getRedactionInterstitialIntent(getActivity());
-                                if (intent != null) {
-                                    startActivity(intent);
-                                }
-                            }
-
-                            Intent intent = new Intent();
-                            intent.putExtra(
-                                    ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
-                            getActivity().setResult(RESULT_FINISHED, intent);
-                            doFinish();
-                        }
-                    });
-        }
-
-        private void doFinish() {
+        @Override
+        public void onChosenLockSaveFinished(boolean wasSecureBefore, Intent resultData) {
+            getActivity().setResult(RESULT_FINISHED, resultData);
             getActivity().finish();
+
+            if (!wasSecureBefore) {
+                Intent intent = getRedactionInterstitialIntent(getActivity());
+                if (intent != null) {
+                    startActivity(intent);
+                }
+            }
+        }
+    }
+
+    private static class SaveAndFinishWorker extends SaveChosenLockWorkerBase {
+
+        private List<LockPatternView.Cell> mChosenPattern;
+        private String mCurrentPattern;
+        private boolean mLockVirgin;
+
+        public void start(LockPatternUtils utils, boolean credentialRequired,
+                boolean hasChallenge, long challenge,
+                List<LockPatternView.Cell> chosenPattern, String currentPattern) {
+            prepare(utils, credentialRequired, hasChallenge, challenge);
+
+            mCurrentPattern = currentPattern;
+            mChosenPattern = chosenPattern;
+
+            mLockVirgin = !mUtils.isPatternEverChosen(UserHandle.myUserId());
+
+            start();
+        }
+
+        @Override
+        protected Intent saveAndVerifyInBackground() {
+            Intent result = null;
+            final int userId = UserHandle.myUserId();
+            mUtils.saveLockPattern(mChosenPattern, mCurrentPattern, userId);
+
+            if (mHasChallenge) {
+                byte[] token;
+                try {
+                    token = mUtils.verifyPattern(mChosenPattern, mChallenge, userId);
+                } catch (RequestThrottledException e) {
+                    token = null;
+                }
+
+                if (token == null) {
+                    Log.e(TAG, "critical: no token returned for known good pattern");
+                }
+
+                result = new Intent();
+                result.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
+            }
+
+            return result;
+        }
+
+        @Override
+        protected void finish(Intent resultData) {
+            if (mLockVirgin) {
+                mUtils.setVisiblePatternEnabled(true, UserHandle.myUserId());
+            }
+
+            super.finish(resultData);
         }
     }
 }
diff --git a/src/com/android/settings/SaveChosenLockWorkerBase.java b/src/com/android/settings/SaveChosenLockWorkerBase.java
new file mode 100644
index 0000000..a40871a
--- /dev/null
+++ b/src/com/android/settings/SaveChosenLockWorkerBase.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings;
+
+import android.app.Fragment;
+import android.content.Intent;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.UserHandle;
+
+import com.android.internal.widget.LockPatternUtils;
+
+/**
+ * An invisible retained worker fragment to track the AsyncWork that saves (and optionally
+ * verifies if a challenge is given) the chosen lock credential (pattern/pin/password).
+ */
+abstract class SaveChosenLockWorkerBase extends Fragment {
+
+    private Listener mListener;
+    private boolean mFinished;
+    private Intent mResultData;
+
+    protected LockPatternUtils mUtils;
+    protected boolean mHasChallenge;
+    protected long mChallenge;
+    protected boolean mWasSecureBefore;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setRetainInstance(true);
+    }
+
+    public void setListener(Listener listener) {
+        if (mListener == listener) {
+            return;
+        }
+
+        mListener = listener;
+        if (mFinished && mListener != null) {
+            mListener.onChosenLockSaveFinished(mWasSecureBefore, mResultData);
+        }
+    }
+
+    protected void prepare(LockPatternUtils utils, boolean credentialRequired,
+            boolean hasChallenge, long challenge) {
+        mUtils = utils;
+
+        mHasChallenge = hasChallenge;
+        mChallenge = challenge;
+        mWasSecureBefore = mUtils.isSecure(UserHandle.myUserId());
+
+        mUtils.setCredentialRequiredToDecrypt(credentialRequired);
+
+        mFinished = false;
+        mResultData = null;
+    }
+
+    protected void start() {
+        new Task().execute();
+    }
+
+    /**
+     * Executes the save and verify work in background.
+     * @return Intent with challenge token or null.
+     */
+    protected abstract Intent saveAndVerifyInBackground();
+
+    protected void finish(Intent resultData) {
+        mFinished = true;
+        mResultData = resultData;
+        if (mListener != null) {
+            mListener.onChosenLockSaveFinished(mWasSecureBefore, mResultData);
+        }
+    }
+
+    private class Task extends AsyncTask<Void, Void, Intent> {
+        @Override
+        protected Intent doInBackground(Void... params){
+            return saveAndVerifyInBackground();
+        }
+
+        @Override
+        protected void onPostExecute(Intent resultData) {
+            finish(resultData);
+        }
+    }
+
+    interface Listener {
+        public void onChosenLockSaveFinished(boolean wasSecureBefore, Intent resultData);
+    }
+}