KeyguardPasswordView.java revision 25a272a9f6323f6a3513bb522d45e839449878ce
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.internal.policy.impl.keyguard; 18 19import android.app.admin.DevicePolicyManager; 20import android.content.Context; 21import android.content.res.Configuration; 22import android.text.Editable; 23import android.text.InputType; 24import android.text.TextWatcher; 25import android.text.method.DigitsKeyListener; 26import android.text.method.TextKeyListener; 27import android.util.AttributeSet; 28import android.view.View; 29import android.view.inputmethod.InputMethodInfo; 30import android.view.inputmethod.InputMethodManager; 31import android.view.inputmethod.InputMethodSubtype; 32import android.widget.TextView.OnEditorActionListener; 33 34import com.android.internal.R; 35import com.android.internal.widget.PasswordEntryKeyboardHelper; 36import com.android.internal.widget.PasswordEntryKeyboardView; 37 38import java.util.List; 39/** 40 * Displays an alphanumeric (latin-1) key entry for the user to enter 41 * an unlock password 42 */ 43 44public class KeyguardPasswordView extends KeyguardAbsKeyInputView 45 implements KeyguardSecurityView, OnEditorActionListener, TextWatcher { 46 47 private final boolean mShowImeAtScreenOn; 48 49 InputMethodManager mImm; 50 51 public KeyguardPasswordView(Context context) { 52 this(context, null); 53 } 54 55 public KeyguardPasswordView(Context context, AttributeSet attrs) { 56 super(context, attrs); 57 mShowImeAtScreenOn = context.getResources(). 58 getBoolean(R.bool.kg_show_ime_at_screen_on); 59 } 60 61 protected void resetState() { 62 mSecurityMessageDisplay.setMessage(R.string.kg_password_instructions, false); 63 mPasswordEntry.setEnabled(true); 64 } 65 66 @Override 67 protected int getPasswordTextViewId() { 68 return R.id.passwordEntry; 69 } 70 71 @Override 72 public boolean needsInput() { 73 return true; 74 } 75 76 @Override 77 public void onResume(int reason) { 78 super.onResume(reason); 79 mPasswordEntry.requestFocus(); 80 if (reason != KeyguardSecurityView.SCREEN_ON || mShowImeAtScreenOn) { 81 mImm.showSoftInput(mPasswordEntry, InputMethodManager.SHOW_IMPLICIT); 82 } 83 } 84 85 @Override 86 public void onPause() { 87 super.onPause(); 88 mImm.hideSoftInputFromWindow(getWindowToken(), 0); 89 } 90 91 @Override 92 protected void onFinishInflate() { 93 super.onFinishInflate(); 94 95 boolean imeOrDeleteButtonVisible = false; 96 97 mImm = (InputMethodManager) getContext().getSystemService( 98 Context.INPUT_METHOD_SERVICE); 99 100 mPasswordEntry.setKeyListener(TextKeyListener.getInstance()); 101 mPasswordEntry.setInputType(InputType.TYPE_CLASS_TEXT 102 | InputType.TYPE_TEXT_VARIATION_PASSWORD); 103 104 // Poke the wakelock any time the text is selected or modified 105 mPasswordEntry.setOnClickListener(new OnClickListener() { 106 public void onClick(View v) { 107 mCallback.userActivity(0); // TODO: customize timeout for text? 108 } 109 }); 110 111 mPasswordEntry.addTextChangedListener(new TextWatcher() { 112 public void onTextChanged(CharSequence s, int start, int before, int count) { 113 } 114 115 public void beforeTextChanged(CharSequence s, int start, int count, int after) { 116 } 117 118 public void afterTextChanged(Editable s) { 119 if (mCallback != null) { 120 mCallback.userActivity(0); 121 } 122 } 123 }); 124 125 mPasswordEntry.requestFocus(); 126 127 // If there's more than one IME, enable the IME switcher button 128 View switchImeButton = findViewById(R.id.switch_ime_button); 129 if (switchImeButton != null && hasMultipleEnabledIMEsOrSubtypes(mImm, false)) { 130 switchImeButton.setVisibility(View.VISIBLE); 131 imeOrDeleteButtonVisible = true; 132 switchImeButton.setOnClickListener(new OnClickListener() { 133 public void onClick(View v) { 134 mCallback.userActivity(0); // Leave the screen on a bit longer 135 mImm.showInputMethodPicker(); 136 } 137 }); 138 } 139 140 // If no icon is visible, reset the start margin on the password field so the text is 141 // still centered. 142 if (!imeOrDeleteButtonVisible) { 143 android.view.ViewGroup.LayoutParams params = mPasswordEntry.getLayoutParams(); 144 if (params instanceof MarginLayoutParams) { 145 final MarginLayoutParams mlp = (MarginLayoutParams) params; 146 mlp.setMarginStart(0); 147 mPasswordEntry.setLayoutParams(params); 148 } 149 } 150 } 151 152 /** 153 * Method adapted from com.android.inputmethod.latin.Utils 154 * 155 * @param imm The input method manager 156 * @param shouldIncludeAuxiliarySubtypes 157 * @return true if we have multiple IMEs to choose from 158 */ 159 private boolean hasMultipleEnabledIMEsOrSubtypes(InputMethodManager imm, 160 final boolean shouldIncludeAuxiliarySubtypes) { 161 final List<InputMethodInfo> enabledImis = imm.getEnabledInputMethodList(); 162 163 // Number of the filtered IMEs 164 int filteredImisCount = 0; 165 166 for (InputMethodInfo imi : enabledImis) { 167 // We can return true immediately after we find two or more filtered IMEs. 168 if (filteredImisCount > 1) return true; 169 final List<InputMethodSubtype> subtypes = 170 imm.getEnabledInputMethodSubtypeList(imi, true); 171 // IMEs that have no subtypes should be counted. 172 if (subtypes.isEmpty()) { 173 ++filteredImisCount; 174 continue; 175 } 176 177 int auxCount = 0; 178 for (InputMethodSubtype subtype : subtypes) { 179 if (subtype.isAuxiliary()) { 180 ++auxCount; 181 } 182 } 183 final int nonAuxCount = subtypes.size() - auxCount; 184 185 // IMEs that have one or more non-auxiliary subtypes should be counted. 186 // If shouldIncludeAuxiliarySubtypes is true, IMEs that have two or more auxiliary 187 // subtypes should be counted as well. 188 if (nonAuxCount > 0 || (shouldIncludeAuxiliarySubtypes && auxCount > 1)) { 189 ++filteredImisCount; 190 continue; 191 } 192 } 193 194 return filteredImisCount > 1 195 // imm.getEnabledInputMethodSubtypeList(null, false) will return the current IME's enabled 196 // input method subtype (The current IME should be LatinIME.) 197 || imm.getEnabledInputMethodSubtypeList(null, false).size() > 1; 198 } 199 200 @Override 201 public void showUsabilityHint() { 202 } 203 204 @Override 205 public int getWrongPasswordStringId() { 206 return R.string.kg_wrong_password; 207 } 208} 209