1 /* 2 * Copyright (C) 2014 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 17 package com.android.keyguard; 18 19 import android.content.Context; 20 import android.graphics.Rect; 21 import android.util.AttributeSet; 22 import android.view.KeyEvent; 23 import android.view.View; 24 25 /** 26 * A Pin based Keyguard input view 27 */ 28 public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView 29 implements View.OnKeyListener { 30 31 protected PasswordTextView mPasswordEntry; 32 private View mOkButton; 33 private View mDeleteButton; 34 private View mButton0; 35 private View mButton1; 36 private View mButton2; 37 private View mButton3; 38 private View mButton4; 39 private View mButton5; 40 private View mButton6; 41 private View mButton7; 42 private View mButton8; 43 private View mButton9; 44 45 public KeyguardPinBasedInputView(Context context) { 46 this(context, null); 47 } 48 49 public KeyguardPinBasedInputView(Context context, AttributeSet attrs) { 50 super(context, attrs); 51 } 52 53 @Override 54 public void reset() { 55 mPasswordEntry.requestFocus(); 56 super.reset(); 57 } 58 59 @Override 60 protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) { 61 // send focus to the password field 62 return mPasswordEntry.requestFocus(direction, previouslyFocusedRect); 63 } 64 65 @Override 66 protected void resetState() { 67 setPasswordEntryEnabled(true); 68 } 69 70 @Override 71 protected void setPasswordEntryEnabled(boolean enabled) { 72 mPasswordEntry.setEnabled(enabled); 73 mOkButton.setEnabled(enabled); 74 } 75 76 @Override 77 protected void setPasswordEntryInputEnabled(boolean enabled) { 78 mPasswordEntry.setEnabled(enabled); 79 mOkButton.setEnabled(enabled); 80 } 81 82 @Override 83 public boolean onKeyDown(int keyCode, KeyEvent event) { 84 if (KeyEvent.isConfirmKey(keyCode)) { 85 performClick(mOkButton); 86 return true; 87 } else if (keyCode == KeyEvent.KEYCODE_DEL) { 88 performClick(mDeleteButton); 89 return true; 90 } 91 if (keyCode >= KeyEvent.KEYCODE_0 && keyCode <= KeyEvent.KEYCODE_9) { 92 int number = keyCode - KeyEvent.KEYCODE_0; 93 performNumberClick(number); 94 return true; 95 } 96 if (keyCode >= KeyEvent.KEYCODE_NUMPAD_0 && keyCode <= KeyEvent.KEYCODE_NUMPAD_9) { 97 int number = keyCode - KeyEvent.KEYCODE_NUMPAD_0; 98 performNumberClick(number); 99 return true; 100 } 101 return super.onKeyDown(keyCode, event); 102 } 103 104 @Override 105 protected int getPromtReasonStringRes(int reason) { 106 switch (reason) { 107 case PROMPT_REASON_RESTART: 108 return R.string.kg_prompt_reason_restart_pin; 109 case PROMPT_REASON_TIMEOUT: 110 return R.string.kg_prompt_reason_timeout_pin; 111 case PROMPT_REASON_DEVICE_ADMIN: 112 return R.string.kg_prompt_reason_device_admin; 113 case PROMPT_REASON_USER_REQUEST: 114 return R.string.kg_prompt_reason_user_request; 115 case PROMPT_REASON_NONE: 116 return 0; 117 default: 118 return R.string.kg_prompt_reason_timeout_pin; 119 } 120 } 121 122 private void performClick(View view) { 123 view.performClick(); 124 } 125 126 private void performNumberClick(int number) { 127 switch (number) { 128 case 0: 129 performClick(mButton0); 130 break; 131 case 1: 132 performClick(mButton1); 133 break; 134 case 2: 135 performClick(mButton2); 136 break; 137 case 3: 138 performClick(mButton3); 139 break; 140 case 4: 141 performClick(mButton4); 142 break; 143 case 5: 144 performClick(mButton5); 145 break; 146 case 6: 147 performClick(mButton6); 148 break; 149 case 7: 150 performClick(mButton7); 151 break; 152 case 8: 153 performClick(mButton8); 154 break; 155 case 9: 156 performClick(mButton9); 157 break; 158 } 159 } 160 161 @Override 162 protected void resetPasswordText(boolean animate, boolean announce) { 163 mPasswordEntry.reset(animate, announce); 164 } 165 166 @Override 167 protected String getPasswordText() { 168 return mPasswordEntry.getText(); 169 } 170 171 @Override 172 protected void onFinishInflate() { 173 mPasswordEntry = (PasswordTextView) findViewById(getPasswordTextViewId()); 174 mPasswordEntry.setOnKeyListener(this); 175 176 // Set selected property on so the view can send accessibility events. 177 mPasswordEntry.setSelected(true); 178 179 mPasswordEntry.setUserActivityListener(new PasswordTextView.UserActivityListener() { 180 @Override 181 public void onUserActivity() { 182 onUserInput(); 183 } 184 }); 185 186 mOkButton = findViewById(R.id.key_enter); 187 if (mOkButton != null) { 188 mOkButton.setOnClickListener(new View.OnClickListener() { 189 @Override 190 public void onClick(View v) { 191 doHapticKeyClick(); 192 if (mPasswordEntry.isEnabled()) { 193 verifyPasswordAndUnlock(); 194 } 195 } 196 }); 197 mOkButton.setOnHoverListener(new LiftToActivateListener(getContext())); 198 } 199 200 mDeleteButton = findViewById(R.id.delete_button); 201 mDeleteButton.setVisibility(View.VISIBLE); 202 mDeleteButton.setOnClickListener(new OnClickListener() { 203 @Override 204 public void onClick(View v) { 205 // check for time-based lockouts 206 if (mPasswordEntry.isEnabled()) { 207 mPasswordEntry.deleteLastChar(); 208 } 209 doHapticKeyClick(); 210 } 211 }); 212 mDeleteButton.setOnLongClickListener(new View.OnLongClickListener() { 213 @Override 214 public boolean onLongClick(View v) { 215 // check for time-based lockouts 216 if (mPasswordEntry.isEnabled()) { 217 resetPasswordText(true /* animate */, true /* announce */); 218 } 219 doHapticKeyClick(); 220 return true; 221 } 222 }); 223 224 mButton0 = findViewById(R.id.key0); 225 mButton1 = findViewById(R.id.key1); 226 mButton2 = findViewById(R.id.key2); 227 mButton3 = findViewById(R.id.key3); 228 mButton4 = findViewById(R.id.key4); 229 mButton5 = findViewById(R.id.key5); 230 mButton6 = findViewById(R.id.key6); 231 mButton7 = findViewById(R.id.key7); 232 mButton8 = findViewById(R.id.key8); 233 mButton9 = findViewById(R.id.key9); 234 235 mPasswordEntry.requestFocus(); 236 super.onFinishInflate(); 237 } 238 239 @Override 240 public boolean onKey(View v, int keyCode, KeyEvent event) { 241 if (event.getAction() == KeyEvent.ACTION_DOWN) { 242 return onKeyDown(keyCode, event); 243 } 244 return false; 245 } 246 } 247