blob: 84758d88b7ead4dfb55cfd25883a74805e51ec9e [file] [log] [blame]
Jim Miller00d24762009-12-22 19:04:57 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.settings;
18
Jim Miller00d24762009-12-22 19:04:57 -080019import com.android.internal.widget.LockPatternUtils;
Jim Miller2f9dbcb2010-02-09 19:08:02 -080020import com.android.internal.widget.PasswordEntryKeyboardHelper;
21import com.android.internal.widget.PasswordEntryKeyboardView;
Adrian Roos6f60f7e2014-08-05 19:41:11 +020022import com.android.settings.notification.RedactionInterstitial;
Jim Miller00d24762009-12-22 19:04:57 -080023
24import android.app.Activity;
Jim Miller17e9e192010-12-07 20:41:41 -080025import android.app.Fragment;
Jim Milleraf366a32010-03-25 18:45:22 -070026import android.app.admin.DevicePolicyManager;
Jim Miller00d24762009-12-22 19:04:57 -080027import android.content.Intent;
Jim Miller2f9dbcb2010-02-09 19:08:02 -080028import android.inputmethodservice.KeyboardView;
Jim Miller00d24762009-12-22 19:04:57 -080029import android.os.Bundle;
30import android.os.Handler;
Amith Yamasani552bc612011-10-07 13:58:39 -070031import android.os.Message;
Jim Miller00d24762009-12-22 19:04:57 -080032import android.text.Editable;
Jim Miller2e28ace2010-12-15 10:07:16 -080033import android.text.InputType;
Jim Miller122b6c82010-02-10 19:53:58 -080034import android.text.Selection;
35import android.text.Spannable;
Jim Miller00d24762009-12-22 19:04:57 -080036import android.text.TextUtils;
Jim Miller122b6c82010-02-10 19:53:58 -080037import android.text.TextWatcher;
38import android.view.KeyEvent;
Jim Miller17e9e192010-12-07 20:41:41 -080039import android.view.LayoutInflater;
Jim Miller00d24762009-12-22 19:04:57 -080040import android.view.View;
Jim Miller17e9e192010-12-07 20:41:41 -080041import android.view.ViewGroup;
Jim Miller00d24762009-12-22 19:04:57 -080042import android.view.View.OnClickListener;
Jim Miller122b6c82010-02-10 19:53:58 -080043import android.view.inputmethod.EditorInfo;
Jim Miller00d24762009-12-22 19:04:57 -080044import android.widget.Button;
45import android.widget.TextView;
Jim Miller122b6c82010-02-10 19:53:58 -080046import android.widget.TextView.OnEditorActionListener;
Jim Miller00d24762009-12-22 19:04:57 -080047
Fabrice Di Meglio263bcc82014-01-17 19:17:58 -080048public class ChooseLockPassword extends SettingsActivity {
Jim Miller00d24762009-12-22 19:04:57 -080049 public static final String PASSWORD_MIN_KEY = "lockscreen.password_min";
50 public static final String PASSWORD_MAX_KEY = "lockscreen.password_max";
Konstantin Lopyrev57fbf692010-05-27 16:01:41 -070051 public static final String PASSWORD_MIN_LETTERS_KEY = "lockscreen.password_min_letters";
52 public static final String PASSWORD_MIN_LOWERCASE_KEY = "lockscreen.password_min_lowercase";
53 public static final String PASSWORD_MIN_UPPERCASE_KEY = "lockscreen.password_min_uppercase";
54 public static final String PASSWORD_MIN_NUMERIC_KEY = "lockscreen.password_min_numeric";
55 public static final String PASSWORD_MIN_SYMBOLS_KEY = "lockscreen.password_min_symbols";
Konstantin Lopyrev2df65e42010-06-04 17:27:53 -070056 public static final String PASSWORD_MIN_NONLETTER_KEY = "lockscreen.password_min_nonletter";
Jim Miller00d24762009-12-22 19:04:57 -080057
Jim Miller17e9e192010-12-07 20:41:41 -080058 @Override
59 public Intent getIntent() {
60 Intent modIntent = new Intent(super.getIntent());
61 modIntent.putExtra(EXTRA_SHOW_FRAGMENT, ChooseLockPasswordFragment.class.getName());
Jim Miller17e9e192010-12-07 20:41:41 -080062 return modIntent;
63 }
Jim Miller00d24762009-12-22 19:04:57 -080064
Jim Miller17e9e192010-12-07 20:41:41 -080065 @Override
Amith Yamasania677ee22013-07-26 13:38:41 -070066 protected boolean isValidFragment(String fragmentName) {
67 if (ChooseLockPasswordFragment.class.getName().equals(fragmentName)) return true;
68 return false;
69 }
70
71 @Override
Jim Miller17e9e192010-12-07 20:41:41 -080072 public void onCreate(Bundle savedInstanceState) {
73 // TODO: Fix on phones
74 // Disable IME on our window since we provide our own keyboard
75 //getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
76 //WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
77 super.onCreate(savedInstanceState);
Jim Miller7da8cae2011-01-06 21:52:09 -080078 CharSequence msg = getText(R.string.lockpassword_choose_your_password_header);
Fabrice Di Meglio263bcc82014-01-17 19:17:58 -080079 setTitle(msg);
Jim Miller17e9e192010-12-07 20:41:41 -080080 }
Jim Miller122b6c82010-02-10 19:53:58 -080081
Jim Miller17e9e192010-12-07 20:41:41 -080082 public static class ChooseLockPasswordFragment extends Fragment
83 implements OnClickListener, OnEditorActionListener, TextWatcher {
84 private static final String KEY_FIRST_PIN = "first_pin";
85 private static final String KEY_UI_STAGE = "ui_stage";
86 private TextView mPasswordEntry;
87 private int mPasswordMinLength = 4;
88 private int mPasswordMaxLength = 16;
89 private int mPasswordMinLetters = 0;
90 private int mPasswordMinUpperCase = 0;
91 private int mPasswordMinLowerCase = 0;
92 private int mPasswordMinSymbols = 0;
93 private int mPasswordMinNumeric = 0;
94 private int mPasswordMinNonLetter = 0;
95 private LockPatternUtils mLockPatternUtils;
96 private int mRequestedQuality = DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
97 private ChooseLockSettingsHelper mChooseLockSettingsHelper;
98 private Stage mUiStage = Stage.Introduction;
99 private TextView mHeaderText;
100 private String mFirstPin;
101 private KeyboardView mKeyboardView;
102 private PasswordEntryKeyboardHelper mKeyboardHelper;
103 private boolean mIsAlphaMode;
104 private Button mCancelButton;
105 private Button mNextButton;
Jim Miller17e9e192010-12-07 20:41:41 -0800106 private static final int CONFIRM_EXISTING_REQUEST = 58;
107 static final int RESULT_FINISHED = RESULT_FIRST_USER;
108 private static final long ERROR_MESSAGE_TIMEOUT = 3000;
Amith Yamasani552bc612011-10-07 13:58:39 -0700109 private static final int MSG_SHOW_ERROR = 1;
110
111 private Handler mHandler = new Handler() {
112 @Override
113 public void handleMessage(Message msg) {
114 if (msg.what == MSG_SHOW_ERROR) {
115 updateStage((Stage) msg.obj);
116 }
117 }
118 };
Jim Miller00d24762009-12-22 19:04:57 -0800119
120 /**
Jim Miller17e9e192010-12-07 20:41:41 -0800121 * Keep track internally of where the user is in choosing a pattern.
Jim Miller00d24762009-12-22 19:04:57 -0800122 */
Jim Miller17e9e192010-12-07 20:41:41 -0800123 protected enum Stage {
Jim Miller00d24762009-12-22 19:04:57 -0800124
Jim Miller17e9e192010-12-07 20:41:41 -0800125 Introduction(R.string.lockpassword_choose_your_password_header,
126 R.string.lockpassword_choose_your_pin_header,
127 R.string.lockpassword_continue_label),
Jim Miller00d24762009-12-22 19:04:57 -0800128
Jim Miller17e9e192010-12-07 20:41:41 -0800129 NeedToConfirm(R.string.lockpassword_confirm_your_password_header,
130 R.string.lockpassword_confirm_your_pin_header,
131 R.string.lockpassword_ok_label),
Konstantin Lopyrev57fbf692010-05-27 16:01:41 -0700132
Jim Miller17e9e192010-12-07 20:41:41 -0800133 ConfirmWrong(R.string.lockpassword_confirm_passwords_dont_match,
134 R.string.lockpassword_confirm_pins_dont_match,
135 R.string.lockpassword_continue_label);
Konstantin Lopyrev57fbf692010-05-27 16:01:41 -0700136
Jim Miller17e9e192010-12-07 20:41:41 -0800137 Stage(int hintInAlpha, int hintInNumeric, int nextButtonText) {
138 this.alphaHint = hintInAlpha;
139 this.numericHint = hintInNumeric;
140 this.buttonText = nextButtonText;
Jim Millerbbb4afa2010-04-08 19:40:19 -0700141 }
Jim Miller17e9e192010-12-07 20:41:41 -0800142
143 public final int alphaHint;
144 public final int numericHint;
145 public final int buttonText;
Jim Miller00d24762009-12-22 19:04:57 -0800146 }
Jim Miller00d24762009-12-22 19:04:57 -0800147
Jim Miller17e9e192010-12-07 20:41:41 -0800148 // required constructor for fragments
149 public ChooseLockPasswordFragment() {
Jim Miller2f9dbcb2010-02-09 19:08:02 -0800150
Jim Miller17e9e192010-12-07 20:41:41 -0800151 }
Jim Miller2f9dbcb2010-02-09 19:08:02 -0800152
Jim Miller17e9e192010-12-07 20:41:41 -0800153 @Override
154 public void onCreate(Bundle savedInstanceState) {
155 super.onCreate(savedInstanceState);
156 mLockPatternUtils = new LockPatternUtils(getActivity());
157 Intent intent = getActivity().getIntent();
Amith Yamasani66026772013-09-25 14:05:33 -0700158 if (!(getActivity() instanceof ChooseLockPassword)) {
159 throw new SecurityException("Fragment contained in wrong activity");
160 }
Jim Miller17e9e192010-12-07 20:41:41 -0800161 mRequestedQuality = Math.max(intent.getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY,
162 mRequestedQuality), mLockPatternUtils.getRequestedPasswordQuality());
163 mPasswordMinLength = Math.max(
164 intent.getIntExtra(PASSWORD_MIN_KEY, mPasswordMinLength), mLockPatternUtils
165 .getRequestedMinimumPasswordLength());
166 mPasswordMaxLength = intent.getIntExtra(PASSWORD_MAX_KEY, mPasswordMaxLength);
167 mPasswordMinLetters = Math.max(intent.getIntExtra(PASSWORD_MIN_LETTERS_KEY,
168 mPasswordMinLetters), mLockPatternUtils.getRequestedPasswordMinimumLetters());
169 mPasswordMinUpperCase = Math.max(intent.getIntExtra(PASSWORD_MIN_UPPERCASE_KEY,
170 mPasswordMinUpperCase), mLockPatternUtils.getRequestedPasswordMinimumUpperCase());
171 mPasswordMinLowerCase = Math.max(intent.getIntExtra(PASSWORD_MIN_LOWERCASE_KEY,
172 mPasswordMinLowerCase), mLockPatternUtils.getRequestedPasswordMinimumLowerCase());
173 mPasswordMinNumeric = Math.max(intent.getIntExtra(PASSWORD_MIN_NUMERIC_KEY,
174 mPasswordMinNumeric), mLockPatternUtils.getRequestedPasswordMinimumNumeric());
175 mPasswordMinSymbols = Math.max(intent.getIntExtra(PASSWORD_MIN_SYMBOLS_KEY,
176 mPasswordMinSymbols), mLockPatternUtils.getRequestedPasswordMinimumSymbols());
177 mPasswordMinNonLetter = Math.max(intent.getIntExtra(PASSWORD_MIN_NONLETTER_KEY,
178 mPasswordMinNonLetter), mLockPatternUtils.getRequestedPasswordMinimumNonLetter());
Jim Miller2f9dbcb2010-02-09 19:08:02 -0800179
Jim Miller17e9e192010-12-07 20:41:41 -0800180 mChooseLockSettingsHelper = new ChooseLockSettingsHelper(getActivity());
181 }
Jim Miller2f9dbcb2010-02-09 19:08:02 -0800182
Jim Miller17e9e192010-12-07 20:41:41 -0800183 @Override
184 public View onCreateView(LayoutInflater inflater, ViewGroup container,
185 Bundle savedInstanceState) {
Jim Miller2f9dbcb2010-02-09 19:08:02 -0800186
Jim Miller17e9e192010-12-07 20:41:41 -0800187 View view = inflater.inflate(R.layout.choose_lock_password, null);
Jim Miller2f9dbcb2010-02-09 19:08:02 -0800188
Jim Miller17e9e192010-12-07 20:41:41 -0800189 mCancelButton = (Button) view.findViewById(R.id.cancel_button);
190 mCancelButton.setOnClickListener(this);
191 mNextButton = (Button) view.findViewById(R.id.next_button);
192 mNextButton.setOnClickListener(this);
Jim Miller122b6c82010-02-10 19:53:58 -0800193
Jim Miller17e9e192010-12-07 20:41:41 -0800194 mIsAlphaMode = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == mRequestedQuality
195 || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == mRequestedQuality
196 || DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == mRequestedQuality;
197 mKeyboardView = (PasswordEntryKeyboardView) view.findViewById(R.id.keyboard);
198 mPasswordEntry = (TextView) view.findViewById(R.id.password_entry);
199 mPasswordEntry.setOnEditorActionListener(this);
200 mPasswordEntry.addTextChangedListener(this);
201
Jim Miller9757e302010-12-17 18:23:23 -0800202 final Activity activity = getActivity();
203 mKeyboardHelper = new PasswordEntryKeyboardHelper(activity,
Jim Miller17e9e192010-12-07 20:41:41 -0800204 mKeyboardView, mPasswordEntry);
205 mKeyboardHelper.setKeyboardMode(mIsAlphaMode ?
206 PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA
207 : PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);
208
209 mHeaderText = (TextView) view.findViewById(R.id.headerText);
210 mKeyboardView.requestFocus();
211
Jim Miller2e28ace2010-12-15 10:07:16 -0800212 int currentType = mPasswordEntry.getInputType();
213 mPasswordEntry.setInputType(mIsAlphaMode ? currentType
Jim Miller3b46f492011-01-17 15:50:05 -0800214 : (InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD));
Jim Miller2e28ace2010-12-15 10:07:16 -0800215
Jim Miller17e9e192010-12-07 20:41:41 -0800216 Intent intent = getActivity().getIntent();
217 final boolean confirmCredentials = intent.getBooleanExtra("confirm_credentials", true);
218 if (savedInstanceState == null) {
219 updateStage(Stage.Introduction);
220 if (confirmCredentials) {
221 mChooseLockSettingsHelper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST,
222 null, null);
223 }
224 } else {
225 mFirstPin = savedInstanceState.getString(KEY_FIRST_PIN);
226 final String state = savedInstanceState.getString(KEY_UI_STAGE);
227 if (state != null) {
228 mUiStage = Stage.valueOf(state);
229 updateStage(mUiStage);
230 }
231 }
Fabrice Di Meglio263bcc82014-01-17 19:17:58 -0800232 if (activity instanceof SettingsActivity) {
233 final SettingsActivity sa = (SettingsActivity) activity;
Jim Millerd7590592011-01-10 18:24:11 -0800234 int id = mIsAlphaMode ? R.string.lockpassword_choose_your_password_header
235 : R.string.lockpassword_choose_your_pin_header;
Jim Miller9757e302010-12-17 18:23:23 -0800236 CharSequence title = getText(id);
Fabrice Di Meglio263bcc82014-01-17 19:17:58 -0800237 sa.setTitle(title);
Jim Miller9757e302010-12-17 18:23:23 -0800238 }
Jim Miller17e9e192010-12-07 20:41:41 -0800239
240 return view;
241 }
242
243 @Override
244 public void onResume() {
245 super.onResume();
Jim Miller122b6c82010-02-10 19:53:58 -0800246 updateStage(mUiStage);
Jim Miller17e9e192010-12-07 20:41:41 -0800247 mKeyboardView.requestFocus();
Jim Miller122b6c82010-02-10 19:53:58 -0800248 }
Jim Miller00d24762009-12-22 19:04:57 -0800249
Jim Miller17e9e192010-12-07 20:41:41 -0800250 @Override
Amith Yamasani552bc612011-10-07 13:58:39 -0700251 public void onPause() {
252 mHandler.removeMessages(MSG_SHOW_ERROR);
253
254 super.onPause();
255 }
256
257 @Override
Jim Miller17e9e192010-12-07 20:41:41 -0800258 public void onSaveInstanceState(Bundle outState) {
259 super.onSaveInstanceState(outState);
260 outState.putString(KEY_UI_STAGE, mUiStage.name());
261 outState.putString(KEY_FIRST_PIN, mFirstPin);
Jim Miller00d24762009-12-22 19:04:57 -0800262 }
Jim Miller00d24762009-12-22 19:04:57 -0800263
Jim Miller17e9e192010-12-07 20:41:41 -0800264 @Override
265 public void onActivityResult(int requestCode, int resultCode,
266 Intent data) {
267 super.onActivityResult(requestCode, resultCode, data);
268 switch (requestCode) {
269 case CONFIRM_EXISTING_REQUEST:
270 if (resultCode != Activity.RESULT_OK) {
271 getActivity().setResult(RESULT_FINISHED);
272 getActivity().finish();
273 }
274 break;
Jim Miller122b6c82010-02-10 19:53:58 -0800275 }
276 }
Jim Miller122b6c82010-02-10 19:53:58 -0800277
Jim Miller17e9e192010-12-07 20:41:41 -0800278 protected void updateStage(Stage stage) {
alanveef72c32012-10-03 17:10:50 -0700279 final Stage previousStage = mUiStage;
Jim Miller17e9e192010-12-07 20:41:41 -0800280 mUiStage = stage;
281 updateUi();
alanveef72c32012-10-03 17:10:50 -0700282
283 // If the stage changed, announce the header for accessibility. This
284 // is a no-op when accessibility is disabled.
285 if (previousStage != stage) {
286 mHeaderText.announceForAccessibility(mHeaderText.getText());
287 }
Jim Miller122b6c82010-02-10 19:53:58 -0800288 }
Jim Miller00d24762009-12-22 19:04:57 -0800289
Jim Miller17e9e192010-12-07 20:41:41 -0800290 /**
291 * Validates PIN and returns a message to display if PIN fails test.
292 * @param password the raw password the user typed in
293 * @return error message to show to user or null if password is OK
294 */
295 private String validatePassword(String password) {
296 if (password.length() < mPasswordMinLength) {
297 return getString(mIsAlphaMode ?
298 R.string.lockpassword_password_too_short
Jim Miller122b6c82010-02-10 19:53:58 -0800299 : R.string.lockpassword_pin_too_short, mPasswordMinLength);
Jim Miller17e9e192010-12-07 20:41:41 -0800300 }
301 if (password.length() > mPasswordMaxLength) {
302 return getString(mIsAlphaMode ?
303 R.string.lockpassword_password_too_long
Jim Miller9afb14d2011-02-14 17:25:01 -0800304 : R.string.lockpassword_pin_too_long, mPasswordMaxLength + 1);
Jim Miller17e9e192010-12-07 20:41:41 -0800305 }
306 int letters = 0;
307 int numbers = 0;
308 int lowercase = 0;
309 int symbols = 0;
310 int uppercase = 0;
311 int nonletter = 0;
312 for (int i = 0; i < password.length(); i++) {
313 char c = password.charAt(i);
Nick Kralevich7e7912d2012-08-28 10:33:45 -0700314 // allow non control Latin-1 characters only
315 if (c < 32 || c > 127) {
Jim Miller17e9e192010-12-07 20:41:41 -0800316 return getString(R.string.lockpassword_illegal_character);
317 }
318 if (c >= '0' && c <= '9') {
319 numbers++;
320 nonletter++;
321 } else if (c >= 'A' && c <= 'Z') {
322 letters++;
323 uppercase++;
324 } else if (c >= 'a' && c <= 'z') {
325 letters++;
326 lowercase++;
327 } else {
328 symbols++;
329 nonletter++;
330 }
331 }
332 if (DevicePolicyManager.PASSWORD_QUALITY_NUMERIC == mRequestedQuality
Nicolas Prevot8fd852e2014-01-25 01:02:04 +0000333 || DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX == mRequestedQuality) {
334 if (letters > 0 || symbols > 0) {
335 // This shouldn't be possible unless user finds some way to bring up
336 // soft keyboard
337 return getString(R.string.lockpassword_pin_contains_non_digits);
338 }
339 // Check for repeated characters or sequences (e.g. '1234', '0000', '2468')
340 final int sequence = LockPatternUtils.maxLengthSequence(password);
341 if (DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX == mRequestedQuality
342 && sequence > LockPatternUtils.MAX_ALLOWED_SEQUENCE) {
343 return getString(R.string.lockpassword_pin_no_sequential_digits);
344 }
Jim Miller17e9e192010-12-07 20:41:41 -0800345 } else if (DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == mRequestedQuality) {
346 if (letters < mPasswordMinLetters) {
347 return String.format(getResources().getQuantityString(
348 R.plurals.lockpassword_password_requires_letters, mPasswordMinLetters),
349 mPasswordMinLetters);
350 } else if (numbers < mPasswordMinNumeric) {
351 return String.format(getResources().getQuantityString(
352 R.plurals.lockpassword_password_requires_numeric, mPasswordMinNumeric),
353 mPasswordMinNumeric);
354 } else if (lowercase < mPasswordMinLowerCase) {
355 return String.format(getResources().getQuantityString(
356 R.plurals.lockpassword_password_requires_lowercase, mPasswordMinLowerCase),
357 mPasswordMinLowerCase);
358 } else if (uppercase < mPasswordMinUpperCase) {
359 return String.format(getResources().getQuantityString(
360 R.plurals.lockpassword_password_requires_uppercase, mPasswordMinUpperCase),
361 mPasswordMinUpperCase);
362 } else if (symbols < mPasswordMinSymbols) {
363 return String.format(getResources().getQuantityString(
364 R.plurals.lockpassword_password_requires_symbols, mPasswordMinSymbols),
365 mPasswordMinSymbols);
366 } else if (nonletter < mPasswordMinNonLetter) {
367 return String.format(getResources().getQuantityString(
368 R.plurals.lockpassword_password_requires_nonletter, mPasswordMinNonLetter),
369 mPasswordMinNonLetter);
370 }
Jim Miller122b6c82010-02-10 19:53:58 -0800371 } else {
Jim Miller17e9e192010-12-07 20:41:41 -0800372 final boolean alphabetic = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
373 == mRequestedQuality;
374 final boolean alphanumeric = DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
375 == mRequestedQuality;
376 if ((alphabetic || alphanumeric) && letters == 0) {
377 return getString(R.string.lockpassword_password_requires_alpha);
378 }
379 if (alphanumeric && numbers == 0) {
380 return getString(R.string.lockpassword_password_requires_digit);
381 }
382 }
383 if(mLockPatternUtils.checkPasswordHistory(password)) {
384 return getString(mIsAlphaMode ? R.string.lockpassword_password_recently_used
385 : R.string.lockpassword_pin_recently_used);
386 }
Nicolas Prevot8fd852e2014-01-25 01:02:04 +0000387
Jim Miller17e9e192010-12-07 20:41:41 -0800388 return null;
389 }
390
391 private void handleNext() {
392 final String pin = mPasswordEntry.getText().toString();
393 if (TextUtils.isEmpty(pin)) {
394 return;
395 }
396 String errorMsg = null;
397 if (mUiStage == Stage.Introduction) {
398 errorMsg = validatePassword(pin);
399 if (errorMsg == null) {
400 mFirstPin = pin;
Jim Miller17e9e192010-12-07 20:41:41 -0800401 mPasswordEntry.setText("");
alanveef72c32012-10-03 17:10:50 -0700402 updateStage(Stage.NeedToConfirm);
Jim Miller17e9e192010-12-07 20:41:41 -0800403 }
404 } else if (mUiStage == Stage.NeedToConfirm) {
405 if (mFirstPin.equals(pin)) {
Jim Miller5541a862011-09-02 17:33:53 -0700406 final boolean isFallback = getActivity().getIntent().getBooleanExtra(
407 LockPatternUtils.LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK, false);
Steven Rossc620ba42011-09-28 15:43:41 -0400408 mLockPatternUtils.clearLock(isFallback);
Jim Miller5541a862011-09-02 17:33:53 -0700409 mLockPatternUtils.saveLockPassword(pin, mRequestedQuality, isFallback);
Amith Yamasani8d26ba42013-05-15 11:26:19 -0700410 getActivity().setResult(RESULT_FINISHED);
Jim Miller17e9e192010-12-07 20:41:41 -0800411 getActivity().finish();
Adrian Roos6f60f7e2014-08-05 19:41:11 +0200412 startActivity(RedactionInterstitial.createStartIntent(getActivity()));
Jim Miller17e9e192010-12-07 20:41:41 -0800413 } else {
Jim Miller17e9e192010-12-07 20:41:41 -0800414 CharSequence tmp = mPasswordEntry.getText();
415 if (tmp != null) {
416 Selection.setSelection((Spannable) tmp, 0, tmp.length());
417 }
alanveef72c32012-10-03 17:10:50 -0700418 updateStage(Stage.ConfirmWrong);
Jim Miller17e9e192010-12-07 20:41:41 -0800419 }
420 }
421 if (errorMsg != null) {
422 showError(errorMsg, mUiStage);
423 }
424 }
425
426 public void onClick(View v) {
427 switch (v.getId()) {
428 case R.id.next_button:
429 handleNext();
430 break;
431
432 case R.id.cancel_button:
433 getActivity().finish();
434 break;
435 }
436 }
437
438 private void showError(String msg, final Stage next) {
439 mHeaderText.setText(msg);
alanveef72c32012-10-03 17:10:50 -0700440 mHeaderText.announceForAccessibility(mHeaderText.getText());
Amith Yamasani552bc612011-10-07 13:58:39 -0700441 Message mesg = mHandler.obtainMessage(MSG_SHOW_ERROR, next);
442 mHandler.removeMessages(MSG_SHOW_ERROR);
443 mHandler.sendMessageDelayed(mesg, ERROR_MESSAGE_TIMEOUT);
Jim Miller17e9e192010-12-07 20:41:41 -0800444 }
445
446 public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
Jim Miller74b1e0a2011-04-15 18:52:31 -0700447 // Check if this was the result of hitting the enter or "done" key
448 if (actionId == EditorInfo.IME_NULL
449 || actionId == EditorInfo.IME_ACTION_DONE
450 || actionId == EditorInfo.IME_ACTION_NEXT) {
Jim Miller17e9e192010-12-07 20:41:41 -0800451 handleNext();
452 return true;
453 }
454 return false;
455 }
456
457 /**
458 * Update the hint based on current Stage and length of password entry
459 */
460 private void updateUi() {
461 String password = mPasswordEntry.getText().toString();
462 final int length = password.length();
463 if (mUiStage == Stage.Introduction && length > 0) {
464 if (length < mPasswordMinLength) {
465 String msg = getString(mIsAlphaMode ? R.string.lockpassword_password_too_short
466 : R.string.lockpassword_pin_too_short, mPasswordMinLength);
467 mHeaderText.setText(msg);
Jim Milleraf366a32010-03-25 18:45:22 -0700468 mNextButton.setEnabled(false);
469 } else {
Jim Miller17e9e192010-12-07 20:41:41 -0800470 String error = validatePassword(password);
471 if (error != null) {
472 mHeaderText.setText(error);
473 mNextButton.setEnabled(false);
474 } else {
475 mHeaderText.setText(R.string.lockpassword_press_continue);
476 mNextButton.setEnabled(true);
477 }
Jim Milleraf366a32010-03-25 18:45:22 -0700478 }
Jim Miller17e9e192010-12-07 20:41:41 -0800479 } else {
480 mHeaderText.setText(mIsAlphaMode ? mUiStage.alphaHint : mUiStage.numericHint);
481 mNextButton.setEnabled(length > 0);
Jim Miller122b6c82010-02-10 19:53:58 -0800482 }
Jim Miller17e9e192010-12-07 20:41:41 -0800483 mNextButton.setText(mUiStage.buttonText);
Jim Miller122b6c82010-02-10 19:53:58 -0800484 }
Jim Miller122b6c82010-02-10 19:53:58 -0800485
Jim Miller17e9e192010-12-07 20:41:41 -0800486 public void afterTextChanged(Editable s) {
487 // Changing the text while error displayed resets to NeedToConfirm state
488 if (mUiStage == Stage.ConfirmWrong) {
489 mUiStage = Stage.NeedToConfirm;
490 }
491 updateUi();
Jim Miller122b6c82010-02-10 19:53:58 -0800492 }
Jim Miller122b6c82010-02-10 19:53:58 -0800493
Jim Miller17e9e192010-12-07 20:41:41 -0800494 public void beforeTextChanged(CharSequence s, int start, int count, int after) {
Jim Miller122b6c82010-02-10 19:53:58 -0800495
Jim Miller17e9e192010-12-07 20:41:41 -0800496 }
Jim Miller122b6c82010-02-10 19:53:58 -0800497
Jim Miller17e9e192010-12-07 20:41:41 -0800498 public void onTextChanged(CharSequence s, int start, int before, int count) {
Jim Miller122b6c82010-02-10 19:53:58 -0800499
Jim Miller17e9e192010-12-07 20:41:41 -0800500 }
Jim Miller122b6c82010-02-10 19:53:58 -0800501 }
Jim Miller00d24762009-12-22 19:04:57 -0800502}