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