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 
KeyguardPinBasedInputView(Context context)45     public KeyguardPinBasedInputView(Context context) {
46         this(context, null);
47     }
48 
KeyguardPinBasedInputView(Context context, AttributeSet attrs)49     public KeyguardPinBasedInputView(Context context, AttributeSet attrs) {
50         super(context, attrs);
51     }
52 
53     @Override
reset()54     public void reset() {
55         mPasswordEntry.requestFocus();
56         super.reset();
57     }
58 
59     @Override
onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect)60     protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
61         // send focus to the password field
62         return mPasswordEntry.requestFocus(direction, previouslyFocusedRect);
63     }
64 
resetState()65     protected void resetState() {
66         mPasswordEntry.setEnabled(true);
67     }
68 
69     @Override
setPasswordEntryEnabled(boolean enabled)70     protected void setPasswordEntryEnabled(boolean enabled) {
71         mPasswordEntry.setEnabled(enabled);
72     }
73 
74     @Override
setPasswordEntryInputEnabled(boolean enabled)75     protected void setPasswordEntryInputEnabled(boolean enabled) {
76         mPasswordEntry.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         return super.onKeyDown(keyCode, event);
94     }
95 
96     @Override
getPromtReasonStringRes(int reason)97     protected int getPromtReasonStringRes(int reason) {
98         switch (reason) {
99             case PROMPT_REASON_RESTART:
100                 return R.string.kg_prompt_reason_restart_pin;
101             default:
102                 return 0;
103         }
104     }
105 
performClick(View view)106     private void performClick(View view) {
107         view.performClick();
108     }
109 
performNumberClick(int number)110     private void performNumberClick(int number) {
111         switch (number) {
112             case 0:
113                 performClick(mButton0);
114                 break;
115             case 1:
116                 performClick(mButton1);
117                 break;
118             case 2:
119                 performClick(mButton2);
120                 break;
121             case 3:
122                 performClick(mButton3);
123                 break;
124             case 4:
125                 performClick(mButton4);
126                 break;
127             case 5:
128                 performClick(mButton5);
129                 break;
130             case 6:
131                 performClick(mButton6);
132                 break;
133             case 7:
134                 performClick(mButton7);
135                 break;
136             case 8:
137                 performClick(mButton8);
138                 break;
139             case 9:
140                 performClick(mButton9);
141                 break;
142         }
143     }
144 
145     @Override
resetPasswordText(boolean animate)146     protected void resetPasswordText(boolean animate) {
147         mPasswordEntry.reset(animate);
148     }
149 
150     @Override
getPasswordText()151     protected String getPasswordText() {
152         return mPasswordEntry.getText();
153     }
154 
155     @Override
onFinishInflate()156     protected void onFinishInflate() {
157         mPasswordEntry = (PasswordTextView) findViewById(getPasswordTextViewId());
158         mPasswordEntry.setOnKeyListener(this);
159 
160         // Set selected property on so the view can send accessibility events.
161         mPasswordEntry.setSelected(true);
162 
163         mPasswordEntry.setUserActivityListener(new PasswordTextView.UserActivityListener() {
164             @Override
165             public void onUserActivity() {
166                 onUserInput();
167             }
168         });
169 
170         mOkButton = findViewById(R.id.key_enter);
171         if (mOkButton != null) {
172             mOkButton.setOnClickListener(new View.OnClickListener() {
173                 @Override
174                 public void onClick(View v) {
175                     doHapticKeyClick();
176                     if (mPasswordEntry.isEnabled()) {
177                         verifyPasswordAndUnlock();
178                     }
179                 }
180             });
181             mOkButton.setOnHoverListener(new LiftToActivateListener(getContext()));
182         }
183 
184         mDeleteButton = findViewById(R.id.delete_button);
185         mDeleteButton.setVisibility(View.VISIBLE);
186         mDeleteButton.setOnClickListener(new OnClickListener() {
187             public void onClick(View v) {
188                 // check for time-based lockouts
189                 if (mPasswordEntry.isEnabled()) {
190                     mPasswordEntry.deleteLastChar();
191                 }
192                 doHapticKeyClick();
193             }
194         });
195         mDeleteButton.setOnLongClickListener(new View.OnLongClickListener() {
196             public boolean onLongClick(View v) {
197                 // check for time-based lockouts
198                 if (mPasswordEntry.isEnabled()) {
199                     resetPasswordText(true /* animate */);
200                 }
201                 doHapticKeyClick();
202                 return true;
203             }
204         });
205 
206         mButton0 = findViewById(R.id.key0);
207         mButton1 = findViewById(R.id.key1);
208         mButton2 = findViewById(R.id.key2);
209         mButton3 = findViewById(R.id.key3);
210         mButton4 = findViewById(R.id.key4);
211         mButton5 = findViewById(R.id.key5);
212         mButton6 = findViewById(R.id.key6);
213         mButton7 = findViewById(R.id.key7);
214         mButton8 = findViewById(R.id.key8);
215         mButton9 = findViewById(R.id.key9);
216 
217         mPasswordEntry.requestFocus();
218         super.onFinishInflate();
219     }
220 
221     @Override
onKey(View v, int keyCode, KeyEvent event)222     public boolean onKey(View v, int keyCode, KeyEvent event) {
223         if (event.getAction() == KeyEvent.ACTION_DOWN) {
224             onKeyDown(keyCode, event);
225             return true;
226         }
227         return false;
228     }
229 }
230