ChooseLockPassword.java revision af366a3ed66dcb3c3ecb1dd101e5d8869b518598
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; 5100d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller private LockPatternUtils mLockPatternUtils; 52af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller private int mRequestedQuality = DevicePolicyManager.PASSWORD_QUALITY_NUMERIC; 5300d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller private ChooseLockSettingsHelper mChooseLockSettingsHelper; 5400d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller private com.android.settings.ChooseLockPassword.Stage mUiStage = Stage.Introduction; 5500d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller private TextView mHeaderText; 5600d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller private String mFirstPin; 572f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller private KeyboardView mKeyboardView; 582f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller private PasswordEntryKeyboardHelper mKeyboardHelper; 59122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller private boolean mIsAlphaMode; 60122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller private Button mCancelButton; 61122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller private Button mNextButton; 6200d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller public static final String PASSWORD_MIN_KEY = "lockscreen.password_min"; 6300d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller public static final String PASSWORD_MAX_KEY = "lockscreen.password_max"; 6400d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller private static Handler mHandler = new Handler(); 6500d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller private static final int CONFIRM_EXISTING_REQUEST = 58; 6600d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller static final int RESULT_FINISHED = RESULT_FIRST_USER; 6700d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller private static final long ERROR_MESSAGE_TIMEOUT = 3000; 6800d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 6900d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller /** 7000d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller * Keep track internally of where the user is in choosing a pattern. 7100d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller */ 7200d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller protected enum Stage { 7300d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 74122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller Introduction(R.string.lockpassword_choose_your_password_header, 75122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller R.string.lockpassword_choose_your_pin_header, 76122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller R.string.lockpassword_continue_label), 77122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 78122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller NeedToConfirm(R.string.lockpassword_confirm_your_password_header, 79122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller R.string.lockpassword_confirm_your_pin_header, 80122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller R.string.lockpassword_ok_label), 81122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 82122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller ConfirmWrong(R.string.lockpassword_confirm_passwords_dont_match, 83122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller R.string.lockpassword_confirm_pins_dont_match, 84122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller R.string.lockpassword_continue_label); 8500d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 8600d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller /** 8700d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller * @param headerMessage The message displayed at the top. 8800d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller */ 89122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller Stage(int hintInAlpha, int hintInNumeric, int nextButtonText) { 90122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller this.alphaHint = hintInAlpha; 91122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller this.numericHint = hintInNumeric; 92122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller this.buttonText = nextButtonText; 9300d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 9400d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 95122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller public final int alphaHint; 96122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller public final int numericHint; 97122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller public final int buttonText; 9800d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 9900d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 10000d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller @Override 10100d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller protected void onCreate(Bundle savedInstanceState) { 10200d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller super.onCreate(savedInstanceState); 10347d380f1e6c823cea444004cb799d4c791145cc6Jim Miller mLockPatternUtils = new LockPatternUtils(this); 104af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller mRequestedQuality = getIntent().getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY, mRequestedQuality); 10570d5c3a0139899e5f4d425c8ab2d68f0dfc5c6daJim Miller mPasswordMinLength = getIntent().getIntExtra(PASSWORD_MIN_KEY, mPasswordMinLength); 10670d5c3a0139899e5f4d425c8ab2d68f0dfc5c6daJim Miller mPasswordMaxLength = getIntent().getIntExtra(PASSWORD_MAX_KEY, mPasswordMaxLength); 107af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller int minMode = mLockPatternUtils.getRequestedPasswordQuality(); 108af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller if (mRequestedQuality < minMode) { 109af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller mRequestedQuality = minMode; 110abc3dc64cf61c9f5c28b6f2640b221d63cb86a0aDianne Hackborn } 111abc3dc64cf61c9f5c28b6f2640b221d63cb86a0aDianne Hackborn int minLength = mLockPatternUtils.getRequestedMinimumPasswordLength(); 112abc3dc64cf61c9f5c28b6f2640b221d63cb86a0aDianne Hackborn if (mPasswordMinLength < minLength) { 113abc3dc64cf61c9f5c28b6f2640b221d63cb86a0aDianne Hackborn mPasswordMinLength = minLength; 11447d380f1e6c823cea444004cb799d4c791145cc6Jim Miller } 11500d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller initViews(); 11600d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller mChooseLockSettingsHelper = new ChooseLockSettingsHelper(this); 11700d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller if (savedInstanceState == null) { 11800d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller updateStage(Stage.Introduction); 11900d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller mChooseLockSettingsHelper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST); 12000d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 12100d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 12200d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 12300d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller private void initViews() { 1242f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller setContentView(R.layout.choose_lock_password); 1252f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller // Disable IME on our window since we provide our own keyboard 1262f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM, 1272f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); 1282f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller 129122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mCancelButton = (Button) findViewById(R.id.cancel_button); 130122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mCancelButton.setOnClickListener(this); 131122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mNextButton = (Button) findViewById(R.id.next_button); 132122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mNextButton.setOnClickListener(this); 1332f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller 1342f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller mKeyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard); 1352f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller mPasswordEntry = (TextView) findViewById(R.id.password_entry); 136122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mPasswordEntry.setOnEditorActionListener(this); 137122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mPasswordEntry.addTextChangedListener(this); 1382f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller 139af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller mIsAlphaMode = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == mRequestedQuality 140af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == mRequestedQuality; 1412f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller mKeyboardHelper = new PasswordEntryKeyboardHelper(this, mKeyboardView, mPasswordEntry); 142122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mKeyboardHelper.setKeyboardMode(mIsAlphaMode ? 143122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA 1442f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller : PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC); 1452f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller 14600d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller mHeaderText = (TextView) findViewById(R.id.headerText); 1472f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller mKeyboardView.requestFocus(); 1482f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller } 1492f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller 1502f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller @Override 1512f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller protected void onResume() { 1522f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller super.onResume(); 1532f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller updateStage(mUiStage); 1542f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller mKeyboardView.requestFocus(); 15500d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 15600d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 15700d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller @Override 158122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller protected void onSaveInstanceState(Bundle outState) { 159122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller super.onSaveInstanceState(outState); 160122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller outState.putString(KEY_UI_STAGE, mUiStage.name()); 161122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller outState.putString(KEY_FIRST_PIN, mFirstPin); 162122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 163122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 164122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller @Override 165122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller protected void onRestoreInstanceState(Bundle savedInstanceState) { 166122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller super.onRestoreInstanceState(savedInstanceState); 167122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller String state = savedInstanceState.getString(KEY_UI_STAGE); 168122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mFirstPin = savedInstanceState.getString(KEY_FIRST_PIN); 169122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller if (state != null) { 170122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mUiStage = Stage.valueOf(state); 171122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller updateStage(mUiStage); 172122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 173122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 174122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 175122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller @Override 17600d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller protected void onActivityResult(int requestCode, int resultCode, 17700d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller Intent data) { 17800d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller super.onActivityResult(requestCode, resultCode, data); 17900d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller switch (requestCode) { 18000d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller case CONFIRM_EXISTING_REQUEST: 18100d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller if (resultCode != Activity.RESULT_OK) { 18200d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller setResult(RESULT_FINISHED); 18300d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller finish(); 18400d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 18500d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller break; 18600d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 18700d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 18800d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 18900d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller protected void updateStage(Stage stage) { 19000d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller mUiStage = stage; 191122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller updateUi(); 19200d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 19300d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 19400d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller /** 19500d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller * Validates PIN and returns a message to display if PIN fails test. 196af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller * @param password the raw password the user typed in 197af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller * @return error message to show to user or null if password is OK 19800d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller */ 199af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller private String validatePassword(String password) { 200af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller if (password.length() < mPasswordMinLength) { 201122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller return getString(mIsAlphaMode ? 202122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller R.string.lockpassword_password_too_short 203122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller : R.string.lockpassword_pin_too_short, mPasswordMinLength); 20400d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 205af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller if (password.length() > mPasswordMaxLength) { 206122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller return getString(mIsAlphaMode ? 207122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller R.string.lockpassword_password_too_long 208122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller : R.string.lockpassword_pin_too_long, mPasswordMaxLength); 20900d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 210122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller boolean hasAlpha = false; 211122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller boolean hasDigit = false; 212122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller boolean hasSymbol = false; 213af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller for (int i = 0; i < password.length(); i++) { 214af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller char c = password.charAt(i); 215122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller // allow non white space Latin-1 characters only 216122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller if (c <= 32 || c > 127) { 217122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller return getString(R.string.lockpassword_illegal_character); 21800d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 219122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller if (c >= '0' && c <= '9') { 220122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller hasDigit = true; 221122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } else if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) { 222122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller hasAlpha = true; 223122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } else { 224122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller hasSymbol = true; 22500d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 22600d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 227af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller if (DevicePolicyManager.PASSWORD_QUALITY_NUMERIC == mRequestedQuality 228af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller && (hasAlpha | hasSymbol)) { 229af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller // This shouldn't be possible unless user finds some way to bring up soft keyboard 230af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller return getString(R.string.lockpassword_pin_contains_non_digits); 231af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller } else { 232af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller final boolean alphabetic = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC 233af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller == mRequestedQuality; 234af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller final boolean alphanumeric = DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC 235af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller == mRequestedQuality; 236af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller final boolean symbolic = false; // not yet 237af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller if ((alphabetic || alphanumeric) && !hasAlpha) { 238af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller return getString(R.string.lockpassword_password_requires_alpha); 239af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller } 240af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller if (alphanumeric && !hasDigit) { 241af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller return getString(R.string.lockpassword_password_requires_digit); 242af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller } 243af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller if (symbolic && !hasSymbol) { 244af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller return getString(R.string.lockpassword_password_requires_symbol); 245af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller } 246122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 24700d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller return null; 24800d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 24900d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 250122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller private void handleNext() { 251122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller final String pin = mPasswordEntry.getText().toString(); 252122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller if (TextUtils.isEmpty(pin)) { 253122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller return; 254122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 255122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller String errorMsg = null; 256122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller if (mUiStage == Stage.Introduction) { 257122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller errorMsg = validatePassword(pin); 258122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller if (errorMsg == null) { 259122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mFirstPin = pin; 260122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller updateStage(Stage.NeedToConfirm); 261122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mPasswordEntry.setText(""); 262122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 263122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } else if (mUiStage == Stage.NeedToConfirm) { 264122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller if (mFirstPin.equals(pin)) { 265122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mLockPatternUtils.clearLock(); 266af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller mLockPatternUtils.saveLockPassword(pin, mRequestedQuality); 267122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller finish(); 268122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } else { 269122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller updateStage(Stage.ConfirmWrong); 270122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller CharSequence tmp = mPasswordEntry.getText(); 271122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller if (tmp != null) { 272122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller Selection.setSelection((Spannable) tmp, 0, tmp.length()); 273122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 274122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 275122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 276122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller if (errorMsg != null) { 277122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller showError(errorMsg, mUiStage); 278122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 279122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 280122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 28100d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller public void onClick(View v) { 28200d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller switch (v.getId()) { 2832f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller case R.id.next_button: 284122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller handleNext(); 28500d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller break; 28600d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 2872f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller case R.id.cancel_button: 28800d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller finish(); 28900d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller break; 29000d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 29100d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 29200d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 29300d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller private void showError(String msg, final Stage next) { 29400d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller mHeaderText.setText(msg); 29500d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller mHandler.postDelayed(new Runnable() { 29600d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller public void run() { 29700d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller updateStage(next); 29800d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 29900d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller }, ERROR_MESSAGE_TIMEOUT); 30000d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 301122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 302122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { 303122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller // Check if this was the result of hitting the enter key 304122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller if (actionId == EditorInfo.IME_NULL) { 305122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller handleNext(); 306122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller return true; 307122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 308122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller return false; 309122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 310122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 311122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller /** 312122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller * Update the hint based on current Stage and length of password entry 313122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller */ 314122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller private void updateUi() { 315af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller String password = mPasswordEntry.getText().toString(); 316af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller final int length = password.length(); 317122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller if (mUiStage == Stage.Introduction && length > 0) { 318122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller if (length < mPasswordMinLength) { 319122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller String msg = getString(mIsAlphaMode ? R.string.lockpassword_password_too_short 320122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller : R.string.lockpassword_pin_too_short, mPasswordMinLength); 321122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mHeaderText.setText(msg); 322122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mNextButton.setEnabled(false); 323122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } else { 324af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller String error = validatePassword(password); 325af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller if (error != null) { 326af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller mHeaderText.setText(error); 327af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller mNextButton.setEnabled(false); 328af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller } else { 329af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller mHeaderText.setText(R.string.lockpassword_press_continue); 330af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller mNextButton.setEnabled(true); 331af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller } 332122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 333122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } else { 334122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mHeaderText.setText(mIsAlphaMode ? mUiStage.alphaHint : mUiStage.numericHint); 335122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mNextButton.setEnabled(length > 0); 336122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 337122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mNextButton.setText(mUiStage.buttonText); 338122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 339122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 340122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller public void afterTextChanged(Editable s) { 341122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller // Changing the text while error displayed resets to NeedToConfirm state 342122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller if (mUiStage == Stage.ConfirmWrong) { 343122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller mUiStage = Stage.NeedToConfirm; 344122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 345122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller updateUi(); 346122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 347122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 348122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller public void beforeTextChanged(CharSequence s, int start, int count, int after) { 349122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 350122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 351122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 352122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller public void onTextChanged(CharSequence s, int start, int before, int count) { 353122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 354122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 35500d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller} 356