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
onKeyDown(int keyCode, KeyEvent event)75     public boolean onKeyDown(int keyCode, KeyEvent event) {
76         if (KeyEvent.isConfirmKey(keyCode)) {
77             performClick(mOkButton);
78             return true;
79         } else if (keyCode == KeyEvent.KEYCODE_DEL) {
80             performClick(mDeleteButton);
81             return true;
82         }
83         if (keyCode >= KeyEvent.KEYCODE_0 && keyCode <= KeyEvent.KEYCODE_9) {
84             int number = keyCode - KeyEvent.KEYCODE_0 ;
85             performNumberClick(number);
86             return true;
87         }
88         return super.onKeyDown(keyCode, event);
89     }
90 
performClick(View view)91     private void performClick(View view) {
92         view.performClick();
93     }
94 
performNumberClick(int number)95     private void performNumberClick(int number) {
96         switch (number) {
97             case 0:
98                 performClick(mButton0);
99                 break;
100             case 1:
101                 performClick(mButton1);
102                 break;
103             case 2:
104                 performClick(mButton2);
105                 break;
106             case 3:
107                 performClick(mButton3);
108                 break;
109             case 4:
110                 performClick(mButton4);
111                 break;
112             case 5:
113                 performClick(mButton5);
114                 break;
115             case 6:
116                 performClick(mButton6);
117                 break;
118             case 7:
119                 performClick(mButton7);
120                 break;
121             case 8:
122                 performClick(mButton8);
123                 break;
124             case 9:
125                 performClick(mButton9);
126                 break;
127         }
128     }
129 
130     @Override
resetPasswordText(boolean animate)131     protected void resetPasswordText(boolean animate) {
132         mPasswordEntry.reset(animate);
133     }
134 
135     @Override
getPasswordText()136     protected String getPasswordText() {
137         return mPasswordEntry.getText();
138     }
139 
140     @Override
onFinishInflate()141     protected void onFinishInflate() {
142         mPasswordEntry = (PasswordTextView) findViewById(getPasswordTextViewId());
143         mPasswordEntry.setOnKeyListener(this);
144 
145         // Set selected property on so the view can send accessibility events.
146         mPasswordEntry.setSelected(true);
147 
148         // Poke the wakelock any time the text is selected or modified
149         mPasswordEntry.setOnClickListener(new OnClickListener() {
150             public void onClick(View v) {
151                 mCallback.userActivity();
152             }
153         });
154 
155         mOkButton = findViewById(R.id.key_enter);
156         if (mOkButton != null) {
157             mOkButton.setOnClickListener(new View.OnClickListener() {
158                 @Override
159                 public void onClick(View v) {
160                     doHapticKeyClick();
161                     if (mPasswordEntry.isEnabled()) {
162                         verifyPasswordAndUnlock();
163                     }
164                 }
165             });
166             mOkButton.setOnHoverListener(new LiftToActivateListener(getContext()));
167         }
168 
169         mDeleteButton = findViewById(R.id.delete_button);
170         mDeleteButton.setVisibility(View.VISIBLE);
171         mDeleteButton.setOnClickListener(new OnClickListener() {
172             public void onClick(View v) {
173                 // check for time-based lockouts
174                 if (mPasswordEntry.isEnabled()) {
175                     mPasswordEntry.deleteLastChar();
176                 }
177                 doHapticKeyClick();
178             }
179         });
180         mDeleteButton.setOnLongClickListener(new View.OnLongClickListener() {
181             public boolean onLongClick(View v) {
182                 // check for time-based lockouts
183                 if (mPasswordEntry.isEnabled()) {
184                     resetPasswordText(true /* animate */);
185                 }
186                 doHapticKeyClick();
187                 return true;
188             }
189         });
190 
191         mButton0 = findViewById(R.id.key0);
192         mButton1 = findViewById(R.id.key1);
193         mButton2 = findViewById(R.id.key2);
194         mButton3 = findViewById(R.id.key3);
195         mButton4 = findViewById(R.id.key4);
196         mButton5 = findViewById(R.id.key5);
197         mButton6 = findViewById(R.id.key6);
198         mButton7 = findViewById(R.id.key7);
199         mButton8 = findViewById(R.id.key8);
200         mButton9 = findViewById(R.id.key9);
201 
202         mPasswordEntry.requestFocus();
203         super.onFinishInflate();
204     }
205 
206     @Override
onKey(View v, int keyCode, KeyEvent event)207     public boolean onKey(View v, int keyCode, KeyEvent event) {
208         if (event.getAction() == KeyEvent.ACTION_DOWN) {
209             onKeyDown(keyCode, event);
210             return true;
211         }
212         return false;
213     }
214 }
215