blob: d882eca1315a7a345e220f46a2eb2b03f3a3dd21 [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;
Wink Savilleb896b9f2013-10-23 15:44:26 -070020import android.animation.AnimatorSet.Builder;
Jim Millerdcb3d842012-08-23 19:18:12 -070021import android.app.Activity;
Wink Savilleb896b9f2013-10-23 15:44:26 -070022import android.app.AlertDialog;
Jim Millerdcb3d842012-08-23 19:18:12 -070023import 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;
Wink Savilleb896b9f2013-10-23 15:44:26 -070032import android.util.Log;
Jim Millerdcb3d842012-08-23 19:18:12 -070033import android.view.View;
34import android.view.WindowManager;
Jim Millerdcb3d842012-08-23 19:18:12 -070035import android.widget.TextView.OnEditorActionListener;
36
Wink Savilleb896b9f2013-10-23 15:44:26 -070037import com.android.internal.telephony.ITelephony;
38import com.android.internal.telephony.PhoneConstants;
39
40
Daniel Sandler23d7a6e2012-11-02 00:21:07 -040041/**
42 * Displays a PIN pad for entering a PUK (Pin Unlock Kode) provided by a carrier.
43 */
44public class KeyguardSimPukView extends KeyguardAbsKeyInputView
45 implements KeyguardSecurityView, OnEditorActionListener, TextWatcher {
Wink Savilleb896b9f2013-10-23 15:44:26 -070046 private static final String LOG_TAG = "KeyguardSimPukView";
47 private static final boolean DEBUG = KeyguardViewMediator.DEBUG;
Jim Miller4fc2b012013-11-04 16:47:48 -080048 public static final String TAG = "KeyguardSimPukView";
Jim Millerdcb3d842012-08-23 19:18:12 -070049
50 private ProgressDialog mSimUnlockProgressDialog = null;
Jim Miller4fc2b012013-11-04 16:47:48 -080051 private CheckSimPuk mCheckSimPukThread;
Jim Miller3efe1062012-09-28 16:59:31 -070052 private String mPukText;
Jim Miller3efe1062012-09-28 16:59:31 -070053 private String mPinText;
54 private StateMachine mStateMachine = new StateMachine();
Wink Savilleb896b9f2013-10-23 15:44:26 -070055 private AlertDialog mRemainingAttemptsDialog;
Jim Miller3efe1062012-09-28 16:59:31 -070056
57 private class StateMachine {
58 final int ENTER_PUK = 0;
59 final int ENTER_PIN = 1;
60 final int CONFIRM_PIN = 2;
61 final int DONE = 3;
62 private int state = ENTER_PUK;
63
64 public void next() {
65 int msg = 0;
66 if (state == ENTER_PUK) {
67 if (checkPuk()) {
68 state = ENTER_PIN;
69 msg = R.string.kg_puk_enter_pin_hint;
70 } else {
71 msg = R.string.kg_invalid_sim_puk_hint;
72 }
73 } else if (state == ENTER_PIN) {
74 if (checkPin()) {
75 state = CONFIRM_PIN;
76 msg = R.string.kg_enter_confirm_pin_hint;
77 } else {
78 msg = R.string.kg_invalid_sim_pin_hint;
79 }
80 } else if (state == CONFIRM_PIN) {
81 if (confirmPin()) {
82 state = DONE;
Jim Miller5ecd8112013-01-09 18:50:26 -080083 msg = R.string.keyguard_sim_unlock_progress_dialog_message;
Jim Miller3efe1062012-09-28 16:59:31 -070084 updateSim();
85 } else {
Daniel Sandler23d7a6e2012-11-02 00:21:07 -040086 state = ENTER_PIN; // try again?
Jim Miller3efe1062012-09-28 16:59:31 -070087 msg = R.string.kg_invalid_confirm_pin_hint;
88 }
89 }
Daniel Sandler23d7a6e2012-11-02 00:21:07 -040090 mPasswordEntry.setText(null);
Jim Miller3efe1062012-09-28 16:59:31 -070091 if (msg != 0) {
Adam Cohen0a4f9002012-10-12 19:57:16 -070092 mSecurityMessageDisplay.setMessage(msg, true);
Jim Miller3efe1062012-09-28 16:59:31 -070093 }
94 }
95
96 void reset() {
97 mPinText="";
98 mPukText="";
99 state = ENTER_PUK;
Adam Cohen6dbf8612012-10-14 17:26:31 -0700100 mSecurityMessageDisplay.setMessage(R.string.kg_puk_enter_puk_hint, true);
Daniel Sandler23d7a6e2012-11-02 00:21:07 -0400101 mPasswordEntry.requestFocus();
Jim Miller3efe1062012-09-28 16:59:31 -0700102 }
103 }
104
Wink Savilleb896b9f2013-10-23 15:44:26 -0700105 private String getPukPasswordErrorMessage(int attemptsRemaining) {
106 String displayMessage;
107
108 if (attemptsRemaining == 0) {
109 displayMessage = getContext().getString(R.string.kg_password_wrong_puk_code_dead);
110 } else if (attemptsRemaining > 0) {
111 displayMessage = getContext().getResources()
112 .getQuantityString(R.plurals.kg_password_wrong_puk_code, attemptsRemaining,
113 attemptsRemaining);
114 } else {
115 displayMessage = getContext().getString(R.string.kg_password_puk_failed);
116 }
117 if (DEBUG) Log.d(LOG_TAG, "getPukPasswordErrorMessage:"
118 + " attemptsRemaining=" + attemptsRemaining + " displayMessage=" + displayMessage);
119 return displayMessage;
120 }
121
Jim Millerdcb3d842012-08-23 19:18:12 -0700122 public KeyguardSimPukView(Context context) {
123 this(context, null);
124 }
125
126 public KeyguardSimPukView(Context context, AttributeSet attrs) {
127 super(context, attrs);
Jim Millerdcb3d842012-08-23 19:18:12 -0700128 }
129
Daniel Sandler23d7a6e2012-11-02 00:21:07 -0400130 public void resetState() {
131 mStateMachine.reset();
132 mPasswordEntry.setEnabled(true);
133 }
134
135 @Override
Jim Miller7d5e00a2013-10-11 22:45:57 -0700136 protected boolean shouldLockout(long deadline) {
137 // SIM PUK doesn't have a timed lockout
138 return false;
139 }
140
141 @Override
Daniel Sandler23d7a6e2012-11-02 00:21:07 -0400142 protected int getPasswordTextViewId() {
143 return R.id.pinEntry;
Jim Millerdcb3d842012-08-23 19:18:12 -0700144 }
145
146 @Override
147 protected void onFinishInflate() {
148 super.onFinishInflate();
Jim Miller0b728242012-10-28 19:42:30 -0700149
Daniel Sandler23d7a6e2012-11-02 00:21:07 -0400150 final View ok = findViewById(R.id.key_enter);
151 if (ok != null) {
152 ok.setOnClickListener(new View.OnClickListener() {
153 @Override
154 public void onClick(View v) {
155 doHapticKeyClick();
156 verifyPasswordAndUnlock();
157 }
158 });
159 }
160
161 // The delete button is of the PIN keyboard itself in some (e.g. tablet) layouts,
162 // not a separate view
163 View pinDelete = findViewById(R.id.delete_button);
164 if (pinDelete != null) {
165 pinDelete.setVisibility(View.VISIBLE);
166 pinDelete.setOnClickListener(new OnClickListener() {
167 public void onClick(View v) {
168 CharSequence str = mPasswordEntry.getText();
169 if (str.length() > 0) {
170 mPasswordEntry.setText(str.subSequence(0, str.length()-1));
171 }
172 doHapticKeyClick();
173 }
174 });
175 pinDelete.setOnLongClickListener(new View.OnLongClickListener() {
176 public boolean onLongClick(View v) {
177 mPasswordEntry.setText("");
178 doHapticKeyClick();
179 return true;
180 }
181 });
182 }
183
184 mPasswordEntry.setKeyListener(DigitsKeyListener.getInstance());
185 mPasswordEntry.setInputType(InputType.TYPE_CLASS_NUMBER
186 | InputType.TYPE_NUMBER_VARIATION_PASSWORD);
187
188 mPasswordEntry.requestFocus();
189
Jim Miller0b728242012-10-28 19:42:30 -0700190 mSecurityMessageDisplay.setTimeout(0); // don't show ownerinfo/charging status by default
Jim Millerdcb3d842012-08-23 19:18:12 -0700191 }
192
Adam Cohen6fb841f2012-10-24 13:15:38 -0700193 @Override
194 public void showUsabilityHint() {
195 }
196
Daniel Sandler23d7a6e2012-11-02 00:21:07 -0400197 @Override
198 public void onPause() {
Jim Millerdcb3d842012-08-23 19:18:12 -0700199 // dismiss the dialog.
200 if (mSimUnlockProgressDialog != null) {
201 mSimUnlockProgressDialog.dismiss();
202 mSimUnlockProgressDialog = null;
203 }
204 }
205
206 /**
207 * Since the IPC can block, we want to run the request in a separate thread
208 * with a callback.
209 */
210 private abstract class CheckSimPuk extends Thread {
211
212 private final String mPin, mPuk;
213
214 protected CheckSimPuk(String puk, String pin) {
215 mPuk = puk;
216 mPin = pin;
217 }
218
Wink Savilleb896b9f2013-10-23 15:44:26 -0700219 abstract void onSimLockChangedResponse(final int result, final int attemptsRemaining);
Jim Millerdcb3d842012-08-23 19:18:12 -0700220
221 @Override
222 public void run() {
223 try {
Jim Miller4fc2b012013-11-04 16:47:48 -0800224 Log.v(TAG, "call supplyPukReportResult()");
Wink Savilleb896b9f2013-10-23 15:44:26 -0700225 final int[] result = ITelephony.Stub.asInterface(ServiceManager
226 .checkService("phone")).supplyPukReportResult(mPuk, mPin);
Jim Miller4fc2b012013-11-04 16:47:48 -0800227 Log.v(TAG, "supplyPukReportResult returned: " + result[0] + " " + result[1]);
Jim Millerdcb3d842012-08-23 19:18:12 -0700228 post(new Runnable() {
229 public void run() {
Wink Savilleb896b9f2013-10-23 15:44:26 -0700230 onSimLockChangedResponse(result[0], result[1]);
Jim Millerdcb3d842012-08-23 19:18:12 -0700231 }
232 });
233 } catch (RemoteException e) {
Jim Miller4fc2b012013-11-04 16:47:48 -0800234 Log.e(TAG, "RemoteException for supplyPukReportResult:", e);
Jim Millerdcb3d842012-08-23 19:18:12 -0700235 post(new Runnable() {
236 public void run() {
Wink Savilleb896b9f2013-10-23 15:44:26 -0700237 onSimLockChangedResponse(PhoneConstants.PIN_GENERAL_FAILURE, -1);
Jim Millerdcb3d842012-08-23 19:18:12 -0700238 }
239 });
240 }
241 }
242 }
243
Jim Millerdcb3d842012-08-23 19:18:12 -0700244 private Dialog getSimUnlockProgressDialog() {
245 if (mSimUnlockProgressDialog == null) {
246 mSimUnlockProgressDialog = new ProgressDialog(mContext);
Daniel Sandler23d7a6e2012-11-02 00:21:07 -0400247 mSimUnlockProgressDialog.setMessage(
248 mContext.getString(R.string.kg_sim_unlock_progress_dialog_message));
Jim Millerdcb3d842012-08-23 19:18:12 -0700249 mSimUnlockProgressDialog.setIndeterminate(true);
250 mSimUnlockProgressDialog.setCancelable(false);
251 if (!(mContext instanceof Activity)) {
252 mSimUnlockProgressDialog.getWindow().setType(
253 WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
254 }
255 }
256 return mSimUnlockProgressDialog;
257 }
258
Wink Savilleb896b9f2013-10-23 15:44:26 -0700259 private Dialog getPukRemainingAttemptsDialog(int remaining) {
260 String msg = getPukPasswordErrorMessage(remaining);
261 if (mRemainingAttemptsDialog == null) {
262 AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
263 builder.setMessage(msg);
264 builder.setCancelable(false);
265 builder.setNeutralButton(R.string.ok, null);
266 mRemainingAttemptsDialog = builder.create();
267 mRemainingAttemptsDialog.getWindow().setType(
268 WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
269 } else {
270 mRemainingAttemptsDialog.setMessage(msg);
271 }
272 return mRemainingAttemptsDialog;
273 }
274
Jim Miller3efe1062012-09-28 16:59:31 -0700275 private boolean checkPuk() {
Jim Millerdcb3d842012-08-23 19:18:12 -0700276 // make sure the puk is at least 8 digits long.
Rakesh Pallerlab8b7bd32014-01-08 15:49:34 +0530277 if (mPasswordEntry.getText().length() == 8) {
Daniel Sandler23d7a6e2012-11-02 00:21:07 -0400278 mPukText = mPasswordEntry.getText().toString();
Jim Miller3efe1062012-09-28 16:59:31 -0700279 return true;
Jim Millerdcb3d842012-08-23 19:18:12 -0700280 }
Jim Miller3efe1062012-09-28 16:59:31 -0700281 return false;
282 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700283
Jim Miller3efe1062012-09-28 16:59:31 -0700284 private boolean checkPin() {
Jim Millerdcb3d842012-08-23 19:18:12 -0700285 // make sure the PIN is between 4 and 8 digits
Daniel Sandler23d7a6e2012-11-02 00:21:07 -0400286 int length = mPasswordEntry.getText().length();
Jim Miller3efe1062012-09-28 16:59:31 -0700287 if (length >= 4 && length <= 8) {
Daniel Sandler23d7a6e2012-11-02 00:21:07 -0400288 mPinText = mPasswordEntry.getText().toString();
Jim Miller3efe1062012-09-28 16:59:31 -0700289 return true;
Jim Millerdcb3d842012-08-23 19:18:12 -0700290 }
Jim Miller3efe1062012-09-28 16:59:31 -0700291 return false;
292 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700293
Jim Miller3efe1062012-09-28 16:59:31 -0700294 public boolean confirmPin() {
Daniel Sandler23d7a6e2012-11-02 00:21:07 -0400295 return mPinText.equals(mPasswordEntry.getText().toString());
Jim Miller3efe1062012-09-28 16:59:31 -0700296 }
297
298 private void updateSim() {
Jim Millerdcb3d842012-08-23 19:18:12 -0700299 getSimUnlockProgressDialog().show();
300
Jim Miller4fc2b012013-11-04 16:47:48 -0800301 if (mCheckSimPukThread == null) {
302 mCheckSimPukThread = new CheckSimPuk(mPukText, mPinText) {
Wink Savilleb896b9f2013-10-23 15:44:26 -0700303 void onSimLockChangedResponse(final int result, final int attemptsRemaining) {
Jim Miller3efe1062012-09-28 16:59:31 -0700304 post(new Runnable() {
Jim Miller4b09dd32012-09-04 14:27:25 -0700305 public void run() {
306 if (mSimUnlockProgressDialog != null) {
307 mSimUnlockProgressDialog.hide();
308 }
Wink Savilleb896b9f2013-10-23 15:44:26 -0700309 if (result == PhoneConstants.PIN_RESULT_SUCCESS) {
310 KeyguardUpdateMonitor.getInstance(getContext()).reportSimUnlocked();
Jim Miller4b09dd32012-09-04 14:27:25 -0700311 mCallback.dismiss(true);
312 } else {
Wink Savilleb896b9f2013-10-23 15:44:26 -0700313 if (result == PhoneConstants.PIN_PASSWORD_INCORRECT) {
314 if (attemptsRemaining <= 2) {
315 // this is getting critical - show dialog
316 getPukRemainingAttemptsDialog(attemptsRemaining).show();
317 } else {
318 // show message
319 mSecurityMessageDisplay.setMessage(
320 getPukPasswordErrorMessage(attemptsRemaining), true);
321 }
322 } else {
323 mSecurityMessageDisplay.setMessage(getContext().getString(
324 R.string.kg_password_puk_failed), true);
325 }
326 if (DEBUG) Log.d(LOG_TAG, "verifyPasswordAndUnlock "
327 + " UpdateSim.onSimCheckResponse: "
328 + " attemptsRemaining=" + attemptsRemaining);
Jim Miller3efe1062012-09-28 16:59:31 -0700329 mStateMachine.reset();
Jim Miller4b09dd32012-09-04 14:27:25 -0700330 }
Jim Miller4fc2b012013-11-04 16:47:48 -0800331 mCheckSimPukThread = null;
Jim Millerdcb3d842012-08-23 19:18:12 -0700332 }
Jim Miller4b09dd32012-09-04 14:27:25 -0700333 });
334 }
Jim Miller4fc2b012013-11-04 16:47:48 -0800335 };
336 mCheckSimPukThread.start();
Jim Miller4b09dd32012-09-04 14:27:25 -0700337 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700338 }
339
340 @Override
Daniel Sandler23d7a6e2012-11-02 00:21:07 -0400341 protected void verifyPasswordAndUnlock() {
342 mStateMachine.next();
Jim Miller9cf2c522012-10-04 22:02:29 -0700343 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700344}
Daniel Sandler23d7a6e2012-11-02 00:21:07 -0400345
346