blob: 9accbb44cd77af38e7f40497bf7ac7f526d3f0c7 [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 */
16
Jim Miller5ecd8112013-01-09 18:50:26 -080017package com.android.keyguard;
Jim Millerdcb3d842012-08-23 19:18:12 -070018
Daniel Sandler53149e62012-11-01 22:00:07 -040019import com.android.internal.telephony.ITelephony;
Wink Savilleb896b9f2013-10-23 15:44:26 -070020import com.android.internal.telephony.PhoneConstants;
Daniel Sandler53149e62012-11-01 22:00:07 -040021
22import android.content.Context;
Wink Savilleb896b9f2013-10-23 15:44:26 -070023import android.content.DialogInterface;
Jim Millerdcb3d842012-08-23 19:18:12 -070024import android.app.Activity;
Wink Savilleb896b9f2013-10-23 15:44:26 -070025import android.app.AlertDialog;
26import android.app.AlertDialog.Builder;
Jim Millerdcb3d842012-08-23 19:18:12 -070027import android.app.Dialog;
28import android.app.ProgressDialog;
Wink Savilleb896b9f2013-10-23 15:44:26 -070029import android.os.Message;
Jim Millerdcb3d842012-08-23 19:18:12 -070030import android.os.RemoteException;
31import android.os.ServiceManager;
Jim Miller9cf2c522012-10-04 22:02:29 -070032import android.text.Editable;
Daniel Sandler53149e62012-11-01 22:00:07 -040033import android.text.InputType;
Jim Miller9cf2c522012-10-04 22:02:29 -070034import android.text.TextWatcher;
Daniel Sandler53149e62012-11-01 22:00:07 -040035import android.text.method.DigitsKeyListener;
Jim Millerdcb3d842012-08-23 19:18:12 -070036import android.util.AttributeSet;
Jim Millerdcb3d842012-08-23 19:18:12 -070037import android.view.View;
Wink Savilleb896b9f2013-10-23 15:44:26 -070038import android.util.Log;
Jim Millerdcb3d842012-08-23 19:18:12 -070039import android.view.WindowManager;
Jim Millerdcb3d842012-08-23 19:18:12 -070040import android.widget.TextView.OnEditorActionListener;
41
42/**
Daniel Sandler53149e62012-11-01 22:00:07 -040043 * Displays a PIN pad for unlocking.
Jim Millerdcb3d842012-08-23 19:18:12 -070044 */
Daniel Sandler53149e62012-11-01 22:00:07 -040045public class KeyguardSimPinView extends KeyguardAbsKeyInputView
Jim Millerd6c48842012-11-01 21:40:47 -070046 implements KeyguardSecurityView, OnEditorActionListener, TextWatcher {
Wink Savilleb896b9f2013-10-23 15:44:26 -070047 private static final String LOG_TAG = "KeyguardSimPinView";
48 private static final boolean DEBUG = KeyguardViewMediator.DEBUG;
Jim Miller4fc2b012013-11-04 16:47:48 -080049 public static final String TAG = "KeyguardSimPinView";
Jim Millerdcb3d842012-08-23 19:18:12 -070050
Jim Millerd6c48842012-11-01 21:40:47 -070051 private ProgressDialog mSimUnlockProgressDialog = null;
Jim Miller4fc2b012013-11-04 16:47:48 -080052 private CheckSimPin mCheckSimPinThread;
Jim Millerd6c48842012-11-01 21:40:47 -070053
Wink Savilleb896b9f2013-10-23 15:44:26 -070054 private AlertDialog mRemainingAttemptsDialog;
55
Jim Millerd6c48842012-11-01 21:40:47 -070056 public KeyguardSimPinView(Context context) {
Jim Millerdcb3d842012-08-23 19:18:12 -070057 this(context, null);
58 }
59
60 public KeyguardSimPinView(Context context, AttributeSet attrs) {
61 super(context, attrs);
Jim Millerdcb3d842012-08-23 19:18:12 -070062 }
63
Daniel Sandler53149e62012-11-01 22:00:07 -040064 public void resetState() {
65 mSecurityMessageDisplay.setMessage(R.string.kg_sim_pin_instructions, true);
66 mPasswordEntry.setEnabled(true);
67 }
68
Wink Savilleb896b9f2013-10-23 15:44:26 -070069 private String getPinPasswordErrorMessage(int attemptsRemaining) {
70 String displayMessage;
71
72 if (attemptsRemaining == 0) {
73 displayMessage = getContext().getString(R.string.kg_password_wrong_pin_code_pukked);
74 } else if (attemptsRemaining > 0) {
75 displayMessage = getContext().getResources()
76 .getQuantityString(R.plurals.kg_password_wrong_pin_code, attemptsRemaining,
77 attemptsRemaining);
78 } else {
79 displayMessage = getContext().getString(R.string.kg_password_pin_failed);
80 }
81 if (DEBUG) Log.d(LOG_TAG, "getPinPasswordErrorMessage:"
82 + " attemptsRemaining=" + attemptsRemaining + " displayMessage=" + displayMessage);
83 return displayMessage;
84 }
85
Daniel Sandler53149e62012-11-01 22:00:07 -040086 @Override
Jim Miller7d5e00a2013-10-11 22:45:57 -070087 protected boolean shouldLockout(long deadline) {
88 // SIM PIN doesn't have a timed lockout
89 return false;
90 }
91
92 @Override
Daniel Sandler53149e62012-11-01 22:00:07 -040093 protected int getPasswordTextViewId() {
94 return R.id.pinEntry;
Jim Millerdcb3d842012-08-23 19:18:12 -070095 }
96
97 @Override
98 protected void onFinishInflate() {
99 super.onFinishInflate();
100
Daniel Sandler53149e62012-11-01 22:00:07 -0400101 final View ok = findViewById(R.id.key_enter);
102 if (ok != null) {
103 ok.setOnClickListener(new View.OnClickListener() {
104 @Override
Jim Millerdcb3d842012-08-23 19:18:12 -0700105 public void onClick(View v) {
Daniel Sandler53149e62012-11-01 22:00:07 -0400106 doHapticKeyClick();
107 verifyPasswordAndUnlock();
Jim Millerdcb3d842012-08-23 19:18:12 -0700108 }
109 });
110 }
Jim Miller0b728242012-10-28 19:42:30 -0700111
Daniel Sandler53149e62012-11-01 22:00:07 -0400112 // The delete button is of the PIN keyboard itself in some (e.g. tablet) layouts,
113 // not a separate view
114 View pinDelete = findViewById(R.id.delete_button);
115 if (pinDelete != null) {
116 pinDelete.setVisibility(View.VISIBLE);
117 pinDelete.setOnClickListener(new OnClickListener() {
118 public void onClick(View v) {
119 CharSequence str = mPasswordEntry.getText();
120 if (str.length() > 0) {
121 mPasswordEntry.setText(str.subSequence(0, str.length()-1));
122 }
123 doHapticKeyClick();
124 }
125 });
126 pinDelete.setOnLongClickListener(new View.OnLongClickListener() {
127 public boolean onLongClick(View v) {
128 mPasswordEntry.setText("");
129 doHapticKeyClick();
130 return true;
131 }
132 });
133 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700134
Daniel Sandler53149e62012-11-01 22:00:07 -0400135 mPasswordEntry.setKeyListener(DigitsKeyListener.getInstance());
136 mPasswordEntry.setInputType(InputType.TYPE_CLASS_NUMBER
137 | InputType.TYPE_NUMBER_VARIATION_PASSWORD);
Jim Millerdcb3d842012-08-23 19:18:12 -0700138
Daniel Sandler53149e62012-11-01 22:00:07 -0400139 mPasswordEntry.requestFocus();
Wink Savilleb896b9f2013-10-23 15:44:26 -0700140
141 mSecurityMessageDisplay.setTimeout(0); // don't show ownerinfo/charging status by default
Jim Millerdcb3d842012-08-23 19:18:12 -0700142 }
143
Adam Cohen6fb841f2012-10-24 13:15:38 -0700144 @Override
145 public void showUsabilityHint() {
146 }
147
Daniel Sandler53149e62012-11-01 22:00:07 -0400148 @Override
149 public void onPause() {
Jim Millerdcb3d842012-08-23 19:18:12 -0700150 // dismiss the dialog.
151 if (mSimUnlockProgressDialog != null) {
152 mSimUnlockProgressDialog.dismiss();
153 mSimUnlockProgressDialog = null;
154 }
155 }
156
157 /**
158 * Since the IPC can block, we want to run the request in a separate thread
159 * with a callback.
160 */
161 private abstract class CheckSimPin extends Thread {
162 private final String mPin;
163
164 protected CheckSimPin(String pin) {
165 mPin = pin;
166 }
167
Wink Savilleb896b9f2013-10-23 15:44:26 -0700168 abstract void onSimCheckResponse(final int result, final int attemptsRemaining);
Jim Millerdcb3d842012-08-23 19:18:12 -0700169
170 @Override
171 public void run() {
172 try {
Jim Miller4fc2b012013-11-04 16:47:48 -0800173 Log.v(TAG, "call supplyPinReportResult()");
Wink Savilleb896b9f2013-10-23 15:44:26 -0700174 final int[] result = ITelephony.Stub.asInterface(ServiceManager
175 .checkService("phone")).supplyPinReportResult(mPin);
Jim Miller4fc2b012013-11-04 16:47:48 -0800176 Log.v(TAG, "supplyPinReportResult returned: " + result[0] + " " + result[1]);
Jim Millerdcb3d842012-08-23 19:18:12 -0700177 post(new Runnable() {
178 public void run() {
Wink Savilleb896b9f2013-10-23 15:44:26 -0700179 onSimCheckResponse(result[0], result[1]);
Jim Millerdcb3d842012-08-23 19:18:12 -0700180 }
181 });
182 } catch (RemoteException e) {
Jim Miller4fc2b012013-11-04 16:47:48 -0800183 Log.e(TAG, "RemoteException for supplyPinReportResult:", e);
Jim Millerdcb3d842012-08-23 19:18:12 -0700184 post(new Runnable() {
185 public void run() {
Wink Savilleb896b9f2013-10-23 15:44:26 -0700186 onSimCheckResponse(PhoneConstants.PIN_GENERAL_FAILURE, -1);
Jim Millerdcb3d842012-08-23 19:18:12 -0700187 }
188 });
189 }
190 }
191 }
192
Jim Millerdcb3d842012-08-23 19:18:12 -0700193 private Dialog getSimUnlockProgressDialog() {
194 if (mSimUnlockProgressDialog == null) {
195 mSimUnlockProgressDialog = new ProgressDialog(mContext);
196 mSimUnlockProgressDialog.setMessage(
197 mContext.getString(R.string.kg_sim_unlock_progress_dialog_message));
198 mSimUnlockProgressDialog.setIndeterminate(true);
199 mSimUnlockProgressDialog.setCancelable(false);
Wink Savilleb896b9f2013-10-23 15:44:26 -0700200 mSimUnlockProgressDialog.getWindow().setType(
201 WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
Jim Millerdcb3d842012-08-23 19:18:12 -0700202 }
203 return mSimUnlockProgressDialog;
204 }
205
Wink Savilleb896b9f2013-10-23 15:44:26 -0700206 private Dialog getSimRemainingAttemptsDialog(int remaining) {
207 String msg = getPinPasswordErrorMessage(remaining);
208 if (mRemainingAttemptsDialog == null) {
209 Builder builder = new AlertDialog.Builder(mContext);
210 builder.setMessage(msg);
211 builder.setCancelable(false);
212 builder.setNeutralButton(R.string.ok, null);
213 mRemainingAttemptsDialog = builder.create();
214 mRemainingAttemptsDialog.getWindow().setType(
215 WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
216 } else {
217 mRemainingAttemptsDialog.setMessage(msg);
218 }
219 return mRemainingAttemptsDialog;
220 }
221
Daniel Sandler53149e62012-11-01 22:00:07 -0400222 @Override
223 protected void verifyPasswordAndUnlock() {
224 String entry = mPasswordEntry.getText().toString();
Jim Miller7d5e00a2013-10-11 22:45:57 -0700225
Daniel Sandler53149e62012-11-01 22:00:07 -0400226 if (entry.length() < 4) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700227 // otherwise, display a message to the user, and don't submit.
Adam Cohen0a4f9002012-10-12 19:57:16 -0700228 mSecurityMessageDisplay.setMessage(R.string.kg_invalid_sim_pin_hint, true);
Daniel Sandler53149e62012-11-01 22:00:07 -0400229 mPasswordEntry.setText("");
Jim Millerdcb3d842012-08-23 19:18:12 -0700230 mCallback.userActivity(0);
231 return;
232 }
233
234 getSimUnlockProgressDialog().show();
235
Jim Miller4fc2b012013-11-04 16:47:48 -0800236 if (mCheckSimPinThread == null) {
237 mCheckSimPinThread = new CheckSimPin(mPasswordEntry.getText().toString()) {
Wink Savilleb896b9f2013-10-23 15:44:26 -0700238 void onSimCheckResponse(final int result, final int attemptsRemaining) {
Jim Miller4b09dd32012-09-04 14:27:25 -0700239 post(new Runnable() {
240 public void run() {
241 if (mSimUnlockProgressDialog != null) {
242 mSimUnlockProgressDialog.hide();
243 }
Wink Savilleb896b9f2013-10-23 15:44:26 -0700244 if (result == PhoneConstants.PIN_RESULT_SUCCESS) {
Jim Miller4b09dd32012-09-04 14:27:25 -0700245 KeyguardUpdateMonitor.getInstance(getContext()).reportSimUnlocked();
246 mCallback.dismiss(true);
247 } else {
Wink Savilleb896b9f2013-10-23 15:44:26 -0700248 if (result == PhoneConstants.PIN_PASSWORD_INCORRECT) {
249 if (attemptsRemaining <= 2) {
250 // this is getting critical - show dialog
251 getSimRemainingAttemptsDialog(attemptsRemaining).show();
252 } else {
253 // show message
254 mSecurityMessageDisplay.setMessage(
255 getPinPasswordErrorMessage(attemptsRemaining), true);
256 }
257 } else {
258 // "PIN operation failed!" - no idea what this was and no way to
259 // find out. :/
260 mSecurityMessageDisplay.setMessage(getContext().getString(
261 R.string.kg_password_pin_failed), true);
262 }
263 if (DEBUG) Log.d(LOG_TAG, "verifyPasswordAndUnlock "
264 + " CheckSimPin.onSimCheckResponse: " + result
265 + " attemptsRemaining=" + attemptsRemaining);
Daniel Sandler53149e62012-11-01 22:00:07 -0400266 mPasswordEntry.setText("");
Jim Miller4b09dd32012-09-04 14:27:25 -0700267 }
268 mCallback.userActivity(0);
Jim Miller4fc2b012013-11-04 16:47:48 -0800269 mCheckSimPinThread = null;
Jim Millerdcb3d842012-08-23 19:18:12 -0700270 }
Jim Miller4b09dd32012-09-04 14:27:25 -0700271 });
272 }
Jim Miller4fc2b012013-11-04 16:47:48 -0800273 };
274 mCheckSimPinThread.start();
Jim Miller4b09dd32012-09-04 14:27:25 -0700275 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700276 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700277}
Daniel Sandler53149e62012-11-01 22:00:07 -0400278