blob: 6215d3475bd1763d3e24db157ead71a6dd5169ba [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
Jim Miller5ecd8112013-01-09 18:50:26 -080019import android.content.Context;
Jim Millerdcb3d842012-08-23 19:18:12 -070020import android.app.Activity;
Wink Savilleb896b9f2013-10-23 15:44:26 -070021import android.app.AlertDialog;
Jim Millerdcb3d842012-08-23 19:18:12 -070022import android.app.Dialog;
23import android.app.ProgressDialog;
Jim Millerdcb3d842012-08-23 19:18:12 -070024import android.os.RemoteException;
25import android.os.ServiceManager;
Daniel Sandler23d7a6e2012-11-02 00:21:07 -040026import android.text.InputType;
Jim Miller9cf2c522012-10-04 22:02:29 -070027import android.text.TextWatcher;
Daniel Sandler23d7a6e2012-11-02 00:21:07 -040028import android.text.method.DigitsKeyListener;
Jim Millerdcb3d842012-08-23 19:18:12 -070029import android.util.AttributeSet;
Wink Savilleb896b9f2013-10-23 15:44:26 -070030import android.util.Log;
Jim Millerdcb3d842012-08-23 19:18:12 -070031import android.view.View;
32import android.view.WindowManager;
Jim Millerdcb3d842012-08-23 19:18:12 -070033import android.widget.TextView.OnEditorActionListener;
34
Wink Savilleb896b9f2013-10-23 15:44:26 -070035import com.android.internal.telephony.ITelephony;
36import com.android.internal.telephony.PhoneConstants;
37
38
Daniel Sandler23d7a6e2012-11-02 00:21:07 -040039/**
40 * Displays a PIN pad for entering a PUK (Pin Unlock Kode) provided by a carrier.
41 */
42public class KeyguardSimPukView extends KeyguardAbsKeyInputView
43 implements KeyguardSecurityView, OnEditorActionListener, TextWatcher {
Wink Savilleb896b9f2013-10-23 15:44:26 -070044 private static final String LOG_TAG = "KeyguardSimPukView";
Jorim Jaggi5cf17872014-03-26 18:31:48 +010045 private static final boolean DEBUG = KeyguardConstants.DEBUG;
Jim Miller4fc2b012013-11-04 16:47:48 -080046 public static final String TAG = "KeyguardSimPukView";
Jim Millerdcb3d842012-08-23 19:18:12 -070047
48 private ProgressDialog mSimUnlockProgressDialog = null;
Jim Miller4fc2b012013-11-04 16:47:48 -080049 private CheckSimPuk mCheckSimPukThread;
Jim Miller3efe1062012-09-28 16:59:31 -070050 private String mPukText;
Jim Miller3efe1062012-09-28 16:59:31 -070051 private String mPinText;
52 private StateMachine mStateMachine = new StateMachine();
Wink Savilleb896b9f2013-10-23 15:44:26 -070053 private AlertDialog mRemainingAttemptsDialog;
Jim Miller3efe1062012-09-28 16:59:31 -070054
55 private class StateMachine {
56 final int ENTER_PUK = 0;
57 final int ENTER_PIN = 1;
58 final int CONFIRM_PIN = 2;
59 final int DONE = 3;
60 private int state = ENTER_PUK;
61
62 public void next() {
63 int msg = 0;
64 if (state == ENTER_PUK) {
65 if (checkPuk()) {
66 state = ENTER_PIN;
67 msg = R.string.kg_puk_enter_pin_hint;
68 } else {
69 msg = R.string.kg_invalid_sim_puk_hint;
70 }
71 } else if (state == ENTER_PIN) {
72 if (checkPin()) {
73 state = CONFIRM_PIN;
74 msg = R.string.kg_enter_confirm_pin_hint;
75 } else {
76 msg = R.string.kg_invalid_sim_pin_hint;
77 }
78 } else if (state == CONFIRM_PIN) {
79 if (confirmPin()) {
80 state = DONE;
Jim Miller5ecd8112013-01-09 18:50:26 -080081 msg = R.string.keyguard_sim_unlock_progress_dialog_message;
Jim Miller3efe1062012-09-28 16:59:31 -070082 updateSim();
83 } else {
Daniel Sandler23d7a6e2012-11-02 00:21:07 -040084 state = ENTER_PIN; // try again?
Jim Miller3efe1062012-09-28 16:59:31 -070085 msg = R.string.kg_invalid_confirm_pin_hint;
86 }
87 }
Daniel Sandler23d7a6e2012-11-02 00:21:07 -040088 mPasswordEntry.setText(null);
Jim Miller3efe1062012-09-28 16:59:31 -070089 if (msg != 0) {
Adam Cohen0a4f9002012-10-12 19:57:16 -070090 mSecurityMessageDisplay.setMessage(msg, true);
Jim Miller3efe1062012-09-28 16:59:31 -070091 }
92 }
93
94 void reset() {
95 mPinText="";
96 mPukText="";
97 state = ENTER_PUK;
Adam Cohen6dbf8612012-10-14 17:26:31 -070098 mSecurityMessageDisplay.setMessage(R.string.kg_puk_enter_puk_hint, true);
Daniel Sandler23d7a6e2012-11-02 00:21:07 -040099 mPasswordEntry.requestFocus();
Jim Miller3efe1062012-09-28 16:59:31 -0700100 }
101 }
102
Wink Savilleb896b9f2013-10-23 15:44:26 -0700103 private String getPukPasswordErrorMessage(int attemptsRemaining) {
104 String displayMessage;
105
106 if (attemptsRemaining == 0) {
107 displayMessage = getContext().getString(R.string.kg_password_wrong_puk_code_dead);
108 } else if (attemptsRemaining > 0) {
109 displayMessage = getContext().getResources()
110 .getQuantityString(R.plurals.kg_password_wrong_puk_code, attemptsRemaining,
111 attemptsRemaining);
112 } else {
113 displayMessage = getContext().getString(R.string.kg_password_puk_failed);
114 }
115 if (DEBUG) Log.d(LOG_TAG, "getPukPasswordErrorMessage:"
116 + " attemptsRemaining=" + attemptsRemaining + " displayMessage=" + displayMessage);
117 return displayMessage;
118 }
119
Jim Millerdcb3d842012-08-23 19:18:12 -0700120 public KeyguardSimPukView(Context context) {
121 this(context, null);
122 }
123
124 public KeyguardSimPukView(Context context, AttributeSet attrs) {
125 super(context, attrs);
Jim Millerdcb3d842012-08-23 19:18:12 -0700126 }
127
Daniel Sandler23d7a6e2012-11-02 00:21:07 -0400128 public void resetState() {
129 mStateMachine.reset();
130 mPasswordEntry.setEnabled(true);
131 }
132
133 @Override
Jim Miller7d5e00a2013-10-11 22:45:57 -0700134 protected boolean shouldLockout(long deadline) {
135 // SIM PUK doesn't have a timed lockout
136 return false;
137 }
138
139 @Override
Daniel Sandler23d7a6e2012-11-02 00:21:07 -0400140 protected int getPasswordTextViewId() {
Jorim Jaggifa9189f2014-04-17 20:17:30 +0200141 return R.id.pukEntry;
Jim Millerdcb3d842012-08-23 19:18:12 -0700142 }
143
144 @Override
145 protected void onFinishInflate() {
146 super.onFinishInflate();
Jim Miller0b728242012-10-28 19:42:30 -0700147
Daniel Sandler23d7a6e2012-11-02 00:21:07 -0400148 final View ok = findViewById(R.id.key_enter);
149 if (ok != null) {
150 ok.setOnClickListener(new View.OnClickListener() {
151 @Override
152 public void onClick(View v) {
153 doHapticKeyClick();
154 verifyPasswordAndUnlock();
155 }
156 });
157 }
158
159 // The delete button is of the PIN keyboard itself in some (e.g. tablet) layouts,
160 // not a separate view
161 View pinDelete = findViewById(R.id.delete_button);
162 if (pinDelete != null) {
163 pinDelete.setVisibility(View.VISIBLE);
164 pinDelete.setOnClickListener(new OnClickListener() {
165 public void onClick(View v) {
166 CharSequence str = mPasswordEntry.getText();
167 if (str.length() > 0) {
168 mPasswordEntry.setText(str.subSequence(0, str.length()-1));
169 }
170 doHapticKeyClick();
171 }
172 });
173 pinDelete.setOnLongClickListener(new View.OnLongClickListener() {
174 public boolean onLongClick(View v) {
175 mPasswordEntry.setText("");
176 doHapticKeyClick();
177 return true;
178 }
179 });
180 }
181
182 mPasswordEntry.setKeyListener(DigitsKeyListener.getInstance());
183 mPasswordEntry.setInputType(InputType.TYPE_CLASS_NUMBER
184 | InputType.TYPE_NUMBER_VARIATION_PASSWORD);
185
186 mPasswordEntry.requestFocus();
187
Jim Miller0b728242012-10-28 19:42:30 -0700188 mSecurityMessageDisplay.setTimeout(0); // don't show ownerinfo/charging status by default
Jorim Jaggi40a0b382014-05-27 21:12:27 +0200189 if (mEcaView instanceof EmergencyCarrierArea) {
190 ((EmergencyCarrierArea) mEcaView).setCarrierTextVisible(true);
191 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700192 }
193
Adam Cohen6fb841f2012-10-24 13:15:38 -0700194 @Override
195 public void showUsabilityHint() {
196 }
197
Daniel Sandler23d7a6e2012-11-02 00:21:07 -0400198 @Override
199 public void onPause() {
Jim Millerdcb3d842012-08-23 19:18:12 -0700200 // dismiss the dialog.
201 if (mSimUnlockProgressDialog != null) {
202 mSimUnlockProgressDialog.dismiss();
203 mSimUnlockProgressDialog = null;
204 }
205 }
206
207 /**
208 * Since the IPC can block, we want to run the request in a separate thread
209 * with a callback.
210 */
211 private abstract class CheckSimPuk extends Thread {
212
213 private final String mPin, mPuk;
214
215 protected CheckSimPuk(String puk, String pin) {
216 mPuk = puk;
217 mPin = pin;
218 }
219
Wink Savilleb896b9f2013-10-23 15:44:26 -0700220 abstract void onSimLockChangedResponse(final int result, final int attemptsRemaining);
Jim Millerdcb3d842012-08-23 19:18:12 -0700221
222 @Override
223 public void run() {
224 try {
Jim Miller4fc2b012013-11-04 16:47:48 -0800225 Log.v(TAG, "call supplyPukReportResult()");
Wink Savilleb896b9f2013-10-23 15:44:26 -0700226 final int[] result = ITelephony.Stub.asInterface(ServiceManager
227 .checkService("phone")).supplyPukReportResult(mPuk, mPin);
Jim Miller4fc2b012013-11-04 16:47:48 -0800228 Log.v(TAG, "supplyPukReportResult returned: " + result[0] + " " + result[1]);
Jim Millerdcb3d842012-08-23 19:18:12 -0700229 post(new Runnable() {
230 public void run() {
Wink Savilleb896b9f2013-10-23 15:44:26 -0700231 onSimLockChangedResponse(result[0], result[1]);
Jim Millerdcb3d842012-08-23 19:18:12 -0700232 }
233 });
234 } catch (RemoteException e) {
Jim Miller4fc2b012013-11-04 16:47:48 -0800235 Log.e(TAG, "RemoteException for supplyPukReportResult:", e);
Jim Millerdcb3d842012-08-23 19:18:12 -0700236 post(new Runnable() {
237 public void run() {
Wink Savilleb896b9f2013-10-23 15:44:26 -0700238 onSimLockChangedResponse(PhoneConstants.PIN_GENERAL_FAILURE, -1);
Jim Millerdcb3d842012-08-23 19:18:12 -0700239 }
240 });
241 }
242 }
243 }
244
Jim Millerdcb3d842012-08-23 19:18:12 -0700245 private Dialog getSimUnlockProgressDialog() {
246 if (mSimUnlockProgressDialog == null) {
247 mSimUnlockProgressDialog = new ProgressDialog(mContext);
Daniel Sandler23d7a6e2012-11-02 00:21:07 -0400248 mSimUnlockProgressDialog.setMessage(
249 mContext.getString(R.string.kg_sim_unlock_progress_dialog_message));
Jim Millerdcb3d842012-08-23 19:18:12 -0700250 mSimUnlockProgressDialog.setIndeterminate(true);
251 mSimUnlockProgressDialog.setCancelable(false);
252 if (!(mContext instanceof Activity)) {
253 mSimUnlockProgressDialog.getWindow().setType(
254 WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
255 }
256 }
257 return mSimUnlockProgressDialog;
258 }
259
Wink Savilleb896b9f2013-10-23 15:44:26 -0700260 private Dialog getPukRemainingAttemptsDialog(int remaining) {
261 String msg = getPukPasswordErrorMessage(remaining);
262 if (mRemainingAttemptsDialog == null) {
263 AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
264 builder.setMessage(msg);
265 builder.setCancelable(false);
266 builder.setNeutralButton(R.string.ok, null);
267 mRemainingAttemptsDialog = builder.create();
268 mRemainingAttemptsDialog.getWindow().setType(
269 WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
270 } else {
271 mRemainingAttemptsDialog.setMessage(msg);
272 }
273 return mRemainingAttemptsDialog;
274 }
275
Jim Miller3efe1062012-09-28 16:59:31 -0700276 private boolean checkPuk() {
Jim Millerdcb3d842012-08-23 19:18:12 -0700277 // make sure the puk is at least 8 digits long.
Rakesh Pallerlab8b7bd32014-01-08 15:49:34 +0530278 if (mPasswordEntry.getText().length() == 8) {
Daniel Sandler23d7a6e2012-11-02 00:21:07 -0400279 mPukText = mPasswordEntry.getText().toString();
Jim Miller3efe1062012-09-28 16:59:31 -0700280 return true;
Jim Millerdcb3d842012-08-23 19:18:12 -0700281 }
Jim Miller3efe1062012-09-28 16:59:31 -0700282 return false;
283 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700284
Jim Miller3efe1062012-09-28 16:59:31 -0700285 private boolean checkPin() {
Jim Millerdcb3d842012-08-23 19:18:12 -0700286 // make sure the PIN is between 4 and 8 digits
Daniel Sandler23d7a6e2012-11-02 00:21:07 -0400287 int length = mPasswordEntry.getText().length();
Jim Miller3efe1062012-09-28 16:59:31 -0700288 if (length >= 4 && length <= 8) {
Daniel Sandler23d7a6e2012-11-02 00:21:07 -0400289 mPinText = mPasswordEntry.getText().toString();
Jim Miller3efe1062012-09-28 16:59:31 -0700290 return true;
Jim Millerdcb3d842012-08-23 19:18:12 -0700291 }
Jim Miller3efe1062012-09-28 16:59:31 -0700292 return false;
293 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700294
Jim Miller3efe1062012-09-28 16:59:31 -0700295 public boolean confirmPin() {
Daniel Sandler23d7a6e2012-11-02 00:21:07 -0400296 return mPinText.equals(mPasswordEntry.getText().toString());
Jim Miller3efe1062012-09-28 16:59:31 -0700297 }
298
299 private void updateSim() {
Jim Millerdcb3d842012-08-23 19:18:12 -0700300 getSimUnlockProgressDialog().show();
301
Jim Miller4fc2b012013-11-04 16:47:48 -0800302 if (mCheckSimPukThread == null) {
303 mCheckSimPukThread = new CheckSimPuk(mPukText, mPinText) {
Wink Savilleb896b9f2013-10-23 15:44:26 -0700304 void onSimLockChangedResponse(final int result, final int attemptsRemaining) {
Jim Miller3efe1062012-09-28 16:59:31 -0700305 post(new Runnable() {
Jim Miller4b09dd32012-09-04 14:27:25 -0700306 public void run() {
307 if (mSimUnlockProgressDialog != null) {
308 mSimUnlockProgressDialog.hide();
309 }
Wink Savilleb896b9f2013-10-23 15:44:26 -0700310 if (result == PhoneConstants.PIN_RESULT_SUCCESS) {
311 KeyguardUpdateMonitor.getInstance(getContext()).reportSimUnlocked();
Jim Miller4b09dd32012-09-04 14:27:25 -0700312 mCallback.dismiss(true);
313 } else {
Wink Savilleb896b9f2013-10-23 15:44:26 -0700314 if (result == PhoneConstants.PIN_PASSWORD_INCORRECT) {
315 if (attemptsRemaining <= 2) {
316 // this is getting critical - show dialog
317 getPukRemainingAttemptsDialog(attemptsRemaining).show();
318 } else {
319 // show message
320 mSecurityMessageDisplay.setMessage(
321 getPukPasswordErrorMessage(attemptsRemaining), true);
322 }
323 } else {
324 mSecurityMessageDisplay.setMessage(getContext().getString(
325 R.string.kg_password_puk_failed), true);
326 }
327 if (DEBUG) Log.d(LOG_TAG, "verifyPasswordAndUnlock "
328 + " UpdateSim.onSimCheckResponse: "
329 + " attemptsRemaining=" + attemptsRemaining);
Jim Miller3efe1062012-09-28 16:59:31 -0700330 mStateMachine.reset();
Jim Miller4b09dd32012-09-04 14:27:25 -0700331 }
Jim Miller4fc2b012013-11-04 16:47:48 -0800332 mCheckSimPukThread = null;
Jim Millerdcb3d842012-08-23 19:18:12 -0700333 }
Jim Miller4b09dd32012-09-04 14:27:25 -0700334 });
335 }
Jim Miller4fc2b012013-11-04 16:47:48 -0800336 };
337 mCheckSimPukThread.start();
Jim Miller4b09dd32012-09-04 14:27:25 -0700338 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700339 }
340
341 @Override
Daniel Sandler23d7a6e2012-11-02 00:21:07 -0400342 protected void verifyPasswordAndUnlock() {
343 mStateMachine.next();
Jim Miller9cf2c522012-10-04 22:02:29 -0700344 }
Jorim Jaggic14f8292014-05-27 02:25:45 +0200345
346 @Override
347 public void startAppearAnimation() {
348 // noop.
349 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700350}
Daniel Sandler23d7a6e2012-11-02 00:21:07 -0400351
352