OSDN Git Service

am 57c88834: (-s ours) am 9fe36302: (-s ours) am 9cb97c44: Merge "DO NOT MERGE Fix...
[android-x86/packages-apps-Settings.git] / src / com / android / settings / IccLockSettings.java
1 /*
2  * Copyright (C) 2008 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.settings;
18
19 import android.content.Context;
20 import android.content.res.Resources;
21 import android.os.AsyncResult;
22 import android.os.Bundle;
23 import android.os.Handler;
24 import android.os.Message;
25 import android.preference.CheckBoxPreference;
26 import android.preference.Preference;
27 import android.preference.PreferenceActivity;
28 import android.preference.PreferenceScreen;
29 import android.widget.Toast;
30
31 import com.android.internal.telephony.Phone;
32 import com.android.internal.telephony.PhoneFactory;
33
34 /**
35  * Implements the preference screen to enable/disable ICC lock and
36  * also the dialogs to change the ICC PIN. In the former case, enabling/disabling
37  * the ICC lock will prompt the user for the current PIN.
38  * In the Change PIN case, it prompts the user for old pin, new pin and new pin
39  * again before attempting to change it. Calls the SimCard interface to execute
40  * these operations.
41  *
42  */
43 public class IccLockSettings extends PreferenceActivity 
44         implements EditPinPreference.OnPinEnteredListener {
45
46     private static final int OFF_MODE = 0;
47     // State when enabling/disabling ICC lock
48     private static final int ICC_LOCK_MODE = 1;
49     // State when entering the old pin
50     private static final int ICC_OLD_MODE = 2;
51     // State when entering the new pin - first time
52     private static final int ICC_NEW_MODE = 3;
53     // State when entering the new pin - second time
54     private static final int ICC_REENTER_MODE = 4;
55     
56     // Keys in xml file
57     private static final String PIN_DIALOG = "sim_pin";
58     private static final String PIN_TOGGLE = "sim_toggle";
59     // Keys in icicle
60     private static final String DIALOG_STATE = "dialogState";
61     private static final String DIALOG_PIN = "dialogPin";
62     private static final String DIALOG_ERROR = "dialogError";
63     private static final String ENABLE_TO_STATE = "enableState";
64
65     // Save and restore inputted PIN code when configuration changed
66     // (ex. portrait<-->landscape) during change PIN code
67     private static final String OLD_PINCODE = "oldPinCode";
68     private static final String NEW_PINCODE = "newPinCode";
69     
70     private static final int MIN_PIN_LENGTH = 4;
71     private static final int MAX_PIN_LENGTH = 8;
72     // Which dialog to show next when popped up
73     private int mDialogState = OFF_MODE;
74     
75     private String mPin;
76     private String mOldPin;
77     private String mNewPin;
78     private String mError;
79     // Are we trying to enable or disable ICC lock?
80     private boolean mToState;
81     
82     private Phone mPhone;
83     
84     private EditPinPreference mPinDialog;
85     private CheckBoxPreference mPinToggle;
86     
87     private Resources mRes;
88
89     // For async handler to identify request type
90     private static final int ENABLE_ICC_PIN_COMPLETE = 100;
91     private static final int CHANGE_ICC_PIN_COMPLETE = 101;
92
93     // For replies from IccCard interface
94     private Handler mHandler = new Handler() {
95         public void handleMessage(Message msg) {
96             AsyncResult ar = (AsyncResult) msg.obj;
97             switch (msg.what) {
98                 case ENABLE_ICC_PIN_COMPLETE:
99                     iccLockChanged(ar.exception == null);
100                     break;
101                 case CHANGE_ICC_PIN_COMPLETE:
102                     iccPinChanged(ar.exception == null);
103                     break;
104             }
105
106             return;
107         }
108     };
109     
110     // For top-level settings screen to query
111     static boolean isIccLockEnabled() {
112         return PhoneFactory.getDefaultPhone().getIccCard().getIccLockEnabled();
113     }
114     
115     static String getSummary(Context context) {
116         Resources res = context.getResources();
117         String summary = isIccLockEnabled() 
118                 ? res.getString(R.string.sim_lock_on)
119                 : res.getString(R.string.sim_lock_off);
120         return summary;
121     }
122
123     @Override
124     protected void onCreate(Bundle savedInstanceState) {
125         super.onCreate(savedInstanceState);
126
127         if (Utils.isMonkeyRunning()) {
128             finish();
129             return;
130         }
131
132         addPreferencesFromResource(R.xml.sim_lock_settings);
133
134         mPinDialog = (EditPinPreference) findPreference(PIN_DIALOG);
135         mPinToggle = (CheckBoxPreference) findPreference(PIN_TOGGLE);
136         if (savedInstanceState != null && savedInstanceState.containsKey(DIALOG_STATE)) {
137             mDialogState = savedInstanceState.getInt(DIALOG_STATE);
138             mPin = savedInstanceState.getString(DIALOG_PIN);
139             mError = savedInstanceState.getString(DIALOG_ERROR);
140             mToState = savedInstanceState.getBoolean(ENABLE_TO_STATE);
141
142             // Restore inputted PIN code
143             switch (mDialogState) {
144                 case ICC_NEW_MODE:
145                     mOldPin = savedInstanceState.getString(OLD_PINCODE);
146                     break;
147
148                 case ICC_REENTER_MODE:
149                     mOldPin = savedInstanceState.getString(OLD_PINCODE);
150                     mNewPin = savedInstanceState.getString(NEW_PINCODE);
151                     break;
152
153                 case ICC_LOCK_MODE:
154                 case ICC_OLD_MODE:
155                 default:
156                     break;
157             }
158         }
159
160         mPinDialog.setOnPinEnteredListener(this);
161         
162         // Don't need any changes to be remembered
163         getPreferenceScreen().setPersistent(false);
164         
165         mPhone = PhoneFactory.getDefaultPhone();
166         mRes = getResources();
167     }
168     
169     @Override
170     protected void onResume() {
171         super.onResume();
172         
173         mPinToggle.setChecked(mPhone.getIccCard().getIccLockEnabled());
174         
175         if (mDialogState != OFF_MODE) {
176             showPinDialog();
177         } else {
178             // Prep for standard click on "Change PIN"
179             resetDialogState();
180         }
181     }
182     
183     @Override
184     protected void onSaveInstanceState(Bundle out) {
185         // Need to store this state for slider open/close
186         // There is one case where the dialog is popped up by the preference
187         // framework. In that case, let the preference framework store the
188         // dialog state. In other cases, where this activity manually launches
189         // the dialog, store the state of the dialog.
190         if (mPinDialog.isDialogOpen()) {
191             out.putInt(DIALOG_STATE, mDialogState);
192             out.putString(DIALOG_PIN, mPinDialog.getEditText().getText().toString());
193             out.putString(DIALOG_ERROR, mError);
194             out.putBoolean(ENABLE_TO_STATE, mToState);
195
196             // Save inputted PIN code
197             switch (mDialogState) {
198                 case ICC_NEW_MODE:
199                     out.putString(OLD_PINCODE, mOldPin);
200                     break;
201
202                 case ICC_REENTER_MODE:
203                     out.putString(OLD_PINCODE, mOldPin);
204                     out.putString(NEW_PINCODE, mNewPin);
205                     break;
206
207                 case ICC_LOCK_MODE:
208                 case ICC_OLD_MODE:
209                 default:
210                     break;
211             }
212         } else {
213             super.onSaveInstanceState(out);
214         }
215     }
216
217     private void showPinDialog() {
218         if (mDialogState == OFF_MODE) {
219             return;
220         }
221         setDialogValues();
222         
223         mPinDialog.showPinDialog();
224     }
225     
226     private void setDialogValues() {
227         mPinDialog.setText(mPin);
228         String message = "";
229         switch (mDialogState) {
230             case ICC_LOCK_MODE:
231                 message = mRes.getString(R.string.sim_enter_pin);
232                 mPinDialog.setDialogTitle(mToState 
233                         ? mRes.getString(R.string.sim_enable_sim_lock)
234                         : mRes.getString(R.string.sim_disable_sim_lock));
235                 break;
236             case ICC_OLD_MODE:
237                 message = mRes.getString(R.string.sim_enter_old);
238                 mPinDialog.setDialogTitle(mRes.getString(R.string.sim_change_pin));
239                 break;
240             case ICC_NEW_MODE:
241                 message = mRes.getString(R.string.sim_enter_new);
242                 mPinDialog.setDialogTitle(mRes.getString(R.string.sim_change_pin));
243                 break;
244             case ICC_REENTER_MODE:
245                 message = mRes.getString(R.string.sim_reenter_new);
246                 mPinDialog.setDialogTitle(mRes.getString(R.string.sim_change_pin));
247                 break;
248         }
249         if (mError != null) {
250             message = mError + "\n" + message;
251             mError = null;
252         }
253         mPinDialog.setDialogMessage(message);
254     }
255
256     public void onPinEntered(EditPinPreference preference, boolean positiveResult) {
257         if (!positiveResult) {
258             resetDialogState();
259             return;
260         }
261         
262         mPin = preference.getText();
263         if (!reasonablePin(mPin)) {
264             // inject error message and display dialog again
265             mError = mRes.getString(R.string.sim_bad_pin);
266             showPinDialog();
267             return;
268         }
269         switch (mDialogState) {
270             case ICC_LOCK_MODE:
271                 tryChangeIccLockState();
272                 break;
273             case ICC_OLD_MODE:
274                 mOldPin = mPin;
275                 mDialogState = ICC_NEW_MODE;
276                 mError = null;
277                 mPin = null;
278                 showPinDialog();
279                 break;
280             case ICC_NEW_MODE:
281                 mNewPin = mPin;
282                 mDialogState = ICC_REENTER_MODE;
283                 mPin = null;
284                 showPinDialog();
285                 break;
286             case ICC_REENTER_MODE:
287                 if (!mPin.equals(mNewPin)) {
288                     mError = mRes.getString(R.string.sim_pins_dont_match);
289                     mDialogState = ICC_NEW_MODE;
290                     mPin = null;
291                     showPinDialog();
292                 } else {
293                     mError = null;
294                     tryChangePin();
295                 }
296                 break;
297         }
298     }
299     
300     public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
301         if (preference == mPinToggle) {
302             // Get the new, preferred state
303             mToState = mPinToggle.isChecked();
304             // Flip it back and pop up pin dialog  
305             mPinToggle.setChecked(!mToState);  
306             mDialogState = ICC_LOCK_MODE;
307             showPinDialog();
308         } else if (preference == mPinDialog) {
309             mDialogState = ICC_OLD_MODE;
310             return false;
311         }
312         return true;
313     }
314
315     private void tryChangeIccLockState() {
316         // Try to change icc lock. If it succeeds, toggle the lock state and 
317         // reset dialog state. Else inject error message and show dialog again.
318         Message callback = Message.obtain(mHandler, ENABLE_ICC_PIN_COMPLETE);
319         mPhone.getIccCard().setIccLockEnabled(mToState, mPin, callback);
320
321     }
322     
323     private void iccLockChanged(boolean success) {
324         if (success) {
325             mPinToggle.setChecked(mToState);
326         } else {
327             Toast.makeText(this, mRes.getString(R.string.sim_lock_failed), Toast.LENGTH_SHORT)
328                     .show();
329         }
330         resetDialogState();
331     }
332
333     private void iccPinChanged(boolean success) {
334         if (!success) {
335             Toast.makeText(this, mRes.getString(R.string.sim_change_failed),
336                     Toast.LENGTH_SHORT)
337                     .show();
338         } else {
339             Toast.makeText(this, mRes.getString(R.string.sim_change_succeeded),
340                     Toast.LENGTH_SHORT)
341                     .show();
342
343         }
344         resetDialogState();
345     }
346
347     private void tryChangePin() {
348         Message callback = Message.obtain(mHandler, CHANGE_ICC_PIN_COMPLETE);
349         mPhone.getIccCard().changeIccLockPassword(mOldPin,
350                 mNewPin, callback);
351     }
352
353     private boolean reasonablePin(String pin) {
354         if (pin == null || pin.length() < MIN_PIN_LENGTH || pin.length() > MAX_PIN_LENGTH) {
355             return false;
356         } else {
357             return true;
358         }
359     }
360
361     private void resetDialogState() {
362         mError = null;
363         mDialogState = ICC_OLD_MODE; // Default for when Change PIN is clicked
364         mPin = "";
365         setDialogValues();
366         mDialogState = OFF_MODE;
367     }
368 }