]> nv-tegra.nvidia Code Review - android/platform/packages/apps/Phone.git/blob - src/com/android/phone/FdnSetting.java
Revert "Remove packages/apps/Phone per b/10976383."
[android/platform/packages/apps/Phone.git] / src / com / android / phone / FdnSetting.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.phone;
18
19 import android.app.ActionBar;
20 import android.app.AlertDialog;
21 import android.content.DialogInterface;
22 import android.os.AsyncResult;
23 import android.os.Bundle;
24 import android.os.Handler;
25 import android.os.Message;
26 import android.util.Log;
27 import android.preference.PreferenceActivity;
28 import android.preference.PreferenceScreen;
29 import android.view.MenuItem;
30 import android.view.WindowManager;
31 import android.widget.Toast;
32
33 import com.android.internal.telephony.CommandException;
34 import com.android.internal.telephony.Phone;
35
36 /**
37  * FDN settings UI for the Phone app.
38  * Rewritten to look and behave closer to the other preferences.
39  */
40 public class FdnSetting extends PreferenceActivity
41         implements EditPinPreference.OnPinEnteredListener, DialogInterface.OnCancelListener {
42
43     private static final String LOG_TAG = PhoneGlobals.LOG_TAG;
44     private static final boolean DBG = false;
45
46     private Phone mPhone;
47
48     /**
49      * Events we handle.
50      * The first is used for toggling FDN enable, the second for the PIN change.
51      */
52     private static final int EVENT_PIN2_ENTRY_COMPLETE = 100;
53     private static final int EVENT_PIN2_CHANGE_COMPLETE = 200;
54
55     // String keys for preference lookup
56     // We only care about the pin preferences here, the manage FDN contacts
57     // Preference is handled solely in xml.
58     private static final String BUTTON_FDN_ENABLE_KEY = "button_fdn_enable_key";
59     private static final String BUTTON_CHANGE_PIN2_KEY = "button_change_pin2_key";
60
61     private EditPinPreference mButtonEnableFDN;
62     private EditPinPreference mButtonChangePin2;
63
64     // State variables
65     private String mOldPin;
66     private String mNewPin;
67     private String mPuk2;
68     private static final int PIN_CHANGE_OLD = 0;
69     private static final int PIN_CHANGE_NEW = 1;
70     private static final int PIN_CHANGE_REENTER = 2;
71     private static final int PIN_CHANGE_PUK = 3;
72     private static final int PIN_CHANGE_NEW_PIN_FOR_PUK = 4;
73     private static final int PIN_CHANGE_REENTER_PIN_FOR_PUK = 5;
74     private int mPinChangeState;
75     private boolean mIsPuk2Locked;    // Indicates we know that we are PUK2 blocked.
76
77     private static final String SKIP_OLD_PIN_KEY = "skip_old_pin_key";
78     private static final String PIN_CHANGE_STATE_KEY = "pin_change_state_key";
79     private static final String OLD_PIN_KEY = "old_pin_key";
80     private static final String NEW_PIN_KEY = "new_pin_key";
81     private static final String DIALOG_MESSAGE_KEY = "dialog_message_key";
82     private static final String DIALOG_PIN_ENTRY_KEY = "dialog_pin_entry_key";
83
84     // size limits for the pin.
85     private static final int MIN_PIN_LENGTH = 4;
86     private static final int MAX_PIN_LENGTH = 8;
87
88     /**
89      * Delegate to the respective handlers.
90      */
91     @Override
92     public void onPinEntered(EditPinPreference preference, boolean positiveResult) {
93         if (preference == mButtonEnableFDN) {
94             toggleFDNEnable(positiveResult);
95         } else if (preference == mButtonChangePin2){
96             updatePINChangeState(positiveResult);
97         }
98     }
99
100     /**
101      * Attempt to toggle FDN activation.
102      */
103     private void toggleFDNEnable(boolean positiveResult) {
104         if (!positiveResult) {
105             return;
106         }
107
108         // validate the pin first, before submitting it to the RIL for FDN enable.
109         String password = mButtonEnableFDN.getText();
110         if (validatePin (password, false)) {
111             // get the relevant data for the icc call
112             boolean isEnabled = mPhone.getIccCard().getIccFdnEnabled();
113             Message onComplete = mFDNHandler.obtainMessage(EVENT_PIN2_ENTRY_COMPLETE);
114
115             // make fdn request
116             mPhone.getIccCard().setIccFdnEnabled(!isEnabled, password, onComplete);
117         } else {
118             // throw up error if the pin is invalid.
119             displayMessage(R.string.invalidPin2);
120         }
121
122         mButtonEnableFDN.setText("");
123     }
124
125     /**
126      * Attempt to change the pin.
127      */
128     private void updatePINChangeState(boolean positiveResult) {
129         if (DBG) log("updatePINChangeState positive=" + positiveResult
130                 + " mPinChangeState=" + mPinChangeState
131                 + " mSkipOldPin=" + mIsPuk2Locked);
132
133         if (!positiveResult) {
134             // reset the state on cancel, either to expect PUK2 or PIN2
135             if (!mIsPuk2Locked) {
136                 resetPinChangeState();
137             } else {
138                 resetPinChangeStateForPUK2();
139             }
140             return;
141         }
142
143         // Progress through the dialog states, generally in this order:
144         //   1. Enter old pin
145         //   2. Enter new pin
146         //   3. Re-Enter new pin
147         // While handling any error conditions that may show up in between.
148         // Also handle the PUK2 entry, if it is requested.
149         //
150         // In general, if any invalid entries are made, the dialog re-
151         // appears with text to indicate what the issue is.
152         switch (mPinChangeState) {
153             case PIN_CHANGE_OLD:
154                 mOldPin = mButtonChangePin2.getText();
155                 mButtonChangePin2.setText("");
156                 // if the pin is not valid, display a message and reset the state.
157                 if (validatePin (mOldPin, false)) {
158                     mPinChangeState = PIN_CHANGE_NEW;
159                     displayPinChangeDialog();
160                 } else {
161                     displayPinChangeDialog(R.string.invalidPin2, true);
162                 }
163                 break;
164             case PIN_CHANGE_NEW:
165                 mNewPin = mButtonChangePin2.getText();
166                 mButtonChangePin2.setText("");
167                 // if the new pin is not valid, display a message and reset the state.
168                 if (validatePin (mNewPin, false)) {
169                     mPinChangeState = PIN_CHANGE_REENTER;
170                     displayPinChangeDialog();
171                 } else {
172                     displayPinChangeDialog(R.string.invalidPin2, true);
173                 }
174                 break;
175             case PIN_CHANGE_REENTER:
176                 // if the re-entered pin is not valid, display a message and reset the state.
177                 if (!mNewPin.equals(mButtonChangePin2.getText())) {
178                     mPinChangeState = PIN_CHANGE_NEW;
179                     mButtonChangePin2.setText("");
180                     displayPinChangeDialog(R.string.mismatchPin2, true);
181                 } else {
182                     // If the PIN is valid, then we submit the change PIN request.
183                     mButtonChangePin2.setText("");
184                     Message onComplete = mFDNHandler.obtainMessage(
185                             EVENT_PIN2_CHANGE_COMPLETE);
186                     mPhone.getIccCard().changeIccFdnPassword(
187                             mOldPin, mNewPin, onComplete);
188                 }
189                 break;
190             case PIN_CHANGE_PUK: {
191                     // Doh! too many incorrect requests, PUK requested.
192                     mPuk2 = mButtonChangePin2.getText();
193                     mButtonChangePin2.setText("");
194                     // if the puk is not valid, display
195                     // a message and reset the state.
196                     if (validatePin (mPuk2, true)) {
197                         mPinChangeState = PIN_CHANGE_NEW_PIN_FOR_PUK;
198                         displayPinChangeDialog();
199                     } else {
200                         displayPinChangeDialog(R.string.invalidPuk2, true);
201                     }
202                 }
203                 break;
204             case PIN_CHANGE_NEW_PIN_FOR_PUK:
205                 mNewPin = mButtonChangePin2.getText();
206                 mButtonChangePin2.setText("");
207                 // if the new pin is not valid, display
208                 // a message and reset the state.
209                 if (validatePin (mNewPin, false)) {
210                     mPinChangeState = PIN_CHANGE_REENTER_PIN_FOR_PUK;
211                     displayPinChangeDialog();
212                 } else {
213                     displayPinChangeDialog(R.string.invalidPin2, true);
214                 }
215                 break;
216             case PIN_CHANGE_REENTER_PIN_FOR_PUK:
217                 // if the re-entered pin is not valid, display
218                 // a message and reset the state.
219                 if (!mNewPin.equals(mButtonChangePin2.getText())) {
220                     mPinChangeState = PIN_CHANGE_NEW_PIN_FOR_PUK;
221                     mButtonChangePin2.setText("");
222                     displayPinChangeDialog(R.string.mismatchPin2, true);
223                 } else {
224                     // Both puk2 and new pin2 are ready to submit
225                     mButtonChangePin2.setText("");
226                     Message onComplete = mFDNHandler.obtainMessage(
227                             EVENT_PIN2_CHANGE_COMPLETE);
228                     mPhone.getIccCard().supplyPuk2(mPuk2, mNewPin, onComplete);
229                 }
230                 break;
231         }
232     }
233
234     /**
235      * Handler for asynchronous replies from the sim.
236      */
237     private final Handler mFDNHandler = new Handler() {
238         @Override
239         public void handleMessage(Message msg) {
240             switch (msg.what) {
241
242                 // when we are enabling FDN, either we are unsuccessful and display
243                 // a toast, or just update the UI.
244                 case EVENT_PIN2_ENTRY_COMPLETE: {
245                         AsyncResult ar = (AsyncResult) msg.obj;
246                         if (ar.exception != null) {
247                             // see if PUK2 is requested and alert the user accordingly.
248                             CommandException ce = (CommandException) ar.exception;
249                             if (ce.getCommandError() == CommandException.Error.SIM_PUK2) {
250                                 // make sure we set the PUK2 state so that we can skip
251                                 // some redundant behaviour.
252                                 displayMessage(R.string.fdn_enable_puk2_requested);
253                                 resetPinChangeStateForPUK2();
254                             } else {
255                                 displayMessage(R.string.pin2_invalid);
256                             }
257                         }
258                         updateEnableFDN();
259                     }
260                     break;
261
262                 // when changing the pin we need to pay attention to whether or not
263                 // the error requests a PUK (usually after too many incorrect tries)
264                 // Set the state accordingly.
265                 case EVENT_PIN2_CHANGE_COMPLETE: {
266                         if (DBG)
267                             log("Handle EVENT_PIN2_CHANGE_COMPLETE");
268                         AsyncResult ar = (AsyncResult) msg.obj;
269                         if (ar.exception != null) {
270                             CommandException ce = (CommandException) ar.exception;
271                             if (ce.getCommandError() == CommandException.Error.SIM_PUK2) {
272                                 // throw an alert dialog on the screen, displaying the
273                                 // request for a PUK2.  set the cancel listener to
274                                 // FdnSetting.onCancel().
275                                 AlertDialog a = new AlertDialog.Builder(FdnSetting.this)
276                                     .setMessage(R.string.puk2_requested)
277                                     .setCancelable(true)
278                                     .setOnCancelListener(FdnSetting.this)
279                                     .create();
280                                 a.getWindow().addFlags(
281                                         WindowManager.LayoutParams.FLAG_DIM_BEHIND);
282                                 a.show();
283                             } else {
284                                 // set the correct error message depending upon the state.
285                                 // Reset the state depending upon or knowledge of the PUK state.
286                                 if (!mIsPuk2Locked) {
287                                     displayMessage(R.string.badPin2);
288                                     resetPinChangeState();
289                                 } else {
290                                     displayMessage(R.string.badPuk2);
291                                     resetPinChangeStateForPUK2();
292                                 }
293                             }
294                         } else {
295                             // reset to normal behaviour on successful change.
296                             displayMessage(R.string.pin2_changed);
297                             resetPinChangeState();
298                         }
299                     }
300                     break;
301             }
302         }
303     };
304
305     /**
306      * Cancel listener for the PUK2 request alert dialog.
307      */
308     @Override
309     public void onCancel(DialogInterface dialog) {
310         // set the state of the preference and then display the dialog.
311         resetPinChangeStateForPUK2();
312         displayPinChangeDialog(0, true);
313     }
314
315     /**
316      * Display a toast for message, like the rest of the settings.
317      */
318     private final void displayMessage(int strId) {
319         Toast.makeText(this, getString(strId), Toast.LENGTH_SHORT)
320             .show();
321     }
322
323     /**
324      * The next two functions are for updating the message field on the dialog.
325      */
326     private final void displayPinChangeDialog() {
327         displayPinChangeDialog(0, true);
328     }
329
330     private final void displayPinChangeDialog(int strId, boolean shouldDisplay) {
331         int msgId;
332         switch (mPinChangeState) {
333             case PIN_CHANGE_OLD:
334                 msgId = R.string.oldPin2Label;
335                 break;
336             case PIN_CHANGE_NEW:
337             case PIN_CHANGE_NEW_PIN_FOR_PUK:
338                 msgId = R.string.newPin2Label;
339                 break;
340             case PIN_CHANGE_REENTER:
341             case PIN_CHANGE_REENTER_PIN_FOR_PUK:
342                 msgId = R.string.confirmPin2Label;
343                 break;
344             case PIN_CHANGE_PUK:
345             default:
346                 msgId = R.string.label_puk2_code;
347                 break;
348         }
349
350         // append the note / additional message, if needed.
351         if (strId != 0) {
352             mButtonChangePin2.setDialogMessage(getText(msgId) + "\n" + getText(strId));
353         } else {
354             mButtonChangePin2.setDialogMessage(msgId);
355         }
356
357         // only display if requested.
358         if (shouldDisplay) {
359             mButtonChangePin2.showPinDialog();
360         }
361     }
362
363     /**
364      * Reset the state of the pin change dialog.
365      */
366     private final void resetPinChangeState() {
367         if (DBG) log("resetPinChangeState");
368         mPinChangeState = PIN_CHANGE_OLD;
369         displayPinChangeDialog(0, false);
370         mOldPin = mNewPin = "";
371         mIsPuk2Locked = false;
372     }
373
374     /**
375      * Reset the state of the pin change dialog solely for PUK2 use.
376      */
377     private final void resetPinChangeStateForPUK2() {
378         if (DBG) log("resetPinChangeStateForPUK2");
379         mPinChangeState = PIN_CHANGE_PUK;
380         displayPinChangeDialog(0, false);
381         mOldPin = mNewPin = mPuk2 = "";
382         mIsPuk2Locked = true;
383     }
384
385     /**
386      * Validate the pin entry.
387      *
388      * @param pin This is the pin to validate
389      * @param isPuk Boolean indicating whether we are to treat
390      * the pin input as a puk.
391      */
392     private boolean validatePin(String pin, boolean isPuk) {
393
394         // for pin, we have 4-8 numbers, or puk, we use only 8.
395         int pinMinimum = isPuk ? MAX_PIN_LENGTH : MIN_PIN_LENGTH;
396
397         // check validity
398         if (pin == null || pin.length() < pinMinimum || pin.length() > MAX_PIN_LENGTH) {
399             return false;
400         } else {
401             return true;
402         }
403     }
404
405     /**
406      * Reflect the updated FDN state in the UI.
407      */
408     private void updateEnableFDN() {
409         if (mPhone.getIccCard().getIccFdnEnabled()) {
410             mButtonEnableFDN.setTitle(R.string.enable_fdn_ok);
411             mButtonEnableFDN.setSummary(R.string.fdn_enabled);
412             mButtonEnableFDN.setDialogTitle(R.string.disable_fdn);
413         } else {
414             mButtonEnableFDN.setTitle(R.string.disable_fdn_ok);
415             mButtonEnableFDN.setSummary(R.string.fdn_disabled);
416             mButtonEnableFDN.setDialogTitle(R.string.enable_fdn);
417         }
418     }
419
420     @Override
421     protected void onCreate(Bundle icicle) {
422         super.onCreate(icicle);
423
424         addPreferencesFromResource(R.xml.fdn_setting);
425
426         mPhone = PhoneGlobals.getPhone();
427
428         //get UI object references
429         PreferenceScreen prefSet = getPreferenceScreen();
430         mButtonEnableFDN = (EditPinPreference) prefSet.findPreference(BUTTON_FDN_ENABLE_KEY);
431         mButtonChangePin2 = (EditPinPreference) prefSet.findPreference(BUTTON_CHANGE_PIN2_KEY);
432
433         //assign click listener and update state
434         mButtonEnableFDN.setOnPinEnteredListener(this);
435         updateEnableFDN();
436
437         mButtonChangePin2.setOnPinEnteredListener(this);
438
439         // Only reset the pin change dialog if we're not in the middle of changing it.
440         if (icicle == null) {
441             resetPinChangeState();
442         } else {
443             mIsPuk2Locked = icicle.getBoolean(SKIP_OLD_PIN_KEY);
444             mPinChangeState = icicle.getInt(PIN_CHANGE_STATE_KEY);
445             mOldPin = icicle.getString(OLD_PIN_KEY);
446             mNewPin = icicle.getString(NEW_PIN_KEY);
447             mButtonChangePin2.setDialogMessage(icicle.getString(DIALOG_MESSAGE_KEY));
448             mButtonChangePin2.setText(icicle.getString(DIALOG_PIN_ENTRY_KEY));
449         }
450
451         ActionBar actionBar = getActionBar();
452         if (actionBar != null) {
453             // android.R.id.home will be triggered in onOptionsItemSelected()
454             actionBar.setDisplayHomeAsUpEnabled(true);
455         }
456     }
457
458     @Override
459     protected void onResume() {
460         super.onResume();
461         mPhone = PhoneGlobals.getPhone();
462         updateEnableFDN();
463     }
464
465     /**
466      * Save the state of the pin change.
467      */
468     @Override
469     protected void onSaveInstanceState(Bundle out) {
470         super.onSaveInstanceState(out);
471         out.putBoolean(SKIP_OLD_PIN_KEY, mIsPuk2Locked);
472         out.putInt(PIN_CHANGE_STATE_KEY, mPinChangeState);
473         out.putString(OLD_PIN_KEY, mOldPin);
474         out.putString(NEW_PIN_KEY, mNewPin);
475         out.putString(DIALOG_MESSAGE_KEY, mButtonChangePin2.getDialogMessage().toString());
476         out.putString(DIALOG_PIN_ENTRY_KEY, mButtonChangePin2.getText());
477     }
478
479     @Override
480     public boolean onOptionsItemSelected(MenuItem item) {
481         final int itemId = item.getItemId();
482         if (itemId == android.R.id.home) {  // See ActionBar#setDisplayHomeAsUpEnabled()
483             CallFeaturesSetting.goUpToTopLevelSetting(this);
484             return true;
485         }
486         return super.onOptionsItemSelected(item);
487     }
488
489     private void log(String msg) {
490         Log.d(LOG_TAG, "FdnSetting: " + msg);
491     }
492 }
493