ChooseLockPassword.java revision 57fbf694a53afb9c1924d81272179dceb3acfa4d
100d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller/* 200d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller * Copyright (C) 2010 The Android Open Source Project 300d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller * 400d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller * Licensed under the Apache License, Version 2.0 (the "License"); 500d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller * you may not use this file except in compliance with the License. 600d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller * You may obtain a copy of the License at 700d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller * 800d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller * http://www.apache.org/licenses/LICENSE-2.0 900d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller * 1000d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller * Unless required by applicable law or agreed to in writing, software 1100d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller * distributed under the License is distributed on an "AS IS" BASIS, 1200d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1300d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller * See the License for the specific language governing permissions and 1400d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller * limitations under the License. 1500d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller */ 1600d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 1700d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Millerpackage com.android.settings; 1800d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 1900d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Millerimport com.android.internal.widget.LockPatternUtils; 202f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Millerimport com.android.internal.widget.PasswordEntryKeyboardHelper; 212f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Millerimport com.android.internal.widget.PasswordEntryKeyboardView; 2200d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 2300d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Millerimport android.app.Activity; 24af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Millerimport android.app.admin.DevicePolicyManager; 2500d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Millerimport android.content.Intent; 262f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Millerimport android.inputmethodservice.KeyboardView; 2700d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Millerimport android.os.Bundle; 2800d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Millerimport android.os.Handler; 2900d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Millerimport android.text.Editable; 30122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Millerimport android.text.Selection; 31122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Millerimport android.text.Spannable; 3200d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Millerimport android.text.TextUtils; 33122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Millerimport android.text.TextWatcher; 34122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Millerimport android.view.KeyEvent; 3500d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Millerimport android.view.View; 362f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Millerimport android.view.WindowManager; 3700d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Millerimport android.view.View.OnClickListener; 38122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Millerimport android.view.inputmethod.EditorInfo; 3900d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Millerimport android.widget.Button; 4000d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Millerimport android.widget.TextView; 41122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Millerimport android.widget.TextView.OnEditorActionListener; 4200d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 4300d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 44122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Millerpublic class ChooseLockPassword extends Activity implements OnClickListener, OnEditorActionListener, 45122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller TextWatcher { 46122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller private static final String KEY_FIRST_PIN = "first_pin"; 47122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller private static final String KEY_UI_STAGE = "ui_stage"; 482f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller private TextView mPasswordEntry; 4900d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller private int mPasswordMinLength = 4; 5070d5c3a0139899e5f4d425c8ab2d68f0dfc5c6daJim Miller private int mPasswordMaxLength = 16; 5157fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev private int mPasswordMinLetters = 0; 5257fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev private int mPasswordMinUpperCase = 0; 5357fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev private int mPasswordMinLowerCase = 0; 5457fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev private int mPasswordMinSymbols = 0; 5557fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev private int mPasswordMinNumeric = 0; 5600d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller private LockPatternUtils mLockPatternUtils; 57af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller private int mRequestedQuality = DevicePolicyManager.PASSWORD_QUALITY_NUMERIC; 5800d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller private ChooseLockSettingsHelper mChooseLockSettingsHelper; 5900d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller private com.android.settings.ChooseLockPassword.Stage mUiStage = Stage.Introduction; 6000d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller private TextView mHeaderText; 6100d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller private String mFirstPin; 622f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller private KeyboardView mKeyboardView; 632f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller private PasswordEntryKeyboardHelper mKeyboardHelper; 64122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller private boolean mIsAlphaMode; 65122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller private Button mCancelButton; 66122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller private Button mNextButton; 6700d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller public static final String PASSWORD_MIN_KEY = "lockscreen.password_min"; 6800d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller public static final String PASSWORD_MAX_KEY = "lockscreen.password_max"; 6957fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev public static final String PASSWORD_MIN_LETTERS_KEY = "lockscreen.password_min_letters"; 7057fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev public static final String PASSWORD_MIN_LOWERCASE_KEY = "lockscreen.password_min_lowercase"; 7157fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev public static final String PASSWORD_MIN_UPPERCASE_KEY = "lockscreen.password_min_uppercase"; 7257fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev public static final String PASSWORD_MIN_NUMERIC_KEY = "lockscreen.password_min_numeric"; 7357fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev public static final String PASSWORD_MIN_SYMBOLS_KEY = "lockscreen.password_min_symbols"; 7400d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller private static Handler mHandler = new Handler(); 7500d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller private static final int CONFIRM_EXISTING_REQUEST = 58; 7600d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller static final int RESULT_FINISHED = RESULT_FIRST_USER; 7700d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller private static final long ERROR_MESSAGE_TIMEOUT = 3000; 7800d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 7900d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller /** 8000d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller * Keep track internally of where the user is in choosing a pattern. 8100d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller */ 8200d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller protected enum Stage { 8300d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 84122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller Introduction(R.string.lockpassword_choose_your_password_header, 85122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller R.string.lockpassword_choose_your_pin_header, 86122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller R.string.lockpassword_continue_label), 87122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 88122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller NeedToConfirm(R.string.lockpassword_confirm_your_password_header, 89122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller R.string.lockpassword_confirm_your_pin_header, 90122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller R.string.lockpassword_ok_label), 91122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 92122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller ConfirmWrong(R.string.lockpassword_confirm_passwords_dont_match, 93122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller R.string.lockpassword_confirm_pins_dont_match, 94122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller R.string.lockpassword_continue_label); 9500d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 9600d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller /** 9700d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller * @param headerMessage The message displayed at the top. 9800d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller */ 99122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller Stage(int hintInAlpha, int hintInNumeric, int nextButtonText) { 100122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller this.alphaHint = hintInAlpha; 101122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller this.numericHint = hintInNumeric; 102122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller this.buttonText = nextButtonText; 10300d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 10400d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 105122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller public final int alphaHint; 106122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller public final int numericHint; 107122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller public final int buttonText; 10800d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 10900d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 11000d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller @Override 11100d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller protected void onCreate(Bundle savedInstanceState) { 11200d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller super.onCreate(savedInstanceState); 11347d380f1e6c823cea444004cb799d4c791145cc6Jim Miller mLockPatternUtils = new LockPatternUtils(this); 11457fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev mRequestedQuality = Math.max(getIntent().getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY, 11557fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev mRequestedQuality), mLockPatternUtils.getRequestedPasswordQuality()); 11657fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev mPasswordMinLength = Math.max( 11757fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev getIntent().getIntExtra(PASSWORD_MIN_KEY, mPasswordMinLength), mLockPatternUtils 11857fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev .getRequestedMinimumPasswordLength()); 11970d5c3a0139899e5f4d425c8ab2d68f0dfc5c6daJim Miller mPasswordMaxLength = getIntent().getIntExtra(PASSWORD_MAX_KEY, mPasswordMaxLength); 12057fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev mPasswordMinLetters = Math.max(getIntent().getIntExtra(PASSWORD_MIN_LETTERS_KEY, 12157fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev mPasswordMinLetters), mLockPatternUtils.getRequestedPasswordMinimumLetters()); 12257fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev mPasswordMinUpperCase = Math.max(getIntent().getIntExtra(PASSWORD_MIN_UPPERCASE_KEY, 12357fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev mPasswordMinUpperCase), mLockPatternUtils.getRequestedPasswordMinimumUpperCase()); 12457fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev mPasswordMinLowerCase = Math.max(getIntent().getIntExtra(PASSWORD_MIN_LOWERCASE_KEY, 12557fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev mPasswordMinLowerCase), mLockPatternUtils.getRequestedPasswordMinimumLowerCase()); 12657fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev mPasswordMinNumeric = Math.max(getIntent().getIntExtra(PASSWORD_MIN_NUMERIC_KEY, 12757fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev mPasswordMinNumeric), mLockPatternUtils.getRequestedPasswordMinimumNumeric()); 12857fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev mPasswordMinSymbols = Math.max(getIntent().getIntExtra(PASSWORD_MIN_SYMBOLS_KEY, 12957fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev mPasswordMinSymbols), mLockPatternUtils.getRequestedPasswordMinimumSymbols()); 130bbb4afa19f75694c585506b0c091372d60e07ca7Jim Miller final boolean confirmCredentials = getIntent().getBooleanExtra("confirm_credentials", true); 13157fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev 13257fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev 13300d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller initViews(); 13400d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller mChooseLockSettingsHelper = new ChooseLockSettingsHelper(this); 13500d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller if (savedInstanceState == null) { 13600d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller updateStage(Stage.Introduction); 137bbb4afa19f75694c585506b0c091372d60e07ca7Jim Miller if (confirmCredentials) { 1382deec7edc937b1d19df0a74c4cd0c5ee3ef33070Jim Miller mChooseLockSettingsHelper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST, 1392deec7edc937b1d19df0a74c4cd0c5ee3ef33070Jim Miller null, null); 140bbb4afa19f75694c585506b0c091372d60e07ca7Jim Miller } 14100d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 14200d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 14300d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 14400d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller private void initViews() { 1452f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller setContentView(R.layout.choose_lock_password); 1462f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller // Disable IME on our window since we provide our own keyboard 1472f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM, 1482f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); 1492f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller 150122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mCancelButton = (Button) findViewById(R.id.cancel_button); 151122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mCancelButton.setOnClickListener(this); 152122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mNextButton = (Button) findViewById(R.id.next_button); 153122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mNextButton.setOnClickListener(this); 1542f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller 1552f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller mKeyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard); 1562f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller mPasswordEntry = (TextView) findViewById(R.id.password_entry); 157122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mPasswordEntry.setOnEditorActionListener(this); 158122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mPasswordEntry.addTextChangedListener(this); 1592f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller 160af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller mIsAlphaMode = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == mRequestedQuality 16157fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == mRequestedQuality 16257fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev || DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == mRequestedQuality; 1632f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller mKeyboardHelper = new PasswordEntryKeyboardHelper(this, mKeyboardView, mPasswordEntry); 164122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mKeyboardHelper.setKeyboardMode(mIsAlphaMode ? 165122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA 1662f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller : PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC); 1672f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller 16800d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller mHeaderText = (TextView) findViewById(R.id.headerText); 1692f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller mKeyboardView.requestFocus(); 1702f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller } 1712f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller 1722f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller @Override 1732f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller protected void onResume() { 1742f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller super.onResume(); 1752f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller updateStage(mUiStage); 1762f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller mKeyboardView.requestFocus(); 17700d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 17800d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 17900d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller @Override 180122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller protected void onSaveInstanceState(Bundle outState) { 181122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller super.onSaveInstanceState(outState); 182122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller outState.putString(KEY_UI_STAGE, mUiStage.name()); 183122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller outState.putString(KEY_FIRST_PIN, mFirstPin); 184122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 185122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 186122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller @Override 187122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller protected void onRestoreInstanceState(Bundle savedInstanceState) { 188122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller super.onRestoreInstanceState(savedInstanceState); 189122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller String state = savedInstanceState.getString(KEY_UI_STAGE); 190122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mFirstPin = savedInstanceState.getString(KEY_FIRST_PIN); 191122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller if (state != null) { 192122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mUiStage = Stage.valueOf(state); 193122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller updateStage(mUiStage); 194122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 195122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 196122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 197122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller @Override 19800d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller protected void onActivityResult(int requestCode, int resultCode, 19900d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller Intent data) { 20000d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller super.onActivityResult(requestCode, resultCode, data); 20100d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller switch (requestCode) { 20200d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller case CONFIRM_EXISTING_REQUEST: 20300d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller if (resultCode != Activity.RESULT_OK) { 20400d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller setResult(RESULT_FINISHED); 20500d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller finish(); 20600d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 20700d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller break; 20800d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 20900d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 21000d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 21100d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller protected void updateStage(Stage stage) { 21200d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller mUiStage = stage; 213122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller updateUi(); 21400d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 21500d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 21600d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller /** 21700d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller * Validates PIN and returns a message to display if PIN fails test. 218af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller * @param password the raw password the user typed in 219af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller * @return error message to show to user or null if password is OK 22000d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller */ 221af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller private String validatePassword(String password) { 222af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller if (password.length() < mPasswordMinLength) { 223122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller return getString(mIsAlphaMode ? 224122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller R.string.lockpassword_password_too_short 225122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller : R.string.lockpassword_pin_too_short, mPasswordMinLength); 22600d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 227af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller if (password.length() > mPasswordMaxLength) { 228122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller return getString(mIsAlphaMode ? 229122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller R.string.lockpassword_password_too_long 230122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller : R.string.lockpassword_pin_too_long, mPasswordMaxLength); 23100d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 23257fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev int letters = 0; 23357fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev int numbers = 0; 23457fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev int lowercase = 0; 23557fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev int symbols = 0; 23657fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev int uppercase = 0; 237af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller for (int i = 0; i < password.length(); i++) { 238af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller char c = password.charAt(i); 239122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller // allow non white space Latin-1 characters only 240122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller if (c <= 32 || c > 127) { 241122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller return getString(R.string.lockpassword_illegal_character); 24200d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 243122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller if (c >= '0' && c <= '9') { 24457fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev numbers++; 24557fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev } else if (c >= 'A' && c <= 'Z') { 24657fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev letters++; 24757fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev uppercase++; 24857fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev } else if (c >= 'a' && c <= 'z') { 24957fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev letters++; 25057fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev lowercase++; 251122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } else { 25257fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev symbols++; 25300d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 25400d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 255af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller if (DevicePolicyManager.PASSWORD_QUALITY_NUMERIC == mRequestedQuality 25657fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev && (letters > 0 || symbols > 0)) { 25757fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev // This shouldn't be possible unless user finds some way to bring up 25857fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev // soft keyboard 259af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller return getString(R.string.lockpassword_pin_contains_non_digits); 26057fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev } else if (DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == mRequestedQuality) { 26157fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev if (letters < mPasswordMinLetters) { 26257fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev return String.format(getResources().getQuantityString( 26357fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev R.plurals.lockpassword_password_requires_letters, mPasswordMinLetters), 26457fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev mPasswordMinLetters); 26557fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev } else if (numbers < mPasswordMinNumeric) { 26657fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev return String.format(getResources().getQuantityString( 26757fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev R.plurals.lockpassword_password_requires_numeric, mPasswordMinNumeric), 26857fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev mPasswordMinNumeric); 26957fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev } else if (lowercase < mPasswordMinLowerCase) { 27057fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev return String.format(getResources().getQuantityString( 27157fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev R.plurals.lockpassword_password_requires_lowercase, mPasswordMinLowerCase), 27257fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev mPasswordMinLowerCase); 27357fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev } else if (uppercase < mPasswordMinUpperCase) { 27457fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev return String.format(getResources().getQuantityString( 27557fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev R.plurals.lockpassword_password_requires_uppercase, mPasswordMinUpperCase), 27657fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev mPasswordMinUpperCase); 27757fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev } else if (symbols < mPasswordMinSymbols) { 27857fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev return String.format(getResources().getQuantityString( 27957fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev R.plurals.lockpassword_password_requires_symbols, mPasswordMinSymbols), 28057fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev mPasswordMinSymbols); 28157fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev } 282af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller } else { 283af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller final boolean alphabetic = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC 284af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller == mRequestedQuality; 285af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller final boolean alphanumeric = DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC 286af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller == mRequestedQuality; 28757fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev if ((alphabetic || alphanumeric) && letters == 0) { 288af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller return getString(R.string.lockpassword_password_requires_alpha); 289af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller } 29057fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev if (alphanumeric && numbers == 0) { 291af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller return getString(R.string.lockpassword_password_requires_digit); 292af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller } 293122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 294015c186a2466ad1bee01952ef067ba8d7e21cab7Konstantin Lopyrev if(mLockPatternUtils.checkPasswordHistory(password)) { 295015c186a2466ad1bee01952ef067ba8d7e21cab7Konstantin Lopyrev return getString(mIsAlphaMode ? R.string.lockpassword_password_recently_used 296015c186a2466ad1bee01952ef067ba8d7e21cab7Konstantin Lopyrev : R.string.lockpassword_pin_recently_used); 297015c186a2466ad1bee01952ef067ba8d7e21cab7Konstantin Lopyrev } 29800d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller return null; 29900d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 30000d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 301122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller private void handleNext() { 302122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller final String pin = mPasswordEntry.getText().toString(); 303122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller if (TextUtils.isEmpty(pin)) { 304122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller return; 305122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 306122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller String errorMsg = null; 307122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller if (mUiStage == Stage.Introduction) { 308122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller errorMsg = validatePassword(pin); 309122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller if (errorMsg == null) { 310122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mFirstPin = pin; 311122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller updateStage(Stage.NeedToConfirm); 312122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mPasswordEntry.setText(""); 313122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 314122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } else if (mUiStage == Stage.NeedToConfirm) { 315122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller if (mFirstPin.equals(pin)) { 316122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mLockPatternUtils.clearLock(); 317af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller mLockPatternUtils.saveLockPassword(pin, mRequestedQuality); 318122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller finish(); 319122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } else { 320122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller updateStage(Stage.ConfirmWrong); 321122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller CharSequence tmp = mPasswordEntry.getText(); 322122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller if (tmp != null) { 323122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller Selection.setSelection((Spannable) tmp, 0, tmp.length()); 324122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 325122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 326122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 327122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller if (errorMsg != null) { 328122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller showError(errorMsg, mUiStage); 329122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 330122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 331122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 33200d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller public void onClick(View v) { 33300d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller switch (v.getId()) { 3342f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller case R.id.next_button: 335122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller handleNext(); 33600d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller break; 33700d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 3382f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller case R.id.cancel_button: 33900d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller finish(); 34000d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller break; 34100d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 34200d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 34300d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 34400d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller private void showError(String msg, final Stage next) { 34500d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller mHeaderText.setText(msg); 34600d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller mHandler.postDelayed(new Runnable() { 34700d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller public void run() { 34800d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller updateStage(next); 34900d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 35000d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller }, ERROR_MESSAGE_TIMEOUT); 35100d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 352122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 353122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { 354122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller // Check if this was the result of hitting the enter key 355015c186a2466ad1bee01952ef067ba8d7e21cab7Konstantin Lopyrev if (actionId == EditorInfo.IME_NULL && event.getAction() == KeyEvent.ACTION_DOWN) { 356122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller handleNext(); 357122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller return true; 358122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 359122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller return false; 360122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 361122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 362122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller /** 363122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller * Update the hint based on current Stage and length of password entry 364122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller */ 365122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller private void updateUi() { 366af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller String password = mPasswordEntry.getText().toString(); 367af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller final int length = password.length(); 368122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller if (mUiStage == Stage.Introduction && length > 0) { 369122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller if (length < mPasswordMinLength) { 370122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller String msg = getString(mIsAlphaMode ? R.string.lockpassword_password_too_short 371122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller : R.string.lockpassword_pin_too_short, mPasswordMinLength); 372122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mHeaderText.setText(msg); 373122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mNextButton.setEnabled(false); 374122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } else { 375af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller String error = validatePassword(password); 376af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller if (error != null) { 377af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller mHeaderText.setText(error); 378af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller mNextButton.setEnabled(false); 379af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller } else { 380af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller mHeaderText.setText(R.string.lockpassword_press_continue); 381af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller mNextButton.setEnabled(true); 382af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller } 383122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 384122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } else { 385122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mHeaderText.setText(mIsAlphaMode ? mUiStage.alphaHint : mUiStage.numericHint); 386122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mNextButton.setEnabled(length > 0); 387122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 388122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mNextButton.setText(mUiStage.buttonText); 389122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 390122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 391122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller public void afterTextChanged(Editable s) { 392122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller // Changing the text while error displayed resets to NeedToConfirm state 393122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller if (mUiStage == Stage.ConfirmWrong) { 394122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mUiStage = Stage.NeedToConfirm; 395122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 396122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller updateUi(); 397122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 398122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 399122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller public void beforeTextChanged(CharSequence s, int start, int count, int after) { 400122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 401122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 402122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 403122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller public void onTextChanged(CharSequence s, int start, int before, int count) { 404122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 405122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 40600d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller} 407