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