15e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller/* 2dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller * Copyright (C) 2012 The Android Open Source Project 35e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller * 45e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller * Licensed under the Apache License, Version 2.0 (the "License"); 55e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller * you may not use this file except in compliance with the License. 65e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller * You may obtain a copy of the License at 75e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller * 85e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller * http://www.apache.org/licenses/LICENSE-2.0 95e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller * 105e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller * Unless required by applicable law or agreed to in writing, software 115e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller * distributed under the License is distributed on an "AS IS" BASIS, 125e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller * See the License for the specific language governing permissions and 145e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller * limitations under the License. 155e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller */ 165e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller 175ecd81154fa039961f65bb4e36d18ac555b0d1d6Jim Millerpackage com.android.keyguard; 185e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller 19f7c5d0e46ced3ec3edb6f656acd82900b9ac988cJim Millerimport android.app.admin.DevicePolicyManager; 201254f2f42f7173ef51d0034975ab5cb7d44f8209Michael Jurkaimport android.content.Context; 215475906f53e2d79807548932dfabbf9945143740Jim Millerimport android.content.res.Configuration; 228ecfac1d8c2988c3d5031e78f9edefff6e663fd1Jim Millerimport android.text.Editable; 23da3ae8fba865e4b02016bcb65b87a1fbfa000158Jim Millerimport android.text.InputType; 248ecfac1d8c2988c3d5031e78f9edefff6e663fd1Jim Millerimport android.text.TextWatcher; 258b9dda28c9850b4a68b6958b8d4f751dd64157adJim Millerimport android.text.method.DigitsKeyListener; 268b9dda28c9850b4a68b6958b8d4f751dd64157adJim Millerimport android.text.method.TextKeyListener; 271254f2f42f7173ef51d0034975ab5cb7d44f8209Michael Jurkaimport android.util.AttributeSet; 281254f2f42f7173ef51d0034975ab5cb7d44f8209Michael Jurkaimport android.view.View; 29858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Millerimport android.view.inputmethod.InputMethodInfo; 30858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Millerimport android.view.inputmethod.InputMethodManager; 31858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Millerimport android.view.inputmethod.InputMethodSubtype; 32a781d016108d64b2735740d42b5a7c57eb420406Jim Millerimport android.widget.TextView.OnEditorActionListener; 33a781d016108d64b2735740d42b5a7c57eb420406Jim Miller 34a781d016108d64b2735740d42b5a7c57eb420406Jim Millerimport com.android.internal.widget.PasswordEntryKeyboardHelper; 351254f2f42f7173ef51d0034975ab5cb7d44f8209Michael Jurkaimport com.android.internal.widget.PasswordEntryKeyboardView; 361254f2f42f7173ef51d0034975ab5cb7d44f8209Michael Jurka 371254f2f42f7173ef51d0034975ab5cb7d44f8209Michael Jurkaimport java.util.List; 385e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller/** 392c1ce0564fbd329e9e9ccfca100c69cfc1fd2645Daniel Sandler * Displays an alphanumeric (latin-1) key entry for the user to enter 405e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller * an unlock password 415e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller */ 425e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller 4369bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandlerpublic class KeyguardPasswordView extends KeyguardAbsKeyInputView 449cf2c523d82ec14632fd0db920dcc8909c0f44a5Jim Miller implements KeyguardSecurityView, OnEditorActionListener, TextWatcher { 4569bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler 46a042ac90640c0c3fd3c5349083b86bbfd6319b64Chris Wren private final boolean mShowImeAtScreenOn; 47a042ac90640c0c3fd3c5349083b86bbfd6319b64Chris Wren 482c1ce0564fbd329e9e9ccfca100c69cfc1fd2645Daniel Sandler InputMethodManager mImm; 49ac8f5751f52fa445af641604e476703dd5e89504Jim Miller 50dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller public KeyguardPasswordView(Context context) { 51a042ac90640c0c3fd3c5349083b86bbfd6319b64Chris Wren this(context, null); 52dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 53dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 54dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller public KeyguardPasswordView(Context context, AttributeSet attrs) { 55dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller super(context, attrs); 56a042ac90640c0c3fd3c5349083b86bbfd6319b64Chris Wren mShowImeAtScreenOn = context.getResources(). 57a042ac90640c0c3fd3c5349083b86bbfd6319b64Chris Wren getBoolean(R.bool.kg_show_ime_at_screen_on); 58dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 595475906f53e2d79807548932dfabbf9945143740Jim Miller 6069bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler protected void resetState() { 612c1ce0564fbd329e9e9ccfca100c69cfc1fd2645Daniel Sandler mSecurityMessageDisplay.setMessage(R.string.kg_password_instructions, false); 6208b2b6bfe2550b65c68ad7b4bef8283f1ff17561Jim Miller mPasswordEntry.setEnabled(true); 6308b2b6bfe2550b65c68ad7b4bef8283f1ff17561Jim Miller } 6408b2b6bfe2550b65c68ad7b4bef8283f1ff17561Jim Miller 65dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller @Override 668a26bf5aea45650a14215d398c7d0909fcf80c43Daniel Sandler protected int getPasswordTextViewId() { 678a26bf5aea45650a14215d398c7d0909fcf80c43Daniel Sandler return R.id.passwordEntry; 688a26bf5aea45650a14215d398c7d0909fcf80c43Daniel Sandler } 698a26bf5aea45650a14215d398c7d0909fcf80c43Daniel Sandler 708a26bf5aea45650a14215d398c7d0909fcf80c43Daniel Sandler @Override 7186f9637d7bfdc33ab826cc3bbd740f4bf01be280Jim Miller public boolean needsInput() { 7286f9637d7bfdc33ab826cc3bbd740f4bf01be280Jim Miller return true; 7386f9637d7bfdc33ab826cc3bbd740f4bf01be280Jim Miller } 7486f9637d7bfdc33ab826cc3bbd740f4bf01be280Jim Miller 7586f9637d7bfdc33ab826cc3bbd740f4bf01be280Jim Miller @Override 76a042ac90640c0c3fd3c5349083b86bbfd6319b64Chris Wren public void onResume(int reason) { 77a042ac90640c0c3fd3c5349083b86bbfd6319b64Chris Wren super.onResume(reason); 78fba4d4a7678862a21d5cf7770ca8bfcc79831bf6Daniel Sandler mPasswordEntry.requestFocus(); 79a042ac90640c0c3fd3c5349083b86bbfd6319b64Chris Wren if (reason != KeyguardSecurityView.SCREEN_ON || mShowImeAtScreenOn) { 80a042ac90640c0c3fd3c5349083b86bbfd6319b64Chris Wren mImm.showSoftInput(mPasswordEntry, InputMethodManager.SHOW_IMPLICIT); 81a042ac90640c0c3fd3c5349083b86bbfd6319b64Chris Wren } 822c1ce0564fbd329e9e9ccfca100c69cfc1fd2645Daniel Sandler } 83f7c5d0e46ced3ec3edb6f656acd82900b9ac988cJim Miller 842c1ce0564fbd329e9e9ccfca100c69cfc1fd2645Daniel Sandler @Override 852c1ce0564fbd329e9e9ccfca100c69cfc1fd2645Daniel Sandler public void onPause() { 862c1ce0564fbd329e9e9ccfca100c69cfc1fd2645Daniel Sandler super.onPause(); 872c1ce0564fbd329e9e9ccfca100c69cfc1fd2645Daniel Sandler mImm.hideSoftInputFromWindow(getWindowToken(), 0); 882c1ce0564fbd329e9e9ccfca100c69cfc1fd2645Daniel Sandler } 895e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller 902c1ce0564fbd329e9e9ccfca100c69cfc1fd2645Daniel Sandler @Override 912c1ce0564fbd329e9e9ccfca100c69cfc1fd2645Daniel Sandler protected void onFinishInflate() { 922c1ce0564fbd329e9e9ccfca100c69cfc1fd2645Daniel Sandler super.onFinishInflate(); 93dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 94d9d09451ccec7c551d5f9c2f1417c9c1de2952a6Jim Miller boolean imeOrDeleteButtonVisible = false; 955e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller 962c1ce0564fbd329e9e9ccfca100c69cfc1fd2645Daniel Sandler mImm = (InputMethodManager) getContext().getSystemService( 972c1ce0564fbd329e9e9ccfca100c69cfc1fd2645Daniel Sandler Context.INPUT_METHOD_SERVICE); 982c1ce0564fbd329e9e9ccfca100c69cfc1fd2645Daniel Sandler 992c1ce0564fbd329e9e9ccfca100c69cfc1fd2645Daniel Sandler mPasswordEntry.setKeyListener(TextKeyListener.getInstance()); 1002c1ce0564fbd329e9e9ccfca100c69cfc1fd2645Daniel Sandler mPasswordEntry.setInputType(InputType.TYPE_CLASS_TEXT 1012c1ce0564fbd329e9e9ccfca100c69cfc1fd2645Daniel Sandler | InputType.TYPE_TEXT_VARIATION_PASSWORD); 1028b9dda28c9850b4a68b6958b8d4f751dd64157adJim Miller 1036b05d58018c2806459c121e507c005639b74aee9Jim Miller // Poke the wakelock any time the text is selected or modified 1046b05d58018c2806459c121e507c005639b74aee9Jim Miller mPasswordEntry.setOnClickListener(new OnClickListener() { 1056b05d58018c2806459c121e507c005639b74aee9Jim Miller public void onClick(View v) { 106dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mCallback.userActivity(0); // TODO: customize timeout for text? 1076b05d58018c2806459c121e507c005639b74aee9Jim Miller } 1086b05d58018c2806459c121e507c005639b74aee9Jim Miller }); 109dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 1108ecfac1d8c2988c3d5031e78f9edefff6e663fd1Jim Miller mPasswordEntry.addTextChangedListener(new TextWatcher() { 1118ecfac1d8c2988c3d5031e78f9edefff6e663fd1Jim Miller public void onTextChanged(CharSequence s, int start, int before, int count) { 1128ecfac1d8c2988c3d5031e78f9edefff6e663fd1Jim Miller } 1138ecfac1d8c2988c3d5031e78f9edefff6e663fd1Jim Miller 1148ecfac1d8c2988c3d5031e78f9edefff6e663fd1Jim Miller public void beforeTextChanged(CharSequence s, int start, int count, int after) { 1158ecfac1d8c2988c3d5031e78f9edefff6e663fd1Jim Miller } 1168ecfac1d8c2988c3d5031e78f9edefff6e663fd1Jim Miller 1178ecfac1d8c2988c3d5031e78f9edefff6e663fd1Jim Miller public void afterTextChanged(Editable s) { 118ac8a59d3d3a6ddb32a293e4dfc74fb55a0ea6e82Adam Cohen if (mCallback != null) { 119ac8a59d3d3a6ddb32a293e4dfc74fb55a0ea6e82Adam Cohen mCallback.userActivity(0); 120ac8a59d3d3a6ddb32a293e4dfc74fb55a0ea6e82Adam Cohen } 1218ecfac1d8c2988c3d5031e78f9edefff6e663fd1Jim Miller } 1228ecfac1d8c2988c3d5031e78f9edefff6e663fd1Jim Miller }); 123858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller 12469bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler mPasswordEntry.requestFocus(); 12569bdee7c873c4a2295651efda2d0e79c515acc17Daniel Sandler 126858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller // If there's more than one IME, enable the IME switcher button 127858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller View switchImeButton = findViewById(R.id.switch_ime_button); 1282c1ce0564fbd329e9e9ccfca100c69cfc1fd2645Daniel Sandler if (switchImeButton != null && hasMultipleEnabledIMEsOrSubtypes(mImm, false)) { 129858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller switchImeButton.setVisibility(View.VISIBLE); 130d9d09451ccec7c551d5f9c2f1417c9c1de2952a6Jim Miller imeOrDeleteButtonVisible = true; 131858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller switchImeButton.setOnClickListener(new OnClickListener() { 132858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller public void onClick(View v) { 133dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mCallback.userActivity(0); // Leave the screen on a bit longer 1342c1ce0564fbd329e9e9ccfca100c69cfc1fd2645Daniel Sandler mImm.showInputMethodPicker(); 135858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller } 136858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller }); 137858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller } 138d9d09451ccec7c551d5f9c2f1417c9c1de2952a6Jim Miller 13970bc9f24ce6098a8c82245ac1ce7721d354ecd3dAdam Powell // If no icon is visible, reset the start margin on the password field so the text is 140d9d09451ccec7c551d5f9c2f1417c9c1de2952a6Jim Miller // still centered. 141d9d09451ccec7c551d5f9c2f1417c9c1de2952a6Jim Miller if (!imeOrDeleteButtonVisible) { 142d9d09451ccec7c551d5f9c2f1417c9c1de2952a6Jim Miller android.view.ViewGroup.LayoutParams params = mPasswordEntry.getLayoutParams(); 143d9d09451ccec7c551d5f9c2f1417c9c1de2952a6Jim Miller if (params instanceof MarginLayoutParams) { 14470bc9f24ce6098a8c82245ac1ce7721d354ecd3dAdam Powell final MarginLayoutParams mlp = (MarginLayoutParams) params; 14570bc9f24ce6098a8c82245ac1ce7721d354ecd3dAdam Powell mlp.setMarginStart(0); 146d9d09451ccec7c551d5f9c2f1417c9c1de2952a6Jim Miller mPasswordEntry.setLayoutParams(params); 147d9d09451ccec7c551d5f9c2f1417c9c1de2952a6Jim Miller } 148d9d09451ccec7c551d5f9c2f1417c9c1de2952a6Jim Miller } 149858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller } 150858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller 151858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller /** 152858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller * Method adapted from com.android.inputmethod.latin.Utils 153858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller * 154858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller * @param imm The input method manager 155858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller * @param shouldIncludeAuxiliarySubtypes 156858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller * @return true if we have multiple IMEs to choose from 157858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller */ 158858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller private boolean hasMultipleEnabledIMEsOrSubtypes(InputMethodManager imm, 159858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller final boolean shouldIncludeAuxiliarySubtypes) { 160858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller final List<InputMethodInfo> enabledImis = imm.getEnabledInputMethodList(); 161858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller 162858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller // Number of the filtered IMEs 163858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller int filteredImisCount = 0; 164858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller 165858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller for (InputMethodInfo imi : enabledImis) { 166858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller // We can return true immediately after we find two or more filtered IMEs. 167858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller if (filteredImisCount > 1) return true; 168858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller final List<InputMethodSubtype> subtypes = 169858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller imm.getEnabledInputMethodSubtypeList(imi, true); 170858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller // IMEs that have no subtypes should be counted. 171858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller if (subtypes.isEmpty()) { 172858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller ++filteredImisCount; 173858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller continue; 174858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller } 175858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller 176858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller int auxCount = 0; 177858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller for (InputMethodSubtype subtype : subtypes) { 178858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller if (subtype.isAuxiliary()) { 179858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller ++auxCount; 180858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller } 181858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller } 182858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller final int nonAuxCount = subtypes.size() - auxCount; 183858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller 184858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller // IMEs that have one or more non-auxiliary subtypes should be counted. 185858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller // If shouldIncludeAuxiliarySubtypes is true, IMEs that have two or more auxiliary 186858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller // subtypes should be counted as well. 187858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller if (nonAuxCount > 0 || (shouldIncludeAuxiliarySubtypes && auxCount > 1)) { 188858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller ++filteredImisCount; 189858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller continue; 190858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller } 191858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller } 192858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller 193858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller return filteredImisCount > 1 194858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller // imm.getEnabledInputMethodSubtypeList(null, false) will return the current IME's enabled 195858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller // input method subtype (The current IME should be LatinIME.) 196858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller || imm.getEnabledInputMethodSubtypeList(null, false).size() > 1; 1975e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller } 1986fb841fa219eaae3e87f2fdc05e105d7a1813c42Adam Cohen 1996fb841fa219eaae3e87f2fdc05e105d7a1813c42Adam Cohen @Override 2006fb841fa219eaae3e87f2fdc05e105d7a1813c42Adam Cohen public void showUsabilityHint() { 2016fb841fa219eaae3e87f2fdc05e105d7a1813c42Adam Cohen } 20216d90923149435cc7f565f684d42ecd074712ce5Daniel Sandler 20316d90923149435cc7f565f684d42ecd074712ce5Daniel Sandler @Override 20416d90923149435cc7f565f684d42ecd074712ce5Daniel Sandler public int getWrongPasswordStringId() { 20516d90923149435cc7f565f684d42ecd074712ce5Daniel Sandler return R.string.kg_wrong_password; 20616d90923149435cc7f565f684d42ecd074712ce5Daniel Sandler } 2075e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller} 208