ChooseLockPassword.java revision 27ca263b7f6cf64f6a789a052a0f737b18a9aef3
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 android.app.Activity; 2017e9e1933055b207473b488595b2887bfcaea32eJim Millerimport android.app.Fragment; 21af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Millerimport android.app.admin.DevicePolicyManager; 2227ca263b7f6cf64f6a789a052a0f737b18a9aef3Andrew Scullimport android.app.admin.PasswordMetrics; 230698a216311acd9ab52224602d1a75c08bf89f04Jim Millerimport android.content.Context; 2400d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Millerimport android.content.Intent; 250bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Makimport android.graphics.drawable.InsetDrawable; 2600d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Millerimport android.os.Bundle; 279ba765b875ebeb66d8a870a29a00fe53e9da306dTony Makimport android.os.Handler; 289ba765b875ebeb66d8a870a29a00fe53e9da306dTony Makimport android.os.Message; 290bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Makimport android.support.v7.widget.LinearLayoutManager; 300bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Makimport android.support.v7.widget.RecyclerView; 3100d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Millerimport android.text.Editable; 322e28acedc623527aa5e84ba66635700d6547569aJim Millerimport android.text.InputType; 33122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Millerimport android.text.Selection; 34122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Millerimport android.text.Spannable; 3500d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Millerimport android.text.TextUtils; 36122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Millerimport android.text.TextWatcher; 3791e6c499ca8f33cc093fed4277d2b48ab780b309Andres Moralesimport android.util.Log; 380bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Makimport android.view.inputmethod.EditorInfo; 39122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Millerimport android.view.KeyEvent; 4017e9e1933055b207473b488595b2887bfcaea32eJim Millerimport android.view.LayoutInflater; 4100d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Millerimport android.view.View; 4200d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Millerimport android.view.View.OnClickListener; 4339b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport android.view.ViewGroup; 4400d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Millerimport android.widget.Button; 450bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Makimport android.widget.EditText; 46d189ac52a4e49291b729d817fc903116abc086d0Maurice Lamimport android.widget.LinearLayout; 4700d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Millerimport android.widget.TextView; 48122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Millerimport android.widget.TextView.OnEditorActionListener; 4900d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 509d1bfd1e8de6e46137a9571507c03526880d6a46Chris Wrenimport com.android.internal.logging.MetricsProto.MetricsEvent; 5139b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport com.android.internal.widget.LockPatternUtils; 5239b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport com.android.internal.widget.LockPatternUtils.RequestThrottledException; 5339b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport com.android.internal.widget.TextViewInputDisabler; 546507613ebcd22e4691c2af92a5c161bd327db336Fan Zhangimport com.android.settings.core.InstrumentedFragment; 5539b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport com.android.settings.notification.RedactionInterstitial; 560bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Makimport com.android.settings.password.PasswordRequirementAdapter; 57d189ac52a4e49291b729d817fc903116abc086d0Maurice Lamimport com.android.setupwizardlib.GlifLayout; 5839b467482d1bf256a111c757e9b7621c6f523271Jason Monk 590bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Makimport java.util.ArrayList; 600bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Makimport java.util.List; 610bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak 620bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Makimport static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC; 630bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Makimport static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC; 640bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Makimport static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX; 650bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Makimport static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC; 660bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Makimport static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX; 670bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak 68263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Megliopublic class ChooseLockPassword extends SettingsActivity { 6900d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller public static final String PASSWORD_MIN_KEY = "lockscreen.password_min"; 7000d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller public static final String PASSWORD_MAX_KEY = "lockscreen.password_max"; 7157fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev public static final String PASSWORD_MIN_LETTERS_KEY = "lockscreen.password_min_letters"; 7257fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev public static final String PASSWORD_MIN_LOWERCASE_KEY = "lockscreen.password_min_lowercase"; 7357fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev public static final String PASSWORD_MIN_UPPERCASE_KEY = "lockscreen.password_min_uppercase"; 7457fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev public static final String PASSWORD_MIN_NUMERIC_KEY = "lockscreen.password_min_numeric"; 7557fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev public static final String PASSWORD_MIN_SYMBOLS_KEY = "lockscreen.password_min_symbols"; 762df65e4facac659314c2440d0af6316924166e2bKonstantin Lopyrev public static final String PASSWORD_MIN_NONLETTER_KEY = "lockscreen.password_min_nonletter"; 7700d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 7891e6c499ca8f33cc093fed4277d2b48ab780b309Andres Morales private static final String TAG = "ChooseLockPassword"; 7991e6c499ca8f33cc093fed4277d2b48ab780b309Andres Morales 8017e9e1933055b207473b488595b2887bfcaea32eJim Miller @Override 8117e9e1933055b207473b488595b2887bfcaea32eJim Miller public Intent getIntent() { 8217e9e1933055b207473b488595b2887bfcaea32eJim Miller Intent modIntent = new Intent(super.getIntent()); 836b19fa9017800b94c75238339a337fd8f6c3e808Maurice Lam modIntent.putExtra(EXTRA_SHOW_FRAGMENT, getFragmentClass().getName()); 8417e9e1933055b207473b488595b2887bfcaea32eJim Miller return modIntent; 8517e9e1933055b207473b488595b2887bfcaea32eJim Miller } 86122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 87f788718f2142e5546bbf1b6847793d59ffea898bAdrian Roos public static Intent createIntent(Context context, int quality, 880698a216311acd9ab52224602d1a75c08bf89f04Jim Miller int minLength, final int maxLength, boolean requirePasswordToDecrypt, 890698a216311acd9ab52224602d1a75c08bf89f04Jim Miller boolean confirmCredentials) { 900698a216311acd9ab52224602d1a75c08bf89f04Jim Miller Intent intent = new Intent().setClass(context, ChooseLockPassword.class); 910698a216311acd9ab52224602d1a75c08bf89f04Jim Miller intent.putExtra(LockPatternUtils.PASSWORD_TYPE_KEY, quality); 920698a216311acd9ab52224602d1a75c08bf89f04Jim Miller intent.putExtra(PASSWORD_MIN_KEY, minLength); 930698a216311acd9ab52224602d1a75c08bf89f04Jim Miller intent.putExtra(PASSWORD_MAX_KEY, maxLength); 940698a216311acd9ab52224602d1a75c08bf89f04Jim Miller intent.putExtra(ChooseLockGeneric.CONFIRM_CREDENTIALS, confirmCredentials); 950698a216311acd9ab52224602d1a75c08bf89f04Jim Miller intent.putExtra(EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, requirePasswordToDecrypt); 960698a216311acd9ab52224602d1a75c08bf89f04Jim Miller return intent; 970698a216311acd9ab52224602d1a75c08bf89f04Jim Miller } 980698a216311acd9ab52224602d1a75c08bf89f04Jim Miller 99a0e1236fa970ea953bfbcc84fcae1f3fb7f189d1Andres Morales public static Intent createIntent(Context context, int quality, 100fe432e838e5588cd4ac664d7e74f3d70a99d7df1Clara Bayarri int minLength, final int maxLength, boolean requirePasswordToDecrypt, 101fe432e838e5588cd4ac664d7e74f3d70a99d7df1Clara Bayarri boolean confirmCredentials, int userId) { 102fe432e838e5588cd4ac664d7e74f3d70a99d7df1Clara Bayarri Intent intent = createIntent(context, quality, minLength, maxLength, 103fe432e838e5588cd4ac664d7e74f3d70a99d7df1Clara Bayarri requirePasswordToDecrypt, confirmCredentials); 1046934a044b8ebf4dac28d1c1142b6eee4ecc64f66Clara Bayarri intent.putExtra(Intent.EXTRA_USER_ID, userId); 105fe432e838e5588cd4ac664d7e74f3d70a99d7df1Clara Bayarri return intent; 106fe432e838e5588cd4ac664d7e74f3d70a99d7df1Clara Bayarri } 107fe432e838e5588cd4ac664d7e74f3d70a99d7df1Clara Bayarri 108fe432e838e5588cd4ac664d7e74f3d70a99d7df1Clara Bayarri public static Intent createIntent(Context context, int quality, 109a0e1236fa970ea953bfbcc84fcae1f3fb7f189d1Andres Morales int minLength, final int maxLength, boolean requirePasswordToDecrypt, String password) { 1103859643c5b65bd54dcacce029a3a97a0386ede25Maurice Lam Intent intent = createIntent(context, quality, minLength, maxLength, 1113859643c5b65bd54dcacce029a3a97a0386ede25Maurice Lam requirePasswordToDecrypt, false); 112a0e1236fa970ea953bfbcc84fcae1f3fb7f189d1Andres Morales intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, password); 113a0e1236fa970ea953bfbcc84fcae1f3fb7f189d1Andres Morales return intent; 114a0e1236fa970ea953bfbcc84fcae1f3fb7f189d1Andres Morales } 115a0e1236fa970ea953bfbcc84fcae1f3fb7f189d1Andres Morales 116fe432e838e5588cd4ac664d7e74f3d70a99d7df1Clara Bayarri public static Intent createIntent(Context context, int quality, int minLength, 117fe432e838e5588cd4ac664d7e74f3d70a99d7df1Clara Bayarri int maxLength, boolean requirePasswordToDecrypt, String password, int userId) { 118fe432e838e5588cd4ac664d7e74f3d70a99d7df1Clara Bayarri Intent intent = createIntent(context, quality, minLength, maxLength, 119fe432e838e5588cd4ac664d7e74f3d70a99d7df1Clara Bayarri requirePasswordToDecrypt, password); 1206934a044b8ebf4dac28d1c1142b6eee4ecc64f66Clara Bayarri intent.putExtra(Intent.EXTRA_USER_ID, userId); 121fe432e838e5588cd4ac664d7e74f3d70a99d7df1Clara Bayarri return intent; 122fe432e838e5588cd4ac664d7e74f3d70a99d7df1Clara Bayarri } 123fe432e838e5588cd4ac664d7e74f3d70a99d7df1Clara Bayarri 1246609b0c22ae89a24d1b07dc3c4143452616d4450Andres Morales public static Intent createIntent(Context context, int quality, 1256609b0c22ae89a24d1b07dc3c4143452616d4450Andres Morales int minLength, final int maxLength, boolean requirePasswordToDecrypt, long challenge) { 1263859643c5b65bd54dcacce029a3a97a0386ede25Maurice Lam Intent intent = createIntent(context, quality, minLength, maxLength, 1273859643c5b65bd54dcacce029a3a97a0386ede25Maurice Lam requirePasswordToDecrypt, false); 1286609b0c22ae89a24d1b07dc3c4143452616d4450Andres Morales intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true); 1296609b0c22ae89a24d1b07dc3c4143452616d4450Andres Morales intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge); 1306609b0c22ae89a24d1b07dc3c4143452616d4450Andres Morales return intent; 1316609b0c22ae89a24d1b07dc3c4143452616d4450Andres Morales } 1326609b0c22ae89a24d1b07dc3c4143452616d4450Andres Morales 133fe432e838e5588cd4ac664d7e74f3d70a99d7df1Clara Bayarri public static Intent createIntent(Context context, int quality, int minLength, 134fe432e838e5588cd4ac664d7e74f3d70a99d7df1Clara Bayarri int maxLength, boolean requirePasswordToDecrypt, long challenge, int userId) { 135fe432e838e5588cd4ac664d7e74f3d70a99d7df1Clara Bayarri Intent intent = createIntent(context, quality, minLength, maxLength, 136fe432e838e5588cd4ac664d7e74f3d70a99d7df1Clara Bayarri requirePasswordToDecrypt, challenge); 1376934a044b8ebf4dac28d1c1142b6eee4ecc64f66Clara Bayarri intent.putExtra(Intent.EXTRA_USER_ID, userId); 138fe432e838e5588cd4ac664d7e74f3d70a99d7df1Clara Bayarri return intent; 139fe432e838e5588cd4ac664d7e74f3d70a99d7df1Clara Bayarri } 140fe432e838e5588cd4ac664d7e74f3d70a99d7df1Clara Bayarri 14117e9e1933055b207473b488595b2887bfcaea32eJim Miller @Override 142a677ee210c67d13d15ba0663887675bda16354d8Amith Yamasani protected boolean isValidFragment(String fragmentName) { 143a677ee210c67d13d15ba0663887675bda16354d8Amith Yamasani if (ChooseLockPasswordFragment.class.getName().equals(fragmentName)) return true; 144a677ee210c67d13d15ba0663887675bda16354d8Amith Yamasani return false; 145a677ee210c67d13d15ba0663887675bda16354d8Amith Yamasani } 146a677ee210c67d13d15ba0663887675bda16354d8Amith Yamasani 1476b19fa9017800b94c75238339a337fd8f6c3e808Maurice Lam /* package */ Class<? extends Fragment> getFragmentClass() { 1486b19fa9017800b94c75238339a337fd8f6c3e808Maurice Lam return ChooseLockPasswordFragment.class; 1496b19fa9017800b94c75238339a337fd8f6c3e808Maurice Lam } 1506b19fa9017800b94c75238339a337fd8f6c3e808Maurice Lam 151a677ee210c67d13d15ba0663887675bda16354d8Amith Yamasani @Override 15271fde52ae36f134e93835bee53bc4bfe5481bba0Udam Saini protected void onCreate(Bundle savedInstanceState) { 15317e9e1933055b207473b488595b2887bfcaea32eJim Miller super.onCreate(savedInstanceState); 1547da8cae44b622518fbffd6d265f291c39e9fc722Jim Miller CharSequence msg = getText(R.string.lockpassword_choose_your_password_header); 155263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Meglio setTitle(msg); 156d189ac52a4e49291b729d817fc903116abc086d0Maurice Lam LinearLayout layout = (LinearLayout) findViewById(R.id.content_parent); 157d189ac52a4e49291b729d817fc903116abc086d0Maurice Lam layout.setFitsSystemWindows(false); 15817e9e1933055b207473b488595b2887bfcaea32eJim Miller } 159122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 1608a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren public static class ChooseLockPasswordFragment extends InstrumentedFragment 1610bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak implements OnClickListener, OnEditorActionListener, TextWatcher, 1623e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia SaveAndFinishWorker.Listener { 16317e9e1933055b207473b488595b2887bfcaea32eJim Miller private static final String KEY_FIRST_PIN = "first_pin"; 16417e9e1933055b207473b488595b2887bfcaea32eJim Miller private static final String KEY_UI_STAGE = "ui_stage"; 165a0e1236fa970ea953bfbcc84fcae1f3fb7f189d1Andres Morales private static final String KEY_CURRENT_PASSWORD = "current_password"; 1663e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia private static final String FRAGMENT_TAG_SAVE_AND_FINISH = "save_and_finish_worker"; 167a0e1236fa970ea953bfbcc84fcae1f3fb7f189d1Andres Morales 168a0e1236fa970ea953bfbcc84fcae1f3fb7f189d1Andres Morales private String mCurrentPassword; 169cff37ecbdd4a3d8f9b81fc295155bde5fcf8ea0cPaul Lawrence private String mChosenPassword; 1706609b0c22ae89a24d1b07dc3c4143452616d4450Andres Morales private boolean mHasChallenge; 1716609b0c22ae89a24d1b07dc3c4143452616d4450Andres Morales private long mChallenge; 1720bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak private EditText mPasswordEntry; 173f2c2c19339b5d821cb6196911cee04dc9ac647adXiyuan Xia private TextViewInputDisabler mPasswordEntryInputDisabler; 1744c00a611835e2257502ddcdd26b4e827c5b64f80Adrian Roos private int mPasswordMinLength = LockPatternUtils.MIN_LOCK_PASSWORD_SIZE; 17517e9e1933055b207473b488595b2887bfcaea32eJim Miller private int mPasswordMaxLength = 16; 17617e9e1933055b207473b488595b2887bfcaea32eJim Miller private int mPasswordMinLetters = 0; 17717e9e1933055b207473b488595b2887bfcaea32eJim Miller private int mPasswordMinUpperCase = 0; 17817e9e1933055b207473b488595b2887bfcaea32eJim Miller private int mPasswordMinLowerCase = 0; 17917e9e1933055b207473b488595b2887bfcaea32eJim Miller private int mPasswordMinSymbols = 0; 18017e9e1933055b207473b488595b2887bfcaea32eJim Miller private int mPasswordMinNumeric = 0; 18117e9e1933055b207473b488595b2887bfcaea32eJim Miller private int mPasswordMinNonLetter = 0; 1829ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak private int mPasswordMinLengthToFulfillAllPolicies = 0; 1830bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak private int mUserId; 1840bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak private boolean mHideDrawer = false; 1850bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak /** 1860bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak * Password requirements that we need to verify. 1870bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak */ 1880bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak private int[] mPasswordRequirements; 1890bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak 19017e9e1933055b207473b488595b2887bfcaea32eJim Miller private LockPatternUtils mLockPatternUtils; 1913e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia private SaveAndFinishWorker mSaveAndFinishWorker; 19217e9e1933055b207473b488595b2887bfcaea32eJim Miller private int mRequestedQuality = DevicePolicyManager.PASSWORD_QUALITY_NUMERIC; 19317e9e1933055b207473b488595b2887bfcaea32eJim Miller private ChooseLockSettingsHelper mChooseLockSettingsHelper; 19417e9e1933055b207473b488595b2887bfcaea32eJim Miller private Stage mUiStage = Stage.Introduction; 1950bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak private PasswordRequirementAdapter mPasswordRequirementAdapter; 1961f8fb0f8ce1e82266a3a12b3d31b9062cff3fc44Paul Lawrence 19717e9e1933055b207473b488595b2887bfcaea32eJim Miller private TextView mHeaderText; 19817e9e1933055b207473b488595b2887bfcaea32eJim Miller private String mFirstPin; 1990bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak private RecyclerView mPasswordRestrictionView; 20017e9e1933055b207473b488595b2887bfcaea32eJim Miller private boolean mIsAlphaMode; 20117e9e1933055b207473b488595b2887bfcaea32eJim Miller private Button mCancelButton; 20217e9e1933055b207473b488595b2887bfcaea32eJim Miller private Button mNextButton; 2030bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak 2049ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak private TextChangedHandler mTextChangedHandler; 2059ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak 20617e9e1933055b207473b488595b2887bfcaea32eJim Miller private static final int CONFIRM_EXISTING_REQUEST = 58; 20717e9e1933055b207473b488595b2887bfcaea32eJim Miller static final int RESULT_FINISHED = RESULT_FIRST_USER; 208552bc61ae2aaf67fd2f19564ca2ced002e8675e6Amith Yamasani 2090bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak private static final int MIN_LETTER_IN_PASSWORD = 0; 2100bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak private static final int MIN_UPPER_LETTERS_IN_PASSWORD = 1; 2110bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak private static final int MIN_LOWER_LETTERS_IN_PASSWORD = 2; 2120bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak private static final int MIN_SYMBOLS_IN_PASSWORD = 3; 2130bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak private static final int MIN_NUMBER_IN_PASSWORD = 4; 2140bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak private static final int MIN_NON_LETTER_IN_PASSWORD = 5; 2150bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak 2160bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak // Error code returned from {@link #validatePassword(String)}. 2170bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak private static final int NO_ERROR = 0; 2180bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak private static final int CONTAIN_INVALID_CHARACTERS = 1 << 0; 2190bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak private static final int TOO_SHORT = 1 << 1; 2200bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak private static final int TOO_LONG = 1 << 2; 2210bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak private static final int CONTAIN_NON_DIGITS = 1 << 3; 2220bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak private static final int CONTAIN_SEQUENTIAL_DIGITS = 1 << 4; 2230bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak private static final int RECENTLY_USED = 1 << 5; 2240bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak private static final int NOT_ENOUGH_LETTER = 1 << 6; 2250bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak private static final int NOT_ENOUGH_UPPER_CASE = 1 << 7; 2260bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak private static final int NOT_ENOUGH_LOWER_CASE = 1 << 8; 2270bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak private static final int NOT_ENOUGH_DIGITS = 1 << 9; 2280bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak private static final int NOT_ENOUGH_SYMBOLS = 1 << 10; 2290bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak private static final int NOT_ENOUGH_NON_LETTER = 1 << 11; 23000d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 23100d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller /** 23217e9e1933055b207473b488595b2887bfcaea32eJim Miller * Keep track internally of where the user is in choosing a pattern. 23300d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller */ 23417e9e1933055b207473b488595b2887bfcaea32eJim Miller protected enum Stage { 23517e9e1933055b207473b488595b2887bfcaea32eJim Miller 23617e9e1933055b207473b488595b2887bfcaea32eJim Miller Introduction(R.string.lockpassword_choose_your_password_header, 23717e9e1933055b207473b488595b2887bfcaea32eJim Miller R.string.lockpassword_choose_your_pin_header, 23817e9e1933055b207473b488595b2887bfcaea32eJim Miller R.string.lockpassword_continue_label), 23917e9e1933055b207473b488595b2887bfcaea32eJim Miller 24017e9e1933055b207473b488595b2887bfcaea32eJim Miller NeedToConfirm(R.string.lockpassword_confirm_your_password_header, 24117e9e1933055b207473b488595b2887bfcaea32eJim Miller R.string.lockpassword_confirm_your_pin_header, 24217e9e1933055b207473b488595b2887bfcaea32eJim Miller R.string.lockpassword_ok_label), 24317e9e1933055b207473b488595b2887bfcaea32eJim Miller 24417e9e1933055b207473b488595b2887bfcaea32eJim Miller ConfirmWrong(R.string.lockpassword_confirm_passwords_dont_match, 24517e9e1933055b207473b488595b2887bfcaea32eJim Miller R.string.lockpassword_confirm_pins_dont_match, 24617e9e1933055b207473b488595b2887bfcaea32eJim Miller R.string.lockpassword_continue_label); 24717e9e1933055b207473b488595b2887bfcaea32eJim Miller 24817e9e1933055b207473b488595b2887bfcaea32eJim Miller Stage(int hintInAlpha, int hintInNumeric, int nextButtonText) { 24917e9e1933055b207473b488595b2887bfcaea32eJim Miller this.alphaHint = hintInAlpha; 25017e9e1933055b207473b488595b2887bfcaea32eJim Miller this.numericHint = hintInNumeric; 25117e9e1933055b207473b488595b2887bfcaea32eJim Miller this.buttonText = nextButtonText; 25217e9e1933055b207473b488595b2887bfcaea32eJim Miller } 25317e9e1933055b207473b488595b2887bfcaea32eJim Miller 25417e9e1933055b207473b488595b2887bfcaea32eJim Miller public final int alphaHint; 25517e9e1933055b207473b488595b2887bfcaea32eJim Miller public final int numericHint; 25617e9e1933055b207473b488595b2887bfcaea32eJim Miller public final int buttonText; 25700d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 25800d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 25917e9e1933055b207473b488595b2887bfcaea32eJim Miller // required constructor for fragments 26017e9e1933055b207473b488595b2887bfcaea32eJim Miller public ChooseLockPasswordFragment() { 26100d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 26200d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 26300d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 26417e9e1933055b207473b488595b2887bfcaea32eJim Miller @Override 26517e9e1933055b207473b488595b2887bfcaea32eJim Miller public void onCreate(Bundle savedInstanceState) { 26617e9e1933055b207473b488595b2887bfcaea32eJim Miller super.onCreate(savedInstanceState); 26717e9e1933055b207473b488595b2887bfcaea32eJim Miller mLockPatternUtils = new LockPatternUtils(getActivity()); 26817e9e1933055b207473b488595b2887bfcaea32eJim Miller Intent intent = getActivity().getIntent(); 26966026773bbf1d7631743a5b892a4f768c694f868Amith Yamasani if (!(getActivity() instanceof ChooseLockPassword)) { 27066026773bbf1d7631743a5b892a4f768c694f868Amith Yamasani throw new SecurityException("Fragment contained in wrong activity"); 27166026773bbf1d7631743a5b892a4f768c694f868Amith Yamasani } 272fe432e838e5588cd4ac664d7e74f3d70a99d7df1Clara Bayarri // Only take this argument into account if it belongs to the current profile. 273194300dff340d67255d12762ffb376b7ba201c87Benjamin Franz mUserId = Utils.getUserIdFromBundle(getActivity(), intent.getExtras()); 2740bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak processPasswordRequirements(intent); 27517e9e1933055b207473b488595b2887bfcaea32eJim Miller mChooseLockSettingsHelper = new ChooseLockSettingsHelper(getActivity()); 27692779ce70156031f4fa3b8c2d84305f5b3b44105Udam Saini mHideDrawer = getActivity().getIntent().getBooleanExtra(EXTRA_HIDE_DRAWER, false); 27762775bf756a8eca9423bb4fab3fc7b71ab22d1a7Adrian Roos 27862775bf756a8eca9423bb4fab3fc7b71ab22d1a7Adrian Roos if (intent.getBooleanExtra( 27962775bf756a8eca9423bb4fab3fc7b71ab22d1a7Adrian Roos ChooseLockSettingsHelper.EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT, false)) { 28062775bf756a8eca9423bb4fab3fc7b71ab22d1a7Adrian Roos SaveAndFinishWorker w = new SaveAndFinishWorker(); 28162775bf756a8eca9423bb4fab3fc7b71ab22d1a7Adrian Roos final boolean required = getActivity().getIntent().getBooleanExtra( 28262775bf756a8eca9423bb4fab3fc7b71ab22d1a7Adrian Roos EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true); 28362775bf756a8eca9423bb4fab3fc7b71ab22d1a7Adrian Roos String current = intent.getStringExtra( 28462775bf756a8eca9423bb4fab3fc7b71ab22d1a7Adrian Roos ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); 28562775bf756a8eca9423bb4fab3fc7b71ab22d1a7Adrian Roos w.setBlocking(true); 28662775bf756a8eca9423bb4fab3fc7b71ab22d1a7Adrian Roos w.setListener(this); 28762775bf756a8eca9423bb4fab3fc7b71ab22d1a7Adrian Roos w.start(mChooseLockSettingsHelper.utils(), required, 28862775bf756a8eca9423bb4fab3fc7b71ab22d1a7Adrian Roos false, 0, current, current, mRequestedQuality, mUserId); 28962775bf756a8eca9423bb4fab3fc7b71ab22d1a7Adrian Roos } 2909ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak mTextChangedHandler = new TextChangedHandler(); 29117e9e1933055b207473b488595b2887bfcaea32eJim Miller } 2922f9dbcb49174d85218dd18e3b2097d3b9fc789c7Jim Miller 29317e9e1933055b207473b488595b2887bfcaea32eJim Miller @Override 29417e9e1933055b207473b488595b2887bfcaea32eJim Miller public View onCreateView(LayoutInflater inflater, ViewGroup container, 29517e9e1933055b207473b488595b2887bfcaea32eJim Miller Bundle savedInstanceState) { 29644f2736f5453ec3bf1fffd3471ecda24da57a094Maurice Lam return inflater.inflate(R.layout.choose_lock_password, container, false); 2976b19fa9017800b94c75238339a337fd8f6c3e808Maurice Lam } 29817e9e1933055b207473b488595b2887bfcaea32eJim Miller 2996b19fa9017800b94c75238339a337fd8f6c3e808Maurice Lam @Override 3006b19fa9017800b94c75238339a337fd8f6c3e808Maurice Lam public void onViewCreated(View view, Bundle savedInstanceState) { 3016b19fa9017800b94c75238339a337fd8f6c3e808Maurice Lam super.onViewCreated(view, savedInstanceState); 30217e9e1933055b207473b488595b2887bfcaea32eJim Miller 30317e9e1933055b207473b488595b2887bfcaea32eJim Miller mCancelButton = (Button) view.findViewById(R.id.cancel_button); 30417e9e1933055b207473b488595b2887bfcaea32eJim Miller mCancelButton.setOnClickListener(this); 30517e9e1933055b207473b488595b2887bfcaea32eJim Miller mNextButton = (Button) view.findViewById(R.id.next_button); 30617e9e1933055b207473b488595b2887bfcaea32eJim Miller mNextButton.setOnClickListener(this); 30717e9e1933055b207473b488595b2887bfcaea32eJim Miller 30817e9e1933055b207473b488595b2887bfcaea32eJim Miller mIsAlphaMode = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == mRequestedQuality 30917e9e1933055b207473b488595b2887bfcaea32eJim Miller || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == mRequestedQuality 31017e9e1933055b207473b488595b2887bfcaea32eJim Miller || DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == mRequestedQuality; 3110bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak 3120bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak setupPasswordRequirementsView(view); 3130bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak 3140bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordRestrictionView.setLayoutManager(new LinearLayoutManager(getActivity())); 3150bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordEntry = (EditText) view.findViewById(R.id.password_entry); 31617e9e1933055b207473b488595b2887bfcaea32eJim Miller mPasswordEntry.setOnEditorActionListener(this); 31717e9e1933055b207473b488595b2887bfcaea32eJim Miller mPasswordEntry.addTextChangedListener(this); 3189c26c9dba6998fda4b3af27e315220b8bec6e0c5Tony Mak mPasswordEntry.requestFocus(); 319f2c2c19339b5d821cb6196911cee04dc9ac647adXiyuan Xia mPasswordEntryInputDisabler = new TextViewInputDisabler(mPasswordEntry); 32017e9e1933055b207473b488595b2887bfcaea32eJim Miller 3219757e30dfa0ab691c4c15366568367e166071a7dJim Miller final Activity activity = getActivity(); 32217e9e1933055b207473b488595b2887bfcaea32eJim Miller mHeaderText = (TextView) view.findViewById(R.id.headerText); 32317e9e1933055b207473b488595b2887bfcaea32eJim Miller 3242e28acedc623527aa5e84ba66635700d6547569aJim Miller int currentType = mPasswordEntry.getInputType(); 3252e28acedc623527aa5e84ba66635700d6547569aJim Miller mPasswordEntry.setInputType(mIsAlphaMode ? currentType 3263b46f49d2a5abb47c1bdf239f855d2063b60595eJim Miller : (InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD)); 3272e28acedc623527aa5e84ba66635700d6547569aJim Miller 32817e9e1933055b207473b488595b2887bfcaea32eJim Miller Intent intent = getActivity().getIntent(); 3296609b0c22ae89a24d1b07dc3c4143452616d4450Andres Morales final boolean confirmCredentials = intent.getBooleanExtra( 3306609b0c22ae89a24d1b07dc3c4143452616d4450Andres Morales ChooseLockGeneric.CONFIRM_CREDENTIALS, true); 331a0e1236fa970ea953bfbcc84fcae1f3fb7f189d1Andres Morales mCurrentPassword = intent.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); 3326609b0c22ae89a24d1b07dc3c4143452616d4450Andres Morales mHasChallenge = intent.getBooleanExtra( 3336609b0c22ae89a24d1b07dc3c4143452616d4450Andres Morales ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false); 3346609b0c22ae89a24d1b07dc3c4143452616d4450Andres Morales mChallenge = intent.getLongExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0); 33517e9e1933055b207473b488595b2887bfcaea32eJim Miller if (savedInstanceState == null) { 33617e9e1933055b207473b488595b2887bfcaea32eJim Miller updateStage(Stage.Introduction); 33717e9e1933055b207473b488595b2887bfcaea32eJim Miller if (confirmCredentials) { 33817e9e1933055b207473b488595b2887bfcaea32eJim Miller mChooseLockSettingsHelper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST, 339fe432e838e5588cd4ac664d7e74f3d70a99d7df1Clara Bayarri getString(R.string.unlock_set_unlock_launch_picker_title), true, 340fe432e838e5588cd4ac664d7e74f3d70a99d7df1Clara Bayarri mUserId); 34117e9e1933055b207473b488595b2887bfcaea32eJim Miller } 34217e9e1933055b207473b488595b2887bfcaea32eJim Miller } else { 343a0e1236fa970ea953bfbcc84fcae1f3fb7f189d1Andres Morales // restore from previous state 34417e9e1933055b207473b488595b2887bfcaea32eJim Miller mFirstPin = savedInstanceState.getString(KEY_FIRST_PIN); 34517e9e1933055b207473b488595b2887bfcaea32eJim Miller final String state = savedInstanceState.getString(KEY_UI_STAGE); 34617e9e1933055b207473b488595b2887bfcaea32eJim Miller if (state != null) { 34717e9e1933055b207473b488595b2887bfcaea32eJim Miller mUiStage = Stage.valueOf(state); 34817e9e1933055b207473b488595b2887bfcaea32eJim Miller updateStage(mUiStage); 34917e9e1933055b207473b488595b2887bfcaea32eJim Miller } 350a0e1236fa970ea953bfbcc84fcae1f3fb7f189d1Andres Morales 351a0e1236fa970ea953bfbcc84fcae1f3fb7f189d1Andres Morales if (mCurrentPassword == null) { 352a0e1236fa970ea953bfbcc84fcae1f3fb7f189d1Andres Morales mCurrentPassword = savedInstanceState.getString(KEY_CURRENT_PASSWORD); 353a0e1236fa970ea953bfbcc84fcae1f3fb7f189d1Andres Morales } 3543e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia 3553e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia // Re-attach to the exiting worker if there is one. 3563e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia mSaveAndFinishWorker = (SaveAndFinishWorker) getFragmentManager().findFragmentByTag( 3573e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia FRAGMENT_TAG_SAVE_AND_FINISH); 35817e9e1933055b207473b488595b2887bfcaea32eJim Miller } 3590bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak 3600bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak // Workaround to show one password requirement below EditText when IME is shown. 3610bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak // By adding an inset to the edit text background, we make the EditText occupy more 3620bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak // vertical space, and the keyboard will then avoid hiding it. We have also set 3630bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak // negative margin in the layout below in order to have them show in the correct 3640bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak // position. 3650bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak final int visibleVerticalSpaceBelowPassword = 3660bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak getResources().getDimensionPixelOffset( 3670bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak R.dimen.visible_vertical_space_below_password); 3680bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak InsetDrawable drawable = 3690bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak new InsetDrawable( 3700bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordEntry.getBackground(), 0, 0, 0, visibleVerticalSpaceBelowPassword); 3710bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordEntry.setBackgroundDrawable(drawable); 3720bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak LinearLayout bottomContainer = (LinearLayout) view.findViewById(R.id.bottom_container); 3730bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak LinearLayout.LayoutParams bottomContainerLp = 3740bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak (LinearLayout.LayoutParams) bottomContainer.getLayoutParams(); 3750bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak bottomContainerLp.setMargins(0, -visibleVerticalSpaceBelowPassword, 0, 0); 3760bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak 377263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Meglio if (activity instanceof SettingsActivity) { 378263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Meglio final SettingsActivity sa = (SettingsActivity) activity; 379d75905991c5a1783ca27dc188c2d086f8f13ff94Jim Miller int id = mIsAlphaMode ? R.string.lockpassword_choose_your_password_header 380d75905991c5a1783ca27dc188c2d086f8f13ff94Jim Miller : R.string.lockpassword_choose_your_pin_header; 3819757e30dfa0ab691c4c15366568367e166071a7dJim Miller CharSequence title = getText(id); 382263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Meglio sa.setTitle(title); 38344f2736f5453ec3bf1fffd3471ecda24da57a094Maurice Lam ((GlifLayout) view).setHeaderText(title); 3849757e30dfa0ab691c4c15366568367e166071a7dJim Miller } 38517e9e1933055b207473b488595b2887bfcaea32eJim Miller } 386122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 3870bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak private void setupPasswordRequirementsView(View view) { 3880bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak // Construct passwordRequirements and requirementDescriptions. 3890bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak List<Integer> passwordRequirements = new ArrayList<>(); 3900bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak List<String> requirementDescriptions = new ArrayList<>(); 3910bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak if (mPasswordMinUpperCase > 0) { 3920bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak passwordRequirements.add(MIN_UPPER_LETTERS_IN_PASSWORD); 3930bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak requirementDescriptions.add(getResources().getQuantityString( 3940bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak R.plurals.lockpassword_password_requires_uppercase, mPasswordMinUpperCase, 3950bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordMinUpperCase)); 3960bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 3970bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak if (mPasswordMinLowerCase > 0) { 3980bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak passwordRequirements.add(MIN_LOWER_LETTERS_IN_PASSWORD); 3990bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak requirementDescriptions.add(getResources().getQuantityString( 4000bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak R.plurals.lockpassword_password_requires_lowercase, mPasswordMinLowerCase, 4010bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordMinLowerCase)); 4020bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 4030bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak if (mPasswordMinLetters > 0) { 4049ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak if (mPasswordMinLetters > mPasswordMinUpperCase + mPasswordMinLowerCase) { 4059ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak passwordRequirements.add(MIN_LETTER_IN_PASSWORD); 4069ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak requirementDescriptions.add(getResources().getQuantityString( 4079ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak R.plurals.lockpassword_password_requires_letters, mPasswordMinLetters, 4089ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak mPasswordMinLetters)); 4099ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak } 4100bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 4110bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak if (mPasswordMinNumeric > 0) { 4120bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak passwordRequirements.add(MIN_NUMBER_IN_PASSWORD); 4130bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak requirementDescriptions.add(getResources().getQuantityString( 4140bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak R.plurals.lockpassword_password_requires_numeric, mPasswordMinNumeric, 4150bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordMinNumeric)); 4160bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 4170bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak if (mPasswordMinSymbols > 0) { 4180bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak passwordRequirements.add(MIN_SYMBOLS_IN_PASSWORD); 4190bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak requirementDescriptions.add(getResources().getQuantityString( 4200bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak R.plurals.lockpassword_password_requires_symbols, mPasswordMinSymbols, 4210bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordMinSymbols)); 4220bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 4230bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak if (mPasswordMinNonLetter > 0) { 4249ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak if (mPasswordMinNonLetter > mPasswordMinNumeric + mPasswordMinSymbols) { 4259ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak passwordRequirements.add(MIN_NON_LETTER_IN_PASSWORD); 4269ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak requirementDescriptions.add(getResources().getQuantityString( 4279ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak R.plurals.lockpassword_password_requires_nonletter, mPasswordMinNonLetter, 4289ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak 4299ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak mPasswordMinNonLetter)); 4309ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak } 4310bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 4320bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak // Convert list to array. 4330bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordRequirements = passwordRequirements.stream().mapToInt(i -> i).toArray(); 4340bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordRestrictionView = 4350bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak (RecyclerView) view.findViewById(R.id.password_requirements_view); 4360bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordRestrictionView.setLayoutManager(new LinearLayoutManager(getActivity())); 4370bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordRequirementAdapter = new PasswordRequirementAdapter(); 4380bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordRestrictionView.setAdapter(mPasswordRequirementAdapter); 4390bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 4400bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak 44117e9e1933055b207473b488595b2887bfcaea32eJim Miller @Override 4426507613ebcd22e4691c2af92a5c161bd327db336Fan Zhang public int getMetricsCategory() { 4439d1bfd1e8de6e46137a9571507c03526880d6a46Chris Wren return MetricsEvent.CHOOSE_LOCK_PASSWORD; 4448a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren } 4458a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren 4468a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren @Override 44717e9e1933055b207473b488595b2887bfcaea32eJim Miller public void onResume() { 44817e9e1933055b207473b488595b2887bfcaea32eJim Miller super.onResume(); 449122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller updateStage(mUiStage); 4503e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia if (mSaveAndFinishWorker != null) { 4513e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia mSaveAndFinishWorker.setListener(this); 4523e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia } else { 4539c26c9dba6998fda4b3af27e315220b8bec6e0c5Tony Mak mPasswordEntry.requestFocus(); 4543e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia } 455122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 456122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 45717e9e1933055b207473b488595b2887bfcaea32eJim Miller @Override 458552bc61ae2aaf67fd2f19564ca2ced002e8675e6Amith Yamasani public void onPause() { 4593e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia if (mSaveAndFinishWorker != null) { 4603e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia mSaveAndFinishWorker.setListener(null); 461bf9ac6b4fb6428d0194a5163181b30cccaedb8ebXiyuan Xia } 462552bc61ae2aaf67fd2f19564ca2ced002e8675e6Amith Yamasani super.onPause(); 463552bc61ae2aaf67fd2f19564ca2ced002e8675e6Amith Yamasani } 464552bc61ae2aaf67fd2f19564ca2ced002e8675e6Amith Yamasani 465552bc61ae2aaf67fd2f19564ca2ced002e8675e6Amith Yamasani @Override 46617e9e1933055b207473b488595b2887bfcaea32eJim Miller public void onSaveInstanceState(Bundle outState) { 46717e9e1933055b207473b488595b2887bfcaea32eJim Miller super.onSaveInstanceState(outState); 46817e9e1933055b207473b488595b2887bfcaea32eJim Miller outState.putString(KEY_UI_STAGE, mUiStage.name()); 46917e9e1933055b207473b488595b2887bfcaea32eJim Miller outState.putString(KEY_FIRST_PIN, mFirstPin); 470a0e1236fa970ea953bfbcc84fcae1f3fb7f189d1Andres Morales outState.putString(KEY_CURRENT_PASSWORD, mCurrentPassword); 47100d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 47200d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 47317e9e1933055b207473b488595b2887bfcaea32eJim Miller @Override 47417e9e1933055b207473b488595b2887bfcaea32eJim Miller public void onActivityResult(int requestCode, int resultCode, 47517e9e1933055b207473b488595b2887bfcaea32eJim Miller Intent data) { 47617e9e1933055b207473b488595b2887bfcaea32eJim Miller super.onActivityResult(requestCode, resultCode, data); 47717e9e1933055b207473b488595b2887bfcaea32eJim Miller switch (requestCode) { 47817e9e1933055b207473b488595b2887bfcaea32eJim Miller case CONFIRM_EXISTING_REQUEST: 47917e9e1933055b207473b488595b2887bfcaea32eJim Miller if (resultCode != Activity.RESULT_OK) { 48017e9e1933055b207473b488595b2887bfcaea32eJim Miller getActivity().setResult(RESULT_FINISHED); 48117e9e1933055b207473b488595b2887bfcaea32eJim Miller getActivity().finish(); 482a0e1236fa970ea953bfbcc84fcae1f3fb7f189d1Andres Morales } else { 483a0e1236fa970ea953bfbcc84fcae1f3fb7f189d1Andres Morales mCurrentPassword = data.getStringExtra( 484a0e1236fa970ea953bfbcc84fcae1f3fb7f189d1Andres Morales ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); 48517e9e1933055b207473b488595b2887bfcaea32eJim Miller } 48617e9e1933055b207473b488595b2887bfcaea32eJim Miller break; 48717e9e1933055b207473b488595b2887bfcaea32eJim Miller } 48800d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 48917e9e1933055b207473b488595b2887bfcaea32eJim Miller 490ecd2b7b81fd2faa2f2f3dbe5a169c749321f3d89Maurice Lam protected Intent getRedactionInterstitialIntent(Context context) { 491f6077f4757183ae8b31af0928c895c806241b593Clara Bayarri return RedactionInterstitial.createStartIntent(context, mUserId); 492ecd2b7b81fd2faa2f2f3dbe5a169c749321f3d89Maurice Lam } 493ecd2b7b81fd2faa2f2f3dbe5a169c749321f3d89Maurice Lam 49417e9e1933055b207473b488595b2887bfcaea32eJim Miller protected void updateStage(Stage stage) { 495eef72c39ae83697b1beaa148ec56aced67382fecalanv final Stage previousStage = mUiStage; 49617e9e1933055b207473b488595b2887bfcaea32eJim Miller mUiStage = stage; 49717e9e1933055b207473b488595b2887bfcaea32eJim Miller updateUi(); 498eef72c39ae83697b1beaa148ec56aced67382fecalanv 499eef72c39ae83697b1beaa148ec56aced67382fecalanv // If the stage changed, announce the header for accessibility. This 500eef72c39ae83697b1beaa148ec56aced67382fecalanv // is a no-op when accessibility is disabled. 501eef72c39ae83697b1beaa148ec56aced67382fecalanv if (previousStage != stage) { 502eef72c39ae83697b1beaa148ec56aced67382fecalanv mHeaderText.announceForAccessibility(mHeaderText.getText()); 503eef72c39ae83697b1beaa148ec56aced67382fecalanv } 50400d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 50517e9e1933055b207473b488595b2887bfcaea32eJim Miller 50617e9e1933055b207473b488595b2887bfcaea32eJim Miller /** 5070bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak * Read the requirements from {@link DevicePolicyManager} and intent and aggregate them. 5080bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak * 5090bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak * @param intent the incoming intent 5100bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak */ 5110bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak private void processPasswordRequirements(Intent intent) { 5120bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak final int dpmPasswordQuality = mLockPatternUtils.getRequestedPasswordQuality(mUserId); 5130bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mRequestedQuality = Math.max(intent.getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY, 5140bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mRequestedQuality), dpmPasswordQuality); 5150bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordMinLength = Math.max(Math.max( 5160bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak LockPatternUtils.MIN_LOCK_PASSWORD_SIZE, 5170bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak intent.getIntExtra(PASSWORD_MIN_KEY, mPasswordMinLength)), 5180bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mLockPatternUtils.getRequestedMinimumPasswordLength(mUserId)); 5190bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordMaxLength = intent.getIntExtra(PASSWORD_MAX_KEY, mPasswordMaxLength); 5200bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordMinLetters = Math.max(intent.getIntExtra(PASSWORD_MIN_LETTERS_KEY, 5210bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordMinLetters), mLockPatternUtils.getRequestedPasswordMinimumLetters( 5220bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mUserId)); 5230bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordMinUpperCase = Math.max(intent.getIntExtra(PASSWORD_MIN_UPPERCASE_KEY, 5240bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordMinUpperCase), mLockPatternUtils.getRequestedPasswordMinimumUpperCase( 5250bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mUserId)); 5260bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordMinLowerCase = Math.max(intent.getIntExtra(PASSWORD_MIN_LOWERCASE_KEY, 5270bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordMinLowerCase), mLockPatternUtils.getRequestedPasswordMinimumLowerCase( 5280bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mUserId)); 5290bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordMinNumeric = Math.max(intent.getIntExtra(PASSWORD_MIN_NUMERIC_KEY, 5300bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordMinNumeric), mLockPatternUtils.getRequestedPasswordMinimumNumeric( 5310bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mUserId)); 5320bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordMinSymbols = Math.max(intent.getIntExtra(PASSWORD_MIN_SYMBOLS_KEY, 5330bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordMinSymbols), mLockPatternUtils.getRequestedPasswordMinimumSymbols( 5340bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mUserId)); 5350bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordMinNonLetter = Math.max(intent.getIntExtra(PASSWORD_MIN_NONLETTER_KEY, 5360bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordMinNonLetter), mLockPatternUtils.getRequestedPasswordMinimumNonLetter( 5370bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mUserId)); 5380bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak 5390bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak // Modify the value based on dpm policy. 5400bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak switch (dpmPasswordQuality) { 5410bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak case PASSWORD_QUALITY_ALPHABETIC: 5420bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak if (mPasswordMinLetters == 0) { 5430bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordMinLetters = 1; 5440bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 5450bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak break; 5460bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak case PASSWORD_QUALITY_ALPHANUMERIC: 5470bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak if (mPasswordMinLetters == 0) { 5480bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordMinLetters = 1; 5490bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 5500bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak if (mPasswordMinNumeric == 0) { 5510bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordMinNumeric = 1; 5520bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 5530bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak break; 5540bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak case PASSWORD_QUALITY_COMPLEX: 5550bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak // Reserve all the requirements. 5560bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak break; 5570bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak default: 5580bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordMinNumeric = 0; 5590bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordMinLetters = 0; 5600bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordMinUpperCase = 0; 5610bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordMinLowerCase = 0; 5620bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordMinSymbols = 0; 5630bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordMinNonLetter = 0; 5640bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 5659ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak mPasswordMinLengthToFulfillAllPolicies = getMinLengthToFulfillAllPolicies(); 5660bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 5670bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak 5680bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak /** 5690bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak * Validates PIN and returns the validation result. 5700bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak * 57117e9e1933055b207473b488595b2887bfcaea32eJim Miller * @param password the raw password the user typed in 5720bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak * @return the validation result. 57317e9e1933055b207473b488595b2887bfcaea32eJim Miller */ 5740bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak private int validatePassword(String password) { 5750bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak int errorCode = NO_ERROR; 5760bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak 57717e9e1933055b207473b488595b2887bfcaea32eJim Miller if (password.length() < mPasswordMinLength) { 5789ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak if (mPasswordMinLength > mPasswordMinLengthToFulfillAllPolicies) { 5799ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak errorCode |= TOO_SHORT; 5809ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak } 5810bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } else if (password.length() > mPasswordMaxLength) { 5820bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak errorCode |= TOO_LONG; 5830bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } else { 5840bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak // The length requirements are fulfilled. 5850bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak if (mRequestedQuality == PASSWORD_QUALITY_NUMERIC_COMPLEX) { 5860bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak // Check for repeated characters or sequences (e.g. '1234', '0000', '2468') 58727ca263b7f6cf64f6a789a052a0f737b18a9aef3Andrew Scull final int sequence = PasswordMetrics.maxLengthSequence(password); 58827ca263b7f6cf64f6a789a052a0f737b18a9aef3Andrew Scull if (sequence > PasswordMetrics.MAX_ALLOWED_SEQUENCE) { 5890bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak errorCode |= CONTAIN_SEQUENTIAL_DIGITS; 5900bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 5910bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 5920bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak // Is the password recently used? 5930bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak if (mLockPatternUtils.checkPasswordHistory(password, mUserId)) { 5940bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak errorCode |= RECENTLY_USED; 5950bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 59600d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 5970bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak 59827ca263b7f6cf64f6a789a052a0f737b18a9aef3Andrew Scull // Allow non-control Latin-1 characters only. 59917e9e1933055b207473b488595b2887bfcaea32eJim Miller for (int i = 0; i < password.length(); i++) { 60017e9e1933055b207473b488595b2887bfcaea32eJim Miller char c = password.charAt(i); 6017e7912de4fb44481ded8e17d5ac1d7a1c9a0d184Nick Kralevich if (c < 32 || c > 127) { 6020bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak errorCode |= CONTAIN_INVALID_CHARACTERS; 60327ca263b7f6cf64f6a789a052a0f737b18a9aef3Andrew Scull break; 60417e9e1933055b207473b488595b2887bfcaea32eJim Miller } 60557fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev } 6060bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak 60727ca263b7f6cf64f6a789a052a0f737b18a9aef3Andrew Scull final PasswordMetrics metrics = PasswordMetrics.computeForPassword(password); 60827ca263b7f6cf64f6a789a052a0f737b18a9aef3Andrew Scull 6090bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak // Ensure no non-digits if we are requesting numbers. This shouldn't be possible unless 6100bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak // user finds some way to bring up soft keyboard. 6110bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak if (mRequestedQuality == PASSWORD_QUALITY_NUMERIC 6120bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak || mRequestedQuality == PASSWORD_QUALITY_NUMERIC_COMPLEX) { 61327ca263b7f6cf64f6a789a052a0f737b18a9aef3Andrew Scull if (metrics.letters > 0 || metrics.symbols > 0) { 6140bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak errorCode |= CONTAIN_NON_DIGITS; 61517e9e1933055b207473b488595b2887bfcaea32eJim Miller } 616af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller } 6178fd852e7c2f488650095024aca9c51f8c7ddc3b3Nicolas Prevot 6180bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak // Check the requirements one by one. 6190bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak for (int i = 0; i < mPasswordRequirements.length; i++) { 6200bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak int passwordRestriction = mPasswordRequirements[i]; 6210bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak switch (passwordRestriction) { 6220bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak case MIN_LETTER_IN_PASSWORD: 62327ca263b7f6cf64f6a789a052a0f737b18a9aef3Andrew Scull if (metrics.letters < mPasswordMinLetters) { 6240bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak errorCode |= NOT_ENOUGH_LETTER; 6250bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 6260bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak break; 6270bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak case MIN_UPPER_LETTERS_IN_PASSWORD: 62827ca263b7f6cf64f6a789a052a0f737b18a9aef3Andrew Scull if (metrics.upperCase < mPasswordMinUpperCase) { 6290bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak errorCode |= NOT_ENOUGH_UPPER_CASE; 6300bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 6310bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak break; 6320bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak case MIN_LOWER_LETTERS_IN_PASSWORD: 63327ca263b7f6cf64f6a789a052a0f737b18a9aef3Andrew Scull if (metrics.lowerCase < mPasswordMinLowerCase) { 6340bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak errorCode |= NOT_ENOUGH_LOWER_CASE; 6350bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 6360bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak break; 6370bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak case MIN_SYMBOLS_IN_PASSWORD: 63827ca263b7f6cf64f6a789a052a0f737b18a9aef3Andrew Scull if (metrics.symbols < mPasswordMinSymbols) { 6390bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak errorCode |= NOT_ENOUGH_SYMBOLS; 6400bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 6410bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak break; 6420bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak case MIN_NUMBER_IN_PASSWORD: 64327ca263b7f6cf64f6a789a052a0f737b18a9aef3Andrew Scull if (metrics.numeric < mPasswordMinNumeric) { 6440bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak errorCode |= NOT_ENOUGH_DIGITS; 6450bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 6460bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak break; 6470bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak case MIN_NON_LETTER_IN_PASSWORD: 64827ca263b7f6cf64f6a789a052a0f737b18a9aef3Andrew Scull if (metrics.nonLetter < mPasswordMinNonLetter) { 6490bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak errorCode |= NOT_ENOUGH_NON_LETTER; 6500bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 6510bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak break; 6520bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 6530bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 6540bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak return errorCode; 655122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 65600d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 657cff37ecbdd4a3d8f9b81fc295155bde5fcf8ea0cPaul Lawrence public void handleNext() { 6583e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia if (mSaveAndFinishWorker != null) return; 659cff37ecbdd4a3d8f9b81fc295155bde5fcf8ea0cPaul Lawrence mChosenPassword = mPasswordEntry.getText().toString(); 660cff37ecbdd4a3d8f9b81fc295155bde5fcf8ea0cPaul Lawrence if (TextUtils.isEmpty(mChosenPassword)) { 66117e9e1933055b207473b488595b2887bfcaea32eJim Miller return; 662122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 66317e9e1933055b207473b488595b2887bfcaea32eJim Miller if (mUiStage == Stage.Introduction) { 6640bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak if (validatePassword(mChosenPassword) == NO_ERROR) { 665cff37ecbdd4a3d8f9b81fc295155bde5fcf8ea0cPaul Lawrence mFirstPin = mChosenPassword; 66617e9e1933055b207473b488595b2887bfcaea32eJim Miller mPasswordEntry.setText(""); 667eef72c39ae83697b1beaa148ec56aced67382fecalanv updateStage(Stage.NeedToConfirm); 66817e9e1933055b207473b488595b2887bfcaea32eJim Miller } 66917e9e1933055b207473b488595b2887bfcaea32eJim Miller } else if (mUiStage == Stage.NeedToConfirm) { 670cff37ecbdd4a3d8f9b81fc295155bde5fcf8ea0cPaul Lawrence if (mFirstPin.equals(mChosenPassword)) { 6713e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia startSaveAndFinish(); 67217e9e1933055b207473b488595b2887bfcaea32eJim Miller } else { 67317e9e1933055b207473b488595b2887bfcaea32eJim Miller CharSequence tmp = mPasswordEntry.getText(); 67417e9e1933055b207473b488595b2887bfcaea32eJim Miller if (tmp != null) { 67517e9e1933055b207473b488595b2887bfcaea32eJim Miller Selection.setSelection((Spannable) tmp, 0, tmp.length()); 67617e9e1933055b207473b488595b2887bfcaea32eJim Miller } 677eef72c39ae83697b1beaa148ec56aced67382fecalanv updateStage(Stage.ConfirmWrong); 678122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 679122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 680122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 681122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 682af103b4eb476881fb27cfb9b6dc94b3fa5e74f28Maurice Lam protected void setNextEnabled(boolean enabled) { 683af103b4eb476881fb27cfb9b6dc94b3fa5e74f28Maurice Lam mNextButton.setEnabled(enabled); 684af103b4eb476881fb27cfb9b6dc94b3fa5e74f28Maurice Lam } 685af103b4eb476881fb27cfb9b6dc94b3fa5e74f28Maurice Lam 686af103b4eb476881fb27cfb9b6dc94b3fa5e74f28Maurice Lam protected void setNextText(int text) { 687af103b4eb476881fb27cfb9b6dc94b3fa5e74f28Maurice Lam mNextButton.setText(text); 688af103b4eb476881fb27cfb9b6dc94b3fa5e74f28Maurice Lam } 689af103b4eb476881fb27cfb9b6dc94b3fa5e74f28Maurice Lam 69017e9e1933055b207473b488595b2887bfcaea32eJim Miller public void onClick(View v) { 69117e9e1933055b207473b488595b2887bfcaea32eJim Miller switch (v.getId()) { 69217e9e1933055b207473b488595b2887bfcaea32eJim Miller case R.id.next_button: 69317e9e1933055b207473b488595b2887bfcaea32eJim Miller handleNext(); 69417e9e1933055b207473b488595b2887bfcaea32eJim Miller break; 69500d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 69617e9e1933055b207473b488595b2887bfcaea32eJim Miller case R.id.cancel_button: 69717e9e1933055b207473b488595b2887bfcaea32eJim Miller getActivity().finish(); 69817e9e1933055b207473b488595b2887bfcaea32eJim Miller break; 69917e9e1933055b207473b488595b2887bfcaea32eJim Miller } 70000d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller } 70100d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller 70217e9e1933055b207473b488595b2887bfcaea32eJim Miller public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { 70374b1e0a7330af195621ad0965748bee66c46f4b6Jim Miller // Check if this was the result of hitting the enter or "done" key 70474b1e0a7330af195621ad0965748bee66c46f4b6Jim Miller if (actionId == EditorInfo.IME_NULL 70574b1e0a7330af195621ad0965748bee66c46f4b6Jim Miller || actionId == EditorInfo.IME_ACTION_DONE 70674b1e0a7330af195621ad0965748bee66c46f4b6Jim Miller || actionId == EditorInfo.IME_ACTION_NEXT) { 70717e9e1933055b207473b488595b2887bfcaea32eJim Miller handleNext(); 70817e9e1933055b207473b488595b2887bfcaea32eJim Miller return true; 70917e9e1933055b207473b488595b2887bfcaea32eJim Miller } 71017e9e1933055b207473b488595b2887bfcaea32eJim Miller return false; 711122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 712122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 71317e9e1933055b207473b488595b2887bfcaea32eJim Miller /** 7140bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak * @param errorCode error code returned from {@link #validatePassword(String)}. 7150bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak * @return an array of messages describing the error, important messages come first. 7160bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak */ 7170bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak private String[] convertErrorCodeToMessages(int errorCode) { 7180bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak List<String> messages = new ArrayList<>(); 7190bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak if ((errorCode & CONTAIN_INVALID_CHARACTERS) > 0) { 7200bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak messages.add(getString(R.string.lockpassword_illegal_character)); 7210bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 7220bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak if ((errorCode & CONTAIN_NON_DIGITS) > 0) { 7230bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak messages.add(getString(R.string.lockpassword_pin_contains_non_digits)); 7240bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 7250bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak if ((errorCode & NOT_ENOUGH_UPPER_CASE) > 0) { 7260bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak messages.add(getResources().getQuantityString( 7270bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak R.plurals.lockpassword_password_requires_uppercase, mPasswordMinUpperCase, 7280bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordMinUpperCase)); 7290bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 7300bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak if ((errorCode & NOT_ENOUGH_LOWER_CASE) > 0) { 7310bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak messages.add(getResources().getQuantityString( 7320bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak R.plurals.lockpassword_password_requires_lowercase, mPasswordMinLowerCase, 7330bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordMinLowerCase)); 7340bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 7359ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak if ((errorCode & NOT_ENOUGH_LETTER) > 0) { 7369ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak messages.add(getResources().getQuantityString( 7379ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak R.plurals.lockpassword_password_requires_letters, mPasswordMinLetters, 7389ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak mPasswordMinLetters)); 7399ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak } 7400bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak if ((errorCode & NOT_ENOUGH_DIGITS) > 0) { 7410bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak messages.add(getResources().getQuantityString( 7420bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak R.plurals.lockpassword_password_requires_numeric, mPasswordMinNumeric, 7430bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordMinNumeric)); 7440bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 7450bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak if ((errorCode & NOT_ENOUGH_SYMBOLS) > 0) { 7460bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak messages.add(getResources().getQuantityString( 7470bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak R.plurals.lockpassword_password_requires_symbols, mPasswordMinSymbols, 7480bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordMinSymbols)); 7490bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 7500bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak if ((errorCode & NOT_ENOUGH_NON_LETTER) > 0) { 7510bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak messages.add(getResources().getQuantityString( 7520bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak R.plurals.lockpassword_password_requires_nonletter, mPasswordMinNonLetter, 7530bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordMinNonLetter)); 7540bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 7550bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak if ((errorCode & TOO_SHORT) > 0) { 7560bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak messages.add(getString(mIsAlphaMode ? 7570bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak R.string.lockpassword_password_too_short 7580bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak : R.string.lockpassword_pin_too_short, mPasswordMinLength)); 7590bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 7600bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak if ((errorCode & TOO_LONG) > 0) { 7610bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak messages.add(getString(mIsAlphaMode ? 7620bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak R.string.lockpassword_password_too_long 7630bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak : R.string.lockpassword_pin_too_long, mPasswordMaxLength + 1)); 7640bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 7650bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak if ((errorCode & CONTAIN_SEQUENTIAL_DIGITS) > 0) { 7660bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak messages.add(getString(R.string.lockpassword_pin_no_sequential_digits)); 7670bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 7680bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak if ((errorCode & RECENTLY_USED) > 0) { 7690bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak messages.add(getString((mIsAlphaMode) ? R.string.lockpassword_password_recently_used 7700bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak : R.string.lockpassword_pin_recently_used)); 7710bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 7720bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak return messages.toArray(new String[0]); 7730bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 7740bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak 7759ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak private int getMinLengthToFulfillAllPolicies() { 7769ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak final int minLengthForLetters = Math.max(mPasswordMinLetters, 7779ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak mPasswordMinUpperCase + mPasswordMinLowerCase); 7789ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak final int minLengthForNonLetters = Math.max(mPasswordMinNonLetter, 7799ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak mPasswordMinSymbols + mPasswordMinNumeric); 7809ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak return minLengthForLetters + minLengthForNonLetters; 7819ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak } 7829ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak 7830bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak /** 78417e9e1933055b207473b488595b2887bfcaea32eJim Miller * Update the hint based on current Stage and length of password entry 78517e9e1933055b207473b488595b2887bfcaea32eJim Miller */ 78617e9e1933055b207473b488595b2887bfcaea32eJim Miller private void updateUi() { 7873e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia final boolean canInput = mSaveAndFinishWorker == null; 78817e9e1933055b207473b488595b2887bfcaea32eJim Miller String password = mPasswordEntry.getText().toString(); 78917e9e1933055b207473b488595b2887bfcaea32eJim Miller final int length = password.length(); 790163dee9fb78ef7c86929b250d150fa989484c2c7Maurice Lam if (mUiStage == Stage.Introduction) { 7910bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordRestrictionView.setVisibility(View.VISIBLE); 7920bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak final int errorCode = validatePassword(password); 7930bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak String[] messages = convertErrorCodeToMessages(errorCode); 7940bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak // Update the fulfillment of requirements. 7950bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordRequirementAdapter.setRequirements(messages); 7960bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak // Enable/Disable the next button accordingly. 7970bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak setNextEnabled(errorCode == NO_ERROR); 79817e9e1933055b207473b488595b2887bfcaea32eJim Miller } else { 7990bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak // Hide password requirement view when we are just asking user to confirm the pw. 8000bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mPasswordRestrictionView.setVisibility(View.GONE); 8010bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak setHeaderText(getString( 8020bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mIsAlphaMode ? mUiStage.alphaHint : mUiStage.numericHint)); 8033e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia setNextEnabled(canInput && length > 0); 804122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 805af103b4eb476881fb27cfb9b6dc94b3fa5e74f28Maurice Lam setNextText(mUiStage.buttonText); 8063e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia mPasswordEntryInputDisabler.setInputEnabled(canInput); 807122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 808122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 8090bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak private void setHeaderText(String text) { 8100bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak // Only set the text if it is different than the existing one to avoid announcing again. 8110bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak if (!TextUtils.isEmpty(mHeaderText.getText()) 8120bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak && mHeaderText.getText().toString().equals(text)) { 8130bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak return; 8140bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 8150bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak mHeaderText.setText(text); 8160bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak } 8170bbcdccdbfa1f8473eb1c14e275c7de6dd43b4d4Tony Mak 81817e9e1933055b207473b488595b2887bfcaea32eJim Miller public void afterTextChanged(Editable s) { 81917e9e1933055b207473b488595b2887bfcaea32eJim Miller // Changing the text while error displayed resets to NeedToConfirm state 82017e9e1933055b207473b488595b2887bfcaea32eJim Miller if (mUiStage == Stage.ConfirmWrong) { 82117e9e1933055b207473b488595b2887bfcaea32eJim Miller mUiStage = Stage.NeedToConfirm; 82217e9e1933055b207473b488595b2887bfcaea32eJim Miller } 8239ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak // Schedule the UI update. 8249ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak mTextChangedHandler.notifyAfterTextChanged(); 825122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 826122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 82717e9e1933055b207473b488595b2887bfcaea32eJim Miller public void beforeTextChanged(CharSequence s, int start, int count, int after) { 828122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 82917e9e1933055b207473b488595b2887bfcaea32eJim Miller } 830122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 83117e9e1933055b207473b488595b2887bfcaea32eJim Miller public void onTextChanged(CharSequence s, int start, int before, int count) { 832122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller 83317e9e1933055b207473b488595b2887bfcaea32eJim Miller } 8343e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia 8353e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia private void startSaveAndFinish() { 8363e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia if (mSaveAndFinishWorker != null) { 8373e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia Log.w(TAG, "startSaveAndFinish with an existing SaveAndFinishWorker."); 8383e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia return; 8393e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia } 8403e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia 8413e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia mPasswordEntryInputDisabler.setInputEnabled(false); 8423e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia setNextEnabled(false); 8433e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia 8443e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia mSaveAndFinishWorker = new SaveAndFinishWorker(); 8455bb1e4fb909a5f0e0574d3572ea1edcf32a2190fRobin Lee mSaveAndFinishWorker.setListener(this); 8465bb1e4fb909a5f0e0574d3572ea1edcf32a2190fRobin Lee 8473e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia getFragmentManager().beginTransaction().add(mSaveAndFinishWorker, 8483e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia FRAGMENT_TAG_SAVE_AND_FINISH).commit(); 8495bb1e4fb909a5f0e0574d3572ea1edcf32a2190fRobin Lee getFragmentManager().executePendingTransactions(); 8503e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia 8513e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia final boolean required = getActivity().getIntent().getBooleanExtra( 8523e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true); 8533e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia mSaveAndFinishWorker.start(mLockPatternUtils, required, mHasChallenge, mChallenge, 854fe432e838e5588cd4ac664d7e74f3d70a99d7df1Clara Bayarri mChosenPassword, mCurrentPassword, mRequestedQuality, mUserId); 8553e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia } 8563e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia 8573e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia @Override 8583e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia public void onChosenLockSaveFinished(boolean wasSecureBefore, Intent resultData) { 8593e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia getActivity().setResult(RESULT_FINISHED, resultData); 8603e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia 8613e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia if (!wasSecureBefore) { 8623e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia Intent intent = getRedactionInterstitialIntent(getActivity()); 8633e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia if (intent != null) { 86492779ce70156031f4fa3b8c2d84305f5b3b44105Udam Saini intent.putExtra(EXTRA_HIDE_DRAWER, mHideDrawer); 8653e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia startActivity(intent); 8663e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia } 8673e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia } 868686ae494f485a5025dfa456b4f32427b3715c337Udam Saini getActivity().finish(); 8693e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia } 8709ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak 8719ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak class TextChangedHandler extends Handler { 8729ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak private static final int ON_TEXT_CHANGED = 1; 8739ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak private static final int DELAY_IN_MILLISECOND = 100; 8749ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak 8759ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak /** 8769ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak * With the introduction of delay, we batch processing the text changed event to reduce 8779ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak * unnecessary UI updates. 8789ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak */ 8799ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak private void notifyAfterTextChanged() { 8809ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak removeMessages(ON_TEXT_CHANGED); 8819ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak sendEmptyMessageDelayed(ON_TEXT_CHANGED, DELAY_IN_MILLISECOND); 8829ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak } 8839ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak 8849ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak @Override 8859ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak public void handleMessage(Message msg) { 886f958f2e14ee07098543291181113c0afdb3b193fDoris Ling if (getActivity() == null) { 887f958f2e14ee07098543291181113c0afdb3b193fDoris Ling return; 888f958f2e14ee07098543291181113c0afdb3b193fDoris Ling } 8899ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak if (msg.what == ON_TEXT_CHANGED) { 8909ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak updateUi(); 8919ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak } 8929ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak } 8939ba765b875ebeb66d8a870a29a00fe53e9da306dTony Mak } 8943e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia } 8953e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia 89677c4345373bdf6d6543bc06a04abc026ce762dbeClara Bayarri public static class SaveAndFinishWorker extends SaveChosenLockWorkerBase { 8973e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia 8983e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia private String mChosenPassword; 8993e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia private String mCurrentPassword; 9003e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia private int mRequestedQuality; 9013e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia 9023e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia public void start(LockPatternUtils utils, boolean required, 9033e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia boolean hasChallenge, long challenge, 904fe432e838e5588cd4ac664d7e74f3d70a99d7df1Clara Bayarri String chosenPassword, String currentPassword, int requestedQuality, int userId) { 905b8a22e42d42e6de8fce1a2026c112c12fd0f0f7aClara Bayarri prepare(utils, required, hasChallenge, challenge, userId); 9063e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia 9073e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia mChosenPassword = chosenPassword; 9083e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia mCurrentPassword = currentPassword; 9093e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia mRequestedQuality = requestedQuality; 910fe432e838e5588cd4ac664d7e74f3d70a99d7df1Clara Bayarri mUserId = userId; 9113e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia 9123e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia start(); 9133e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia } 9143e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia 9153e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia @Override 9163e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia protected Intent saveAndVerifyInBackground() { 9173e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia Intent result = null; 9183e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia mUtils.saveLockPassword(mChosenPassword, mCurrentPassword, mRequestedQuality, 919fe432e838e5588cd4ac664d7e74f3d70a99d7df1Clara Bayarri mUserId); 9203e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia 9213e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia if (mHasChallenge) { 9223e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia byte[] token; 9233e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia try { 924fe432e838e5588cd4ac664d7e74f3d70a99d7df1Clara Bayarri token = mUtils.verifyPassword(mChosenPassword, mChallenge, mUserId); 9253e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia } catch (RequestThrottledException e) { 9263e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia token = null; 9273e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia } 9283e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia 9293e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia if (token == null) { 9303e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia Log.e(TAG, "critical: no token returned for known good password."); 9313e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia } 9323e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia 9333e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia result = new Intent(); 9343e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia result.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token); 9353e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia } 9363e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia 9373e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia return result; 9383e7e3d6c594018e4bc7fc77acc19e148d8bf1bddXiyuan Xia } 939122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller } 94000d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller} 941