blob: ae7ac978ef73f4266755d7b02f3d8884e81cd9a4 [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.app.AlertDialog;
24import android.app.AlertDialog.Builder;
Jim Millerdcb3d842012-08-23 19:18:12 -070025import android.app.Dialog;
26import android.app.ProgressDialog;
Jim Millerdcb3d842012-08-23 19:18:12 -070027import android.os.RemoteException;
28import android.os.ServiceManager;
Daniel Sandler53149e62012-11-01 22:00:07 -040029import android.text.InputType;
Jim Miller9cf2c522012-10-04 22:02:29 -070030import android.text.TextWatcher;
Daniel Sandler53149e62012-11-01 22:00:07 -040031import android.text.method.DigitsKeyListener;
Jim Millerdcb3d842012-08-23 19:18:12 -070032import android.util.AttributeSet;
Jim Millerdcb3d842012-08-23 19:18:12 -070033import android.view.View;
Wink Savilleb896b9f2013-10-23 15:44:26 -070034import android.util.Log;
Jim Millerdcb3d842012-08-23 19:18:12 -070035import android.view.WindowManager;
Jim Millerdcb3d842012-08-23 19:18:12 -070036import android.widget.TextView.OnEditorActionListener;
37
38/**
Daniel Sandler53149e62012-11-01 22:00:07 -040039 * Displays a PIN pad for unlocking.
Jim Millerdcb3d842012-08-23 19:18:12 -070040 */
Daniel Sandler53149e62012-11-01 22:00:07 -040041public class KeyguardSimPinView extends KeyguardAbsKeyInputView
Jim Millerd6c48842012-11-01 21:40:47 -070042 implements KeyguardSecurityView, OnEditorActionListener, TextWatcher {
Wink Savilleb896b9f2013-10-23 15:44:26 -070043 private static final String LOG_TAG = "KeyguardSimPinView";
44 private static final boolean DEBUG = KeyguardViewMediator.DEBUG;
Jim Miller4fc2b012013-11-04 16:47:48 -080045 public static final String TAG = "KeyguardSimPinView";
Jim Millerdcb3d842012-08-23 19:18:12 -070046
Jim Millerd6c48842012-11-01 21:40:47 -070047 private ProgressDialog mSimUnlockProgressDialog = null;
Jim Miller4fc2b012013-11-04 16:47:48 -080048 private CheckSimPin mCheckSimPinThread;
Jim Millerd6c48842012-11-01 21:40:47 -070049
Wink Savilleb896b9f2013-10-23 15:44:26 -070050 private AlertDialog mRemainingAttemptsDialog;
51
Jim Millerd6c48842012-11-01 21:40:47 -070052 public KeyguardSimPinView(Context context) {
Jim Millerdcb3d842012-08-23 19:18:12 -070053 this(context, null);
54 }
55
56 public KeyguardSimPinView(Context context, AttributeSet attrs) {
57 super(context, attrs);
Jim Millerdcb3d842012-08-23 19:18:12 -070058 }
59
Daniel Sandler53149e62012-11-01 22:00:07 -040060 public void resetState() {
61 mSecurityMessageDisplay.setMessage(R.string.kg_sim_pin_instructions, true);
62 mPasswordEntry.setEnabled(true);
63 }
64
Wink Savilleb896b9f2013-10-23 15:44:26 -070065 private String getPinPasswordErrorMessage(int attemptsRemaining) {
66 String displayMessage;
67
68 if (attemptsRemaining == 0) {
69 displayMessage = getContext().getString(R.string.kg_password_wrong_pin_code_pukked);
70 } else if (attemptsRemaining > 0) {
71 displayMessage = getContext().getResources()
72 .getQuantityString(R.plurals.kg_password_wrong_pin_code, attemptsRemaining,
73 attemptsRemaining);
74 } else {
75 displayMessage = getContext().getString(R.string.kg_password_pin_failed);
76 }
77 if (DEBUG) Log.d(LOG_TAG, "getPinPasswordErrorMessage:"
78 + " attemptsRemaining=" + attemptsRemaining + " displayMessage=" + displayMessage);
79 return displayMessage;
80 }
81
Daniel Sandler53149e62012-11-01 22:00:07 -040082 @Override
Jim Miller7d5e00a2013-10-11 22:45:57 -070083 protected boolean shouldLockout(long deadline) {
84 // SIM PIN doesn't have a timed lockout
85 return false;
86 }
87
88 @Override
Daniel Sandler53149e62012-11-01 22:00:07 -040089 protected int getPasswordTextViewId() {
90 return R.id.pinEntry;
Jim Millerdcb3d842012-08-23 19:18:12 -070091 }
92
93 @Override
94 protected void onFinishInflate() {
95 super.onFinishInflate();
96
Daniel Sandler53149e62012-11-01 22:00:07 -040097 final View ok = findViewById(R.id.key_enter);
98 if (ok != null) {
99 ok.setOnClickListener(new View.OnClickListener() {
100 @Override
Jim Millerdcb3d842012-08-23 19:18:12 -0700101 public void onClick(View v) {
Daniel Sandler53149e62012-11-01 22:00:07 -0400102 doHapticKeyClick();
103 verifyPasswordAndUnlock();
Jim Millerdcb3d842012-08-23 19:18:12 -0700104 }
105 });
106 }
Jim Miller0b728242012-10-28 19:42:30 -0700107
Daniel Sandler53149e62012-11-01 22:00:07 -0400108 // The delete button is of the PIN keyboard itself in some (e.g. tablet) layouts,
109 // not a separate view
110 View pinDelete = findViewById(R.id.delete_button);
111 if (pinDelete != null) {
112 pinDelete.setVisibility(View.VISIBLE);
113 pinDelete.setOnClickListener(new OnClickListener() {
114 public void onClick(View v) {
115 CharSequence str = mPasswordEntry.getText();
116 if (str.length() > 0) {
117 mPasswordEntry.setText(str.subSequence(0, str.length()-1));
118 }
119 doHapticKeyClick();
120 }
121 });
122 pinDelete.setOnLongClickListener(new View.OnLongClickListener() {
123 public boolean onLongClick(View v) {
124 mPasswordEntry.setText("");
125 doHapticKeyClick();
126 return true;
127 }
128 });
129 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700130
Daniel Sandler53149e62012-11-01 22:00:07 -0400131 mPasswordEntry.setKeyListener(DigitsKeyListener.getInstance());
132 mPasswordEntry.setInputType(InputType.TYPE_CLASS_NUMBER
133 | InputType.TYPE_NUMBER_VARIATION_PASSWORD);
Jim Millerdcb3d842012-08-23 19:18:12 -0700134
Daniel Sandler53149e62012-11-01 22:00:07 -0400135 mPasswordEntry.requestFocus();
Wink Savilleb896b9f2013-10-23 15:44:26 -0700136
137 mSecurityMessageDisplay.setTimeout(0); // don't show ownerinfo/charging status by default
Jim Millerdcb3d842012-08-23 19:18:12 -0700138 }
139
Adam Cohen6fb841f2012-10-24 13:15:38 -0700140 @Override
141 public void showUsabilityHint() {
142 }
143
Daniel Sandler53149e62012-11-01 22:00:07 -0400144 @Override
145 public void onPause() {
Jim Millerdcb3d842012-08-23 19:18:12 -0700146 // dismiss the dialog.
147 if (mSimUnlockProgressDialog != null) {
148 mSimUnlockProgressDialog.dismiss();
149 mSimUnlockProgressDialog = null;
150 }
151 }
152
153 /**
154 * Since the IPC can block, we want to run the request in a separate thread
155 * with a callback.
156 */
157 private abstract class CheckSimPin extends Thread {
158 private final String mPin;
159
160 protected CheckSimPin(String pin) {
161 mPin = pin;
162 }
163
Wink Savilleb896b9f2013-10-23 15:44:26 -0700164 abstract void onSimCheckResponse(final int result, final int attemptsRemaining);
Jim Millerdcb3d842012-08-23 19:18:12 -0700165
166 @Override
167 public void run() {
168 try {
Jim Miller4fc2b012013-11-04 16:47:48 -0800169 Log.v(TAG, "call supplyPinReportResult()");
Wink Savilleb896b9f2013-10-23 15:44:26 -0700170 final int[] result = ITelephony.Stub.asInterface(ServiceManager
171 .checkService("phone")).supplyPinReportResult(mPin);
Jim Miller4fc2b012013-11-04 16:47:48 -0800172 Log.v(TAG, "supplyPinReportResult returned: " + result[0] + " " + result[1]);
Jim Millerdcb3d842012-08-23 19:18:12 -0700173 post(new Runnable() {
174 public void run() {
Wink Savilleb896b9f2013-10-23 15:44:26 -0700175 onSimCheckResponse(result[0], result[1]);
Jim Millerdcb3d842012-08-23 19:18:12 -0700176 }
177 });
178 } catch (RemoteException e) {
Jim Miller4fc2b012013-11-04 16:47:48 -0800179 Log.e(TAG, "RemoteException for supplyPinReportResult:", e);
Jim Millerdcb3d842012-08-23 19:18:12 -0700180 post(new Runnable() {
181 public void run() {
Wink Savilleb896b9f2013-10-23 15:44:26 -0700182 onSimCheckResponse(PhoneConstants.PIN_GENERAL_FAILURE, -1);
Jim Millerdcb3d842012-08-23 19:18:12 -0700183 }
184 });
185 }
186 }
187 }
188
Jim Millerdcb3d842012-08-23 19:18:12 -0700189 private Dialog getSimUnlockProgressDialog() {
190 if (mSimUnlockProgressDialog == null) {
191 mSimUnlockProgressDialog = new ProgressDialog(mContext);
192 mSimUnlockProgressDialog.setMessage(
193 mContext.getString(R.string.kg_sim_unlock_progress_dialog_message));
194 mSimUnlockProgressDialog.setIndeterminate(true);
195 mSimUnlockProgressDialog.setCancelable(false);
Wink Savilleb896b9f2013-10-23 15:44:26 -0700196 mSimUnlockProgressDialog.getWindow().setType(
197 WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
Jim Millerdcb3d842012-08-23 19:18:12 -0700198 }
199 return mSimUnlockProgressDialog;
200 }
201
Wink Savilleb896b9f2013-10-23 15:44:26 -0700202 private Dialog getSimRemainingAttemptsDialog(int remaining) {
203 String msg = getPinPasswordErrorMessage(remaining);
204 if (mRemainingAttemptsDialog == null) {
205 Builder builder = new AlertDialog.Builder(mContext);
206 builder.setMessage(msg);
207 builder.setCancelable(false);
208 builder.setNeutralButton(R.string.ok, null);
209 mRemainingAttemptsDialog = builder.create();
210 mRemainingAttemptsDialog.getWindow().setType(
211 WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
212 } else {
213 mRemainingAttemptsDialog.setMessage(msg);
214 }
215 return mRemainingAttemptsDialog;
216 }
217
Daniel Sandler53149e62012-11-01 22:00:07 -0400218 @Override
219 protected void verifyPasswordAndUnlock() {
220 String entry = mPasswordEntry.getText().toString();
Jim Miller7d5e00a2013-10-11 22:45:57 -0700221
Daniel Sandler53149e62012-11-01 22:00:07 -0400222 if (entry.length() < 4) {
Jim Millerdcb3d842012-08-23 19:18:12 -0700223 // otherwise, display a message to the user, and don't submit.
Adam Cohen0a4f9002012-10-12 19:57:16 -0700224 mSecurityMessageDisplay.setMessage(R.string.kg_invalid_sim_pin_hint, true);
Daniel Sandler53149e62012-11-01 22:00:07 -0400225 mPasswordEntry.setText("");
Jim Millerdcb3d842012-08-23 19:18:12 -0700226 mCallback.userActivity(0);
227 return;
228 }
229
230 getSimUnlockProgressDialog().show();
231
Jim Miller4fc2b012013-11-04 16:47:48 -0800232 if (mCheckSimPinThread == null) {
233 mCheckSimPinThread = new CheckSimPin(mPasswordEntry.getText().toString()) {
Wink Savilleb896b9f2013-10-23 15:44:26 -0700234 void onSimCheckResponse(final int result, final int attemptsRemaining) {
Jim Miller4b09dd32012-09-04 14:27:25 -0700235 post(new Runnable() {
236 public void run() {
237 if (mSimUnlockProgressDialog != null) {
238 mSimUnlockProgressDialog.hide();
239 }
Wink Savilleb896b9f2013-10-23 15:44:26 -0700240 if (result == PhoneConstants.PIN_RESULT_SUCCESS) {
Jim Miller4b09dd32012-09-04 14:27:25 -0700241 KeyguardUpdateMonitor.getInstance(getContext()).reportSimUnlocked();
242 mCallback.dismiss(true);
243 } else {
Wink Savilleb896b9f2013-10-23 15:44:26 -0700244 if (result == PhoneConstants.PIN_PASSWORD_INCORRECT) {
245 if (attemptsRemaining <= 2) {
246 // this is getting critical - show dialog
247 getSimRemainingAttemptsDialog(attemptsRemaining).show();
248 } else {
249 // show message
250 mSecurityMessageDisplay.setMessage(
251 getPinPasswordErrorMessage(attemptsRemaining), true);
252 }
253 } else {
254 // "PIN operation failed!" - no idea what this was and no way to
255 // find out. :/
256 mSecurityMessageDisplay.setMessage(getContext().getString(
257 R.string.kg_password_pin_failed), true);
258 }
259 if (DEBUG) Log.d(LOG_TAG, "verifyPasswordAndUnlock "
260 + " CheckSimPin.onSimCheckResponse: " + result
261 + " attemptsRemaining=" + attemptsRemaining);
Daniel Sandler53149e62012-11-01 22:00:07 -0400262 mPasswordEntry.setText("");
Jim Miller4b09dd32012-09-04 14:27:25 -0700263 }
264 mCallback.userActivity(0);
Jim Miller4fc2b012013-11-04 16:47:48 -0800265 mCheckSimPinThread = null;
Jim Millerdcb3d842012-08-23 19:18:12 -0700266 }
Jim Miller4b09dd32012-09-04 14:27:25 -0700267 });
268 }
Jim Miller4fc2b012013-11-04 16:47:48 -0800269 };
270 mCheckSimPinThread.start();
Jim Miller4b09dd32012-09-04 14:27:25 -0700271 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700272 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700273}
Daniel Sandler53149e62012-11-01 22:00:07 -0400274