• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package com.android.phone;
18 
19 import android.app.Activity;
20 import android.app.AlertDialog;
21 import android.content.Intent;
22 import android.content.res.Resources;
23 import android.os.AsyncResult;
24 import android.os.Bundle;
25 import android.os.Handler;
26 import android.os.Message;
27 import android.text.method.DigitsKeyListener;
28 import android.util.Log;
29 import android.view.View;
30 import android.widget.Button;
31 import android.widget.EditText;
32 import android.widget.LinearLayout;
33 import android.widget.ScrollView;
34 import android.widget.TextView;
35 import android.widget.Toast;
36 
37 import com.android.internal.telephony.CommandException;
38 import com.android.internal.telephony.IccCard;
39 import com.android.internal.telephony.Phone;
40 
41 /**
42  * "Change ICC PIN" UI for the Phone app.
43  */
44 public 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 
onCreate(Bundle icicle)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 
resolveIntent()139     private void resolveIntent() {
140         Intent intent = getIntent();
141         mChangePin2 = intent.getBooleanExtra("pin2", mChangePin2);
142     }
143 
reset()144     private void reset() {
145         mScrollView.scrollTo(0, 0);
146         mBadPinError.setVisibility(View.GONE);
147         mMismatchError.setVisibility(View.GONE);
148     }
149 
validateNewPin(String p1, String p2)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 
handleResult(AsyncResult ar)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;
displayPUKAlert()278     private void displayPUKAlert () {
279         if (mPUKAlert == null) {
280             mPUKAlert = new AlertDialog.Builder(this)
281             .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 
showConfirmation()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 
log(String msg)302     private void log(String msg) {
303         String prefix = mChangePin2 ? "[ChgPin2]" : "[ChgPin]";
304         Log.d(LOG_TAG, prefix + msg);
305     }
306 }
307