Loading src/com/android/settings/ChooseLockPassword.java +99 −92 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -30,7 +30,6 @@ import android.app.admin.DevicePolicyManager; 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; Loading Loading @@ -122,10 +121,12 @@ public class ChooseLockPassword extends SettingsActivity { } 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; Loading @@ -142,14 +143,11 @@ public class ChooseLockPassword extends SettingsActivity { 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; Loading Loading @@ -305,8 +303,11 @@ public class ChooseLockPassword extends SettingsActivity { 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 Loading @@ -325,16 +326,18 @@ public class ChooseLockPassword extends SettingsActivity { public void onResume() { super.onResume(); updateStage(mUiStage); mPasswordEntryInputDisabler.setInputEnabled(true); 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(); Loading Loading @@ -482,39 +485,8 @@ public class ChooseLockPassword extends SettingsActivity { 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; Loading @@ -529,9 +501,7 @@ public class ChooseLockPassword extends SettingsActivity { } } 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) { Loading @@ -545,49 +515,6 @@ public class ChooseLockPassword extends SettingsActivity { } } 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); } Loading Loading @@ -631,6 +558,7 @@ public class ChooseLockPassword extends SettingsActivity { * 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) { Loading @@ -651,9 +579,10 @@ public class ChooseLockPassword extends SettingsActivity { } } 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) { Loading @@ -671,5 +600,83 @@ public class ChooseLockPassword extends SettingsActivity { 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; } } } src/com/android/settings/ChooseLockPattern.java +87 −80 Original line number Diff line number Diff line Loading @@ -19,8 +19,8 @@ package com.android.settings; 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; Loading @@ -31,7 +31,6 @@ import android.app.Activity; 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; Loading Loading @@ -125,7 +124,7 @@ public class ChooseLockPattern extends SettingsActivity { } public static class ChooseLockPatternFragment extends InstrumentedFragment implements View.OnClickListener { implements View.OnClickListener, SaveAndFinishWorker.Listener { public static final int CONFIRM_EXISTING_REQUEST = 55; Loading @@ -137,6 +136,8 @@ public class ChooseLockPattern extends SettingsActivity { 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; Loading Loading @@ -354,7 +355,7 @@ public class ChooseLockPattern extends SettingsActivity { }; 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"; Loading Loading @@ -433,21 +434,29 @@ public class ChooseLockPattern extends SettingsActivity { 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(); 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); } } Loading Loading @@ -481,7 +490,7 @@ public class ChooseLockPattern extends SettingsActivity { 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, " Loading Loading @@ -568,7 +577,7 @@ public class ChooseLockPattern extends SettingsActivity { 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 { Loading Loading @@ -613,7 +622,6 @@ public class ChooseLockPattern extends SettingsActivity { } } // clear the wrong pattern unless they have started a new one // already private void postClearPatternRunnable() { Loading @@ -621,91 +629,90 @@ public class ChooseLockPattern extends SettingsActivity { 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()); 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( EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true); mUtils.setCredentialRequiredToDecrypt(required); mSaveAndFinishWorker.start(mChooseLockSettingsHelper.utils(), required, mHasChallenge, mChallenge, mChosenPattern, mCurrentPattern); } @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()); } public void onChosenLockSaveFinished(boolean wasSecureBefore, Intent resultData) { getActivity().setResult(RESULT_FINISHED, resultData); getActivity().finish(); if (mHasChallenge) { startVerifyPattern(mUtils, mWasSecureBefore); } else { if (!mWasSecureBefore) { if (!wasSecureBefore) { Intent intent = getRedactionInterstitialIntent(getActivity()); if (intent != null) { startActivity(intent); } } getActivity().setResult(RESULT_FINISHED); doFinish(); } } } private void startVerifyPattern(LockPatternUtils utils, final boolean wasSecureBefore) { mLockPatternView.disableInput(); if (mPendingLockCheck != null) { mPendingLockCheck.cancel(false); 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(); } mPendingLockCheck = LockPatternChecker.verifyPattern( utils, mChosenPattern, mChallenge, UserHandle.myUserId(), new LockPatternChecker.OnVerifyCallback() { @Override public void onVerified(byte[] token, int timeoutMs) { 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"); } mLockPatternView.enableInput(); mPendingLockCheck = null; if (!wasSecureBefore) { Intent intent = getRedactionInterstitialIntent(getActivity()); if (intent != null) { startActivity(intent); } result = new Intent(); result.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token); } Intent intent = new Intent(); intent.putExtra( ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token); getActivity().setResult(RESULT_FINISHED, intent); doFinish(); return result; } }); @Override protected void finish(Intent resultData) { if (mLockVirgin) { mUtils.setVisiblePatternEnabled(true, UserHandle.myUserId()); } private void doFinish() { getActivity().finish(); super.finish(resultData); } } } src/com/android/settings/SaveChosenLockWorkerBase.java 0 → 100644 +106 −0 Original line number Diff line number Diff line /* * 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); } } Loading
src/com/android/settings/ChooseLockPassword.java +99 −92 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -30,7 +30,6 @@ import android.app.admin.DevicePolicyManager; 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; Loading Loading @@ -122,10 +121,12 @@ public class ChooseLockPassword extends SettingsActivity { } 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; Loading @@ -142,14 +143,11 @@ public class ChooseLockPassword extends SettingsActivity { 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; Loading Loading @@ -305,8 +303,11 @@ public class ChooseLockPassword extends SettingsActivity { 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 Loading @@ -325,16 +326,18 @@ public class ChooseLockPassword extends SettingsActivity { public void onResume() { super.onResume(); updateStage(mUiStage); mPasswordEntryInputDisabler.setInputEnabled(true); 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(); Loading Loading @@ -482,39 +485,8 @@ public class ChooseLockPassword extends SettingsActivity { 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; Loading @@ -529,9 +501,7 @@ public class ChooseLockPassword extends SettingsActivity { } } 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) { Loading @@ -545,49 +515,6 @@ public class ChooseLockPassword extends SettingsActivity { } } 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); } Loading Loading @@ -631,6 +558,7 @@ public class ChooseLockPassword extends SettingsActivity { * 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) { Loading @@ -651,9 +579,10 @@ public class ChooseLockPassword extends SettingsActivity { } } 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) { Loading @@ -671,5 +600,83 @@ public class ChooseLockPassword extends SettingsActivity { 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; } } }
src/com/android/settings/ChooseLockPattern.java +87 −80 Original line number Diff line number Diff line Loading @@ -19,8 +19,8 @@ package com.android.settings; 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; Loading @@ -31,7 +31,6 @@ import android.app.Activity; 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; Loading Loading @@ -125,7 +124,7 @@ public class ChooseLockPattern extends SettingsActivity { } public static class ChooseLockPatternFragment extends InstrumentedFragment implements View.OnClickListener { implements View.OnClickListener, SaveAndFinishWorker.Listener { public static final int CONFIRM_EXISTING_REQUEST = 55; Loading @@ -137,6 +136,8 @@ public class ChooseLockPattern extends SettingsActivity { 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; Loading Loading @@ -354,7 +355,7 @@ public class ChooseLockPattern extends SettingsActivity { }; 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"; Loading Loading @@ -433,21 +434,29 @@ public class ChooseLockPattern extends SettingsActivity { 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(); 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); } } Loading Loading @@ -481,7 +490,7 @@ public class ChooseLockPattern extends SettingsActivity { 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, " Loading Loading @@ -568,7 +577,7 @@ public class ChooseLockPattern extends SettingsActivity { 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 { Loading Loading @@ -613,7 +622,6 @@ public class ChooseLockPattern extends SettingsActivity { } } // clear the wrong pattern unless they have started a new one // already private void postClearPatternRunnable() { Loading @@ -621,91 +629,90 @@ public class ChooseLockPattern extends SettingsActivity { 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()); 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( EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true); mUtils.setCredentialRequiredToDecrypt(required); mSaveAndFinishWorker.start(mChooseLockSettingsHelper.utils(), required, mHasChallenge, mChallenge, mChosenPattern, mCurrentPattern); } @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()); } public void onChosenLockSaveFinished(boolean wasSecureBefore, Intent resultData) { getActivity().setResult(RESULT_FINISHED, resultData); getActivity().finish(); if (mHasChallenge) { startVerifyPattern(mUtils, mWasSecureBefore); } else { if (!mWasSecureBefore) { if (!wasSecureBefore) { Intent intent = getRedactionInterstitialIntent(getActivity()); if (intent != null) { startActivity(intent); } } getActivity().setResult(RESULT_FINISHED); doFinish(); } } } private void startVerifyPattern(LockPatternUtils utils, final boolean wasSecureBefore) { mLockPatternView.disableInput(); if (mPendingLockCheck != null) { mPendingLockCheck.cancel(false); 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(); } mPendingLockCheck = LockPatternChecker.verifyPattern( utils, mChosenPattern, mChallenge, UserHandle.myUserId(), new LockPatternChecker.OnVerifyCallback() { @Override public void onVerified(byte[] token, int timeoutMs) { 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"); } mLockPatternView.enableInput(); mPendingLockCheck = null; if (!wasSecureBefore) { Intent intent = getRedactionInterstitialIntent(getActivity()); if (intent != null) { startActivity(intent); } result = new Intent(); result.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token); } Intent intent = new Intent(); intent.putExtra( ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token); getActivity().setResult(RESULT_FINISHED, intent); doFinish(); return result; } }); @Override protected void finish(Intent resultData) { if (mLockVirgin) { mUtils.setVisiblePatternEnabled(true, UserHandle.myUserId()); } private void doFinish() { getActivity().finish(); super.finish(resultData); } } }
src/com/android/settings/SaveChosenLockWorkerBase.java 0 → 100644 +106 −0 Original line number Diff line number Diff line /* * 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); } }