blob: 7c56e84a464e198865255db9b6d4d2a144d74600 [file] [log] [blame]
Selim Cinek4e8b9ed2014-06-20 16:37:04 -07001/*
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
17package com.android.keyguard;
18
19import android.content.Context;
Selim Cinekc199ef32014-12-09 18:49:42 +010020import android.database.ContentObserver;
Selim Cinek4e8b9ed2014-06-20 16:37:04 -070021import android.graphics.Rect;
Selim Cinekc199ef32014-12-09 18:49:42 +010022import android.os.Handler;
23import android.os.UserHandle;
24import android.provider.Settings;
Selim Cinek4e8b9ed2014-06-20 16:37:04 -070025import android.util.AttributeSet;
26import android.view.KeyEvent;
27import android.view.View;
28
29/**
30 * A Pin based Keyguard input view
31 */
32public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView
33 implements View.OnKeyListener {
34
Selim Cinekc199ef32014-12-09 18:49:42 +010035 private final android.database.ContentObserver mSpeakPasswordObserver
36 = new ContentObserver(new Handler()) {
37 @Override
38 public void onChange(boolean selfChange) {
39 super.onChange(selfChange);
40 // Ensure that it's not called too early
41 if (mButton0 != null) {
42 mButton0.updateContentDescription();
43 mButton1.updateContentDescription();
44 mButton2.updateContentDescription();
45 mButton3.updateContentDescription();
46 mButton4.updateContentDescription();
47 mButton5.updateContentDescription();
48 mButton6.updateContentDescription();
49 mButton7.updateContentDescription();
50 mButton8.updateContentDescription();
51 mButton9.updateContentDescription();
52 }
53 }
54 };
Selim Cinek4e8b9ed2014-06-20 16:37:04 -070055 protected PasswordTextView mPasswordEntry;
56 private View mOkButton;
57 private View mDeleteButton;
Selim Cinekc199ef32014-12-09 18:49:42 +010058 private NumPadKey mButton0;
59 private NumPadKey mButton1;
60 private NumPadKey mButton2;
61 private NumPadKey mButton3;
62 private NumPadKey mButton4;
63 private NumPadKey mButton5;
64 private NumPadKey mButton6;
65 private NumPadKey mButton7;
66 private NumPadKey mButton8;
67 private NumPadKey mButton9;
Selim Cinek4e8b9ed2014-06-20 16:37:04 -070068
69 public KeyguardPinBasedInputView(Context context) {
70 this(context, null);
71 }
72
73 public KeyguardPinBasedInputView(Context context, AttributeSet attrs) {
74 super(context, attrs);
Selim Cinekc199ef32014-12-09 18:49:42 +010075 context.getContentResolver().registerContentObserver(
76 Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD), true,
77 mSpeakPasswordObserver, UserHandle.USER_ALL);
Selim Cinek4e8b9ed2014-06-20 16:37:04 -070078 }
79
80 @Override
81 public void reset() {
82 mPasswordEntry.requestFocus();
83 super.reset();
84 }
85
86 @Override
87 protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
88 // send focus to the password field
89 return mPasswordEntry.requestFocus(direction, previouslyFocusedRect);
90 }
91
92 protected void resetState() {
93 mPasswordEntry.setEnabled(true);
94 }
95
96 @Override
97 protected void setPasswordEntryEnabled(boolean enabled) {
98 mPasswordEntry.setEnabled(enabled);
99 }
100
101 @Override
102 public boolean onKeyDown(int keyCode, KeyEvent event) {
103 if (KeyEvent.isConfirmKey(keyCode)) {
104 performClick(mOkButton);
105 return true;
106 } else if (keyCode == KeyEvent.KEYCODE_DEL) {
107 performClick(mDeleteButton);
108 return true;
109 }
110 if (keyCode >= KeyEvent.KEYCODE_0 && keyCode <= KeyEvent.KEYCODE_9) {
111 int number = keyCode - KeyEvent.KEYCODE_0 ;
112 performNumberClick(number);
113 return true;
114 }
115 return super.onKeyDown(keyCode, event);
116 }
117
118 private void performClick(View view) {
119 view.performClick();
120 }
121
122 private void performNumberClick(int number) {
123 switch (number) {
124 case 0:
125 performClick(mButton0);
126 break;
127 case 1:
128 performClick(mButton1);
129 break;
130 case 2:
131 performClick(mButton2);
132 break;
133 case 3:
134 performClick(mButton3);
135 break;
136 case 4:
137 performClick(mButton4);
138 break;
139 case 5:
140 performClick(mButton5);
141 break;
142 case 6:
143 performClick(mButton6);
144 break;
145 case 7:
146 performClick(mButton7);
147 break;
148 case 8:
149 performClick(mButton8);
150 break;
151 case 9:
152 performClick(mButton9);
153 break;
154 }
155 }
156
157 @Override
158 protected void resetPasswordText(boolean animate) {
159 mPasswordEntry.reset(animate);
160 }
161
162 @Override
163 protected String getPasswordText() {
164 return mPasswordEntry.getText();
165 }
166
167 @Override
168 protected void onFinishInflate() {
169 mPasswordEntry = (PasswordTextView) findViewById(getPasswordTextViewId());
170 mPasswordEntry.setOnKeyListener(this);
171
172 // Set selected property on so the view can send accessibility events.
173 mPasswordEntry.setSelected(true);
174
175 // Poke the wakelock any time the text is selected or modified
176 mPasswordEntry.setOnClickListener(new OnClickListener() {
177 public void onClick(View v) {
Jorim Jaggib690f0d2014-07-03 23:25:44 +0200178 mCallback.userActivity();
Selim Cinek4e8b9ed2014-06-20 16:37:04 -0700179 }
180 });
181
182 mOkButton = findViewById(R.id.key_enter);
183 if (mOkButton != null) {
184 mOkButton.setOnClickListener(new View.OnClickListener() {
185 @Override
186 public void onClick(View v) {
187 doHapticKeyClick();
188 if (mPasswordEntry.isEnabled()) {
189 verifyPasswordAndUnlock();
190 }
191 }
192 });
193 mOkButton.setOnHoverListener(new LiftToActivateListener(getContext()));
194 }
195
Selim Cinek103a6c42014-06-30 21:34:57 +0200196 mDeleteButton = findViewById(R.id.delete_button);
Selim Cinek5b1662d2014-06-30 20:59:02 +0200197 mDeleteButton.setVisibility(View.VISIBLE);
198 mDeleteButton.setOnClickListener(new OnClickListener() {
199 public void onClick(View v) {
200 // check for time-based lockouts
201 if (mPasswordEntry.isEnabled()) {
202 mPasswordEntry.deleteLastChar();
Selim Cinek4e8b9ed2014-06-20 16:37:04 -0700203 }
Selim Cinek5b1662d2014-06-30 20:59:02 +0200204 doHapticKeyClick();
205 }
206 });
207 mDeleteButton.setOnLongClickListener(new View.OnLongClickListener() {
208 public boolean onLongClick(View v) {
209 // check for time-based lockouts
210 if (mPasswordEntry.isEnabled()) {
211 resetPasswordText(true /* animate */);
Selim Cinek4e8b9ed2014-06-20 16:37:04 -0700212 }
Selim Cinek5b1662d2014-06-30 20:59:02 +0200213 doHapticKeyClick();
214 return true;
215 }
216 });
217
Selim Cinekc199ef32014-12-09 18:49:42 +0100218 mButton0 = (NumPadKey) findViewById(R.id.key0);
219 mButton1 = (NumPadKey) findViewById(R.id.key1);
220 mButton2 = (NumPadKey) findViewById(R.id.key2);
221 mButton3 = (NumPadKey) findViewById(R.id.key3);
222 mButton4 = (NumPadKey) findViewById(R.id.key4);
223 mButton5 = (NumPadKey) findViewById(R.id.key5);
224 mButton6 = (NumPadKey) findViewById(R.id.key6);
225 mButton7 = (NumPadKey) findViewById(R.id.key7);
226 mButton8 = (NumPadKey) findViewById(R.id.key8);
227 mButton9 = (NumPadKey) findViewById(R.id.key9);
Selim Cinek4e8b9ed2014-06-20 16:37:04 -0700228
229 mPasswordEntry.requestFocus();
230 super.onFinishInflate();
231 }
232
233 @Override
234 public boolean onKey(View v, int keyCode, KeyEvent event) {
235 if (event.getAction() == KeyEvent.ACTION_DOWN) {
236 onKeyDown(keyCode, event);
237 return true;
238 }
239 return false;
240 }
241}