blob: 5369aa31e73b7f8a853bdb9e60006623c83fc445 [file] [log] [blame]
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001/*
2 * Copyright (C) 2006 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
17package com.android.phone;
18
19import android.app.Activity;
20import android.app.AlertDialog;
21import android.content.Intent;
22import android.content.res.Resources;
23import android.os.AsyncResult;
24import android.os.Bundle;
25import android.os.Handler;
26import android.os.Message;
27import android.text.method.DigitsKeyListener;
28import android.util.Log;
29import android.view.View;
30import android.widget.Button;
31import android.widget.EditText;
32import android.widget.LinearLayout;
33import android.widget.ScrollView;
34import android.widget.TextView;
35import android.widget.Toast;
36
37import com.android.internal.telephony.CommandException;
38import com.android.internal.telephony.IccCard;
39import com.android.internal.telephony.Phone;
40
41/**
42 * "Change ICC PIN" UI for the Phone app.
43 */
44public class ChangeIccPinScreen extends Activity {
45 private static final String LOG_TAG = PhoneGlobals.LOG_TAG;
46 private static final boolean DBG = false;
47
48 private static final int EVENT_PIN_CHANGED = 100;
49
50 private enum EntryState {
51 ES_PIN,
52 ES_PUK
53 }
54
55 private EntryState mState;
56
57 private static final int NO_ERROR = 0;
58 private static final int PIN_MISMATCH = 1;
59 private static final int PIN_INVALID_LENGTH = 2;
60
61 private static final int MIN_PIN_LENGTH = 4;
62 private static final int MAX_PIN_LENGTH = 8;
63
64 private Phone mPhone;
65 private boolean mChangePin2;
66 private TextView mBadPinError;
67 private TextView mMismatchError;
68 private EditText mOldPin;
69 private EditText mNewPin1;
70 private EditText mNewPin2;
71 private EditText mPUKCode;
72 private Button mButton;
73 private Button mPUKSubmit;
74 private ScrollView mScrollView;
75
76 private LinearLayout mIccPUKPanel;
77
78 private Handler mHandler = new Handler() {
79 public void handleMessage(Message msg) {
80 switch (msg.what) {
81 case EVENT_PIN_CHANGED:
82 AsyncResult ar = (AsyncResult) msg.obj;
83 handleResult(ar);
84 break;
85 }
86
87 return;
88 }
89 };
90
91 public void onCreate(Bundle icicle) {
92 super.onCreate(icicle);
93
94 mPhone = PhoneGlobals.getPhone();
95
96 resolveIntent();
97
98 setContentView(R.layout.change_sim_pin_screen);
99
100 mOldPin = (EditText) findViewById(R.id.old_pin);
101 mOldPin.setKeyListener(DigitsKeyListener.getInstance());
102 mOldPin.setMovementMethod(null);
103 mOldPin.setOnClickListener(mClicked);
104
105 mNewPin1 = (EditText) findViewById(R.id.new_pin1);
106 mNewPin1.setKeyListener(DigitsKeyListener.getInstance());
107 mNewPin1.setMovementMethod(null);
108 mNewPin1.setOnClickListener(mClicked);
109
110 mNewPin2 = (EditText) findViewById(R.id.new_pin2);
111 mNewPin2.setKeyListener(DigitsKeyListener.getInstance());
112 mNewPin2.setMovementMethod(null);
113 mNewPin2.setOnClickListener(mClicked);
114
115 mBadPinError = (TextView) findViewById(R.id.bad_pin);
116 mMismatchError = (TextView) findViewById(R.id.mismatch);
117
118 mButton = (Button) findViewById(R.id.button);
119 mButton.setOnClickListener(mClicked);
120
121 mScrollView = (ScrollView) findViewById(R.id.scroll);
122
123 mPUKCode = (EditText) findViewById(R.id.puk_code);
124 mPUKCode.setKeyListener(DigitsKeyListener.getInstance());
125 mPUKCode.setMovementMethod(null);
126 mPUKCode.setOnClickListener(mClicked);
127
128 mPUKSubmit = (Button) findViewById(R.id.puk_submit);
129 mPUKSubmit.setOnClickListener(mClicked);
130
131 mIccPUKPanel = (LinearLayout) findViewById(R.id.puk_panel);
132
133 int id = mChangePin2 ? R.string.change_pin2 : R.string.change_pin;
134 setTitle(getResources().getText(id));
135
136 mState = EntryState.ES_PIN;
137 }
138
139 private void resolveIntent() {
140 Intent intent = getIntent();
141 mChangePin2 = intent.getBooleanExtra("pin2", mChangePin2);
142 }
143
144 private void reset() {
145 mScrollView.scrollTo(0, 0);
146 mBadPinError.setVisibility(View.GONE);
147 mMismatchError.setVisibility(View.GONE);
148 }
149
150 private int validateNewPin(String p1, String p2) {
151 if (p1 == null) {
152 return PIN_INVALID_LENGTH;
153 }
154
155 if (!p1.equals(p2)) {
156 return PIN_MISMATCH;
157 }
158
159 int len1 = p1.length();
160
161 if (len1 < MIN_PIN_LENGTH || len1 > MAX_PIN_LENGTH) {
162 return PIN_INVALID_LENGTH;
163 }
164
165 return NO_ERROR;
166 }
167
168 private View.OnClickListener mClicked = new View.OnClickListener() {
169 public void onClick(View v) {
170 if (v == mOldPin) {
171 mNewPin1.requestFocus();
172 } else if (v == mNewPin1) {
173 mNewPin2.requestFocus();
174 } else if (v == mNewPin2) {
175 mButton.requestFocus();
176 } else if (v == mButton) {
177 IccCard iccCardInterface = mPhone.getIccCard();
178 if (iccCardInterface != null) {
179 String oldPin = mOldPin.getText().toString();
180 String newPin1 = mNewPin1.getText().toString();
181 String newPin2 = mNewPin2.getText().toString();
182
183 int error = validateNewPin(newPin1, newPin2);
184
185 switch (error) {
186 case PIN_INVALID_LENGTH:
187 case PIN_MISMATCH:
188 mNewPin1.getText().clear();
189 mNewPin2.getText().clear();
190 mMismatchError.setVisibility(View.VISIBLE);
191
192 Resources r = getResources();
193 CharSequence text;
194
195 if (error == PIN_MISMATCH) {
196 text = r.getString(R.string.mismatchPin);
197 } else {
198 text = r.getString(R.string.invalidPin);
199 }
200
201 mMismatchError.setText(text);
202 break;
203
204 default:
205 Message callBack = Message.obtain(mHandler,
206 EVENT_PIN_CHANGED);
207
208 if (DBG) log("change pin attempt: old=" + oldPin +
209 ", newPin=" + newPin1);
210
211 reset();
212
213 if (mChangePin2) {
214 iccCardInterface.changeIccFdnPassword(oldPin,
215 newPin1, callBack);
216 } else {
217 iccCardInterface.changeIccLockPassword(oldPin,
218 newPin1, callBack);
219 }
220
221 // TODO: show progress panel
222 }
223 }
224 } else if (v == mPUKCode) {
225 mPUKSubmit.requestFocus();
226 } else if (v == mPUKSubmit) {
227 mPhone.getIccCard().supplyPuk2(mPUKCode.getText().toString(),
228 mNewPin1.getText().toString(),
229 Message.obtain(mHandler, EVENT_PIN_CHANGED));
230 }
231 }
232 };
233
234 private void handleResult(AsyncResult ar) {
235 if (ar.exception == null) {
236 if (DBG) log("handleResult: success!");
237
238 if (mState == EntryState.ES_PUK) {
239 mScrollView.setVisibility(View.VISIBLE);
240 mIccPUKPanel.setVisibility(View.GONE);
241 }
242 // TODO: show success feedback
243 showConfirmation();
244
245 mHandler.postDelayed(new Runnable() {
246 public void run() {
247 finish();
248 }
249 }, 3000);
250
251 } else if (ar.exception instanceof CommandException
252 /* && ((CommandException)ar.exception).getCommandError() ==
253 CommandException.Error.PASSWORD_INCORRECT */ ) {
254 if (mState == EntryState.ES_PIN) {
255 if (DBG) log("handleResult: pin failed!");
256 mOldPin.getText().clear();
257 mBadPinError.setVisibility(View.VISIBLE);
258 CommandException ce = (CommandException) ar.exception;
259 if (ce.getCommandError() == CommandException.Error.SIM_PUK2) {
260 if (DBG) log("handleResult: puk requested!");
261 mState = EntryState.ES_PUK;
262 displayPUKAlert();
263 mScrollView.setVisibility(View.GONE);
264 mIccPUKPanel.setVisibility(View.VISIBLE);
265 mPUKCode.requestFocus();
266 }
267 } else if (mState == EntryState.ES_PUK) {
268 //should really check to see if the error is CommandException.PASSWORD_INCORRECT...
269 if (DBG) log("handleResult: puk2 failed!");
270 displayPUKAlert();
271 mPUKCode.getText().clear();
272 mPUKCode.requestFocus();
273 }
274 }
275 }
276
277 private AlertDialog mPUKAlert;
278 private void displayPUKAlert () {
279 if (mPUKAlert == null) {
Sooraj Sasindran9dbb2882021-10-19 11:40:34 -0700280 mPUKAlert = FrameworksUtils.makeAlertDialogBuilder(this)
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700281 .setMessage (R.string.puk_requested)
282 .setCancelable(false)
283 .show();
284 } else {
285 mPUKAlert.show();
286 }
287 //TODO: The 3 second delay here is somewhat arbitrary, reflecting the values
288 //used elsewhere for similar code. This should get revisited with the framework
289 //crew to see if there is some standard we should adhere to.
290 mHandler.postDelayed(new Runnable() {
291 public void run() {
292 mPUKAlert.dismiss();
293 }
294 }, 3000);
295 }
296
297 private void showConfirmation() {
298 int id = mChangePin2 ? R.string.pin2_changed : R.string.pin_changed;
299 Toast.makeText(this, id, Toast.LENGTH_SHORT).show();
300 }
301
302 private void log(String msg) {
303 String prefix = mChangePin2 ? "[ChgPin2]" : "[ChgPin]";
304 Log.d(LOG_TAG, prefix + msg);
305 }
306}