blob: 2ae4cc7ba65386fb69255ae1e43bced74cf07638 [file] [log] [blame]
Jim Millerdcb3d842012-08-23 19:18:12 -07001/*
2 * Copyright (C) 2012 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 */
Jim Millerdcb3d842012-08-23 19:18:12 -070016
Jim Miller5ecd8112013-01-09 18:50:26 -080017package com.android.keyguard;
18
19import com.android.internal.telephony.ITelephony;
20
21import android.content.Context;
Jim Millerdcb3d842012-08-23 19:18:12 -070022import android.app.Activity;
23import android.app.Dialog;
24import android.app.ProgressDialog;
Jim Millerdcb3d842012-08-23 19:18:12 -070025import android.os.RemoteException;
26import android.os.ServiceManager;
27import android.text.Editable;
Daniel Sandler23d7a6e2012-11-02 00:21:07 -040028import android.text.InputType;
Jim Miller9cf2c522012-10-04 22:02:29 -070029import android.text.TextWatcher;
Daniel Sandler23d7a6e2012-11-02 00:21:07 -040030import android.text.method.DigitsKeyListener;
Jim Millerdcb3d842012-08-23 19:18:12 -070031import android.util.AttributeSet;
Jim Millerdcb3d842012-08-23 19:18:12 -070032import android.view.View;
33import android.view.WindowManager;
Jim Millerdcb3d842012-08-23 19:18:12 -070034import android.widget.TextView.OnEditorActionListener;
35
Daniel Sandler23d7a6e2012-11-02 00:21:07 -040036/**
37 * Displays a PIN pad for entering a PUK (Pin Unlock Kode) provided by a carrier.
38 */
39public class KeyguardSimPukView extends KeyguardAbsKeyInputView
40 implements KeyguardSecurityView, OnEditorActionListener, TextWatcher {
Jim Millerdcb3d842012-08-23 19:18:12 -070041
42 private ProgressDialog mSimUnlockProgressDialog = null;
Jim Miller4b09dd32012-09-04 14:27:25 -070043 private volatile boolean mCheckInProgress;
Jim Miller3efe1062012-09-28 16:59:31 -070044 private String mPukText;
Jim Miller3efe1062012-09-28 16:59:31 -070045 private String mPinText;
46 private StateMachine mStateMachine = new StateMachine();
47
48 private class StateMachine {
49 final int ENTER_PUK = 0;
50 final int ENTER_PIN = 1;
51 final int CONFIRM_PIN = 2;
52 final int DONE = 3;
53 private int state = ENTER_PUK;
54
55 public void next() {
56 int msg = 0;
57 if (state == ENTER_PUK) {
58 if (checkPuk()) {
59 state = ENTER_PIN;
60 msg = R.string.kg_puk_enter_pin_hint;
61 } else {
62 msg = R.string.kg_invalid_sim_puk_hint;
63 }
64 } else if (state == ENTER_PIN) {
65 if (checkPin()) {
66 state = CONFIRM_PIN;
67 msg = R.string.kg_enter_confirm_pin_hint;
68 } else {
69 msg = R.string.kg_invalid_sim_pin_hint;
70 }
71 } else if (state == CONFIRM_PIN) {
72 if (confirmPin()) {
73 state = DONE;
Jim Miller5ecd8112013-01-09 18:50:26 -080074 msg = R.string.keyguard_sim_unlock_progress_dialog_message;
Jim Miller3efe1062012-09-28 16:59:31 -070075 updateSim();
76 } else {
Daniel Sandler23d7a6e2012-11-02 00:21:07 -040077 state = ENTER_PIN; // try again?
Jim Miller3efe1062012-09-28 16:59:31 -070078 msg = R.string.kg_invalid_confirm_pin_hint;
79 }
80 }
Daniel Sandler23d7a6e2012-11-02 00:21:07 -040081 mPasswordEntry.setText(null);
Jim Miller3efe1062012-09-28 16:59:31 -070082 if (msg != 0) {
Adam Cohen0a4f9002012-10-12 19:57:16 -070083 mSecurityMessageDisplay.setMessage(msg, true);
Jim Miller3efe1062012-09-28 16:59:31 -070084 }
85 }
86
87 void reset() {
88 mPinText="";
89 mPukText="";
90 state = ENTER_PUK;
Adam Cohen6dbf8612012-10-14 17:26:31 -070091 mSecurityMessageDisplay.setMessage(R.string.kg_puk_enter_puk_hint, true);
Daniel Sandler23d7a6e2012-11-02 00:21:07 -040092 mPasswordEntry.requestFocus();
Jim Miller3efe1062012-09-28 16:59:31 -070093 }
94 }
95
Jim Millerdcb3d842012-08-23 19:18:12 -070096 public KeyguardSimPukView(Context context) {
97 this(context, null);
98 }
99
100 public KeyguardSimPukView(Context context, AttributeSet attrs) {
101 super(context, attrs);
Jim Millerdcb3d842012-08-23 19:18:12 -0700102 }
103
Daniel Sandler23d7a6e2012-11-02 00:21:07 -0400104 public void resetState() {
105 mStateMachine.reset();
106 mPasswordEntry.setEnabled(true);
107 }
108
109 @Override
Jim Miller7d5e00a2013-10-11 22:45:57 -0700110 protected boolean shouldLockout(long deadline) {
111 // SIM PUK doesn't have a timed lockout
112 return false;
113 }
114
115 @Override
Daniel Sandler23d7a6e2012-11-02 00:21:07 -0400116 protected int getPasswordTextViewId() {
117 return R.id.pinEntry;
Jim Millerdcb3d842012-08-23 19:18:12 -0700118 }
119
120 @Override
121 protected void onFinishInflate() {
122 super.onFinishInflate();
Jim Miller0b728242012-10-28 19:42:30 -0700123
Daniel Sandler23d7a6e2012-11-02 00:21:07 -0400124 final View ok = findViewById(R.id.key_enter);
125 if (ok != null) {
126 ok.setOnClickListener(new View.OnClickListener() {
127 @Override
128 public void onClick(View v) {
129 doHapticKeyClick();
130 verifyPasswordAndUnlock();
131 }
132 });
133 }
134
135 // The delete button is of the PIN keyboard itself in some (e.g. tablet) layouts,
136 // not a separate view
137 View pinDelete = findViewById(R.id.delete_button);
138 if (pinDelete != null) {
139 pinDelete.setVisibility(View.VISIBLE);
140 pinDelete.setOnClickListener(new OnClickListener() {
141 public void onClick(View v) {
142 CharSequence str = mPasswordEntry.getText();
143 if (str.length() > 0) {
144 mPasswordEntry.setText(str.subSequence(0, str.length()-1));
145 }
146 doHapticKeyClick();
147 }
148 });
149 pinDelete.setOnLongClickListener(new View.OnLongClickListener() {
150 public boolean onLongClick(View v) {
151 mPasswordEntry.setText("");
152 doHapticKeyClick();
153 return true;
154 }
155 });
156 }
157
158 mPasswordEntry.setKeyListener(DigitsKeyListener.getInstance());
159 mPasswordEntry.setInputType(InputType.TYPE_CLASS_NUMBER
160 | InputType.TYPE_NUMBER_VARIATION_PASSWORD);
161
162 mPasswordEntry.requestFocus();
163
Jim Miller0b728242012-10-28 19:42:30 -0700164 mSecurityMessageDisplay.setTimeout(0); // don't show ownerinfo/charging status by default
Jim Millerdcb3d842012-08-23 19:18:12 -0700165 }
166
Adam Cohen6fb841f2012-10-24 13:15:38 -0700167 @Override
168 public void showUsabilityHint() {
169 }
170
Daniel Sandler23d7a6e2012-11-02 00:21:07 -0400171 @Override
172 public void onPause() {
Jim Millerdcb3d842012-08-23 19:18:12 -0700173 // dismiss the dialog.
174 if (mSimUnlockProgressDialog != null) {
175 mSimUnlockProgressDialog.dismiss();
176 mSimUnlockProgressDialog = null;
177 }
178 }
179
180 /**
181 * Since the IPC can block, we want to run the request in a separate thread
182 * with a callback.
183 */
184 private abstract class CheckSimPuk extends Thread {
185
186 private final String mPin, mPuk;
187
188 protected CheckSimPuk(String puk, String pin) {
189 mPuk = puk;
190 mPin = pin;
191 }
192
193 abstract void onSimLockChangedResponse(boolean success);
194
195 @Override
196 public void run() {
197 try {
198 final boolean result = ITelephony.Stub.asInterface(ServiceManager
199 .checkService("phone")).supplyPuk(mPuk, mPin);
200
201 post(new Runnable() {
202 public void run() {
203 onSimLockChangedResponse(result);
204 }
205 });
206 } catch (RemoteException e) {
207 post(new Runnable() {
208 public void run() {
209 onSimLockChangedResponse(false);
210 }
211 });
212 }
213 }
214 }
215
Jim Millerdcb3d842012-08-23 19:18:12 -0700216 private Dialog getSimUnlockProgressDialog() {
217 if (mSimUnlockProgressDialog == null) {
218 mSimUnlockProgressDialog = new ProgressDialog(mContext);
Daniel Sandler23d7a6e2012-11-02 00:21:07 -0400219 mSimUnlockProgressDialog.setMessage(
220 mContext.getString(R.string.kg_sim_unlock_progress_dialog_message));
Jim Millerdcb3d842012-08-23 19:18:12 -0700221 mSimUnlockProgressDialog.setIndeterminate(true);
222 mSimUnlockProgressDialog.setCancelable(false);
223 if (!(mContext instanceof Activity)) {
224 mSimUnlockProgressDialog.getWindow().setType(
225 WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
226 }
227 }
228 return mSimUnlockProgressDialog;
229 }
230
Jim Miller3efe1062012-09-28 16:59:31 -0700231 private boolean checkPuk() {
Jim Millerdcb3d842012-08-23 19:18:12 -0700232 // make sure the puk is at least 8 digits long.
Daniel Sandler23d7a6e2012-11-02 00:21:07 -0400233 if (mPasswordEntry.getText().length() >= 8) {
234 mPukText = mPasswordEntry.getText().toString();
Jim Miller3efe1062012-09-28 16:59:31 -0700235 return true;
Jim Millerdcb3d842012-08-23 19:18:12 -0700236 }
Jim Miller3efe1062012-09-28 16:59:31 -0700237 return false;
238 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700239
Jim Miller3efe1062012-09-28 16:59:31 -0700240 private boolean checkPin() {
Jim Millerdcb3d842012-08-23 19:18:12 -0700241 // make sure the PIN is between 4 and 8 digits
Daniel Sandler23d7a6e2012-11-02 00:21:07 -0400242 int length = mPasswordEntry.getText().length();
Jim Miller3efe1062012-09-28 16:59:31 -0700243 if (length >= 4 && length <= 8) {
Daniel Sandler23d7a6e2012-11-02 00:21:07 -0400244 mPinText = mPasswordEntry.getText().toString();
Jim Miller3efe1062012-09-28 16:59:31 -0700245 return true;
Jim Millerdcb3d842012-08-23 19:18:12 -0700246 }
Jim Miller3efe1062012-09-28 16:59:31 -0700247 return false;
248 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700249
Jim Miller3efe1062012-09-28 16:59:31 -0700250 public boolean confirmPin() {
Daniel Sandler23d7a6e2012-11-02 00:21:07 -0400251 return mPinText.equals(mPasswordEntry.getText().toString());
Jim Miller3efe1062012-09-28 16:59:31 -0700252 }
253
254 private void updateSim() {
Jim Millerdcb3d842012-08-23 19:18:12 -0700255 getSimUnlockProgressDialog().show();
256
Jim Miller4b09dd32012-09-04 14:27:25 -0700257 if (!mCheckInProgress) {
258 mCheckInProgress = true;
Jim Miller3efe1062012-09-28 16:59:31 -0700259 new CheckSimPuk(mPukText, mPinText) {
Jim Miller4b09dd32012-09-04 14:27:25 -0700260 void onSimLockChangedResponse(final boolean success) {
Jim Miller3efe1062012-09-28 16:59:31 -0700261 post(new Runnable() {
Jim Miller4b09dd32012-09-04 14:27:25 -0700262 public void run() {
263 if (mSimUnlockProgressDialog != null) {
264 mSimUnlockProgressDialog.hide();
265 }
266 if (success) {
267 mCallback.dismiss(true);
268 } else {
Jim Miller3efe1062012-09-28 16:59:31 -0700269 mStateMachine.reset();
Adam Cohen0a4f9002012-10-12 19:57:16 -0700270 mSecurityMessageDisplay.setMessage(R.string.kg_invalid_puk, true);
Jim Miller4b09dd32012-09-04 14:27:25 -0700271 }
272 mCheckInProgress = false;
Jim Millerdcb3d842012-08-23 19:18:12 -0700273 }
Jim Miller4b09dd32012-09-04 14:27:25 -0700274 });
275 }
276 }.start();
277 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700278 }
279
280 @Override
Daniel Sandler23d7a6e2012-11-02 00:21:07 -0400281 protected void verifyPasswordAndUnlock() {
282 mStateMachine.next();
Jim Miller9cf2c522012-10-04 22:02:29 -0700283 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700284}
Daniel Sandler23d7a6e2012-11-02 00:21:07 -0400285
286