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.settings.fdn;
18 
19 import android.app.ActionBar;
20 import android.app.FragmentManager;
21 import android.app.FragmentTransaction;
22 import android.content.Context;
23 import android.os.AsyncResult;
24 import android.os.Bundle;
25 import android.os.Handler;
26 import android.os.Message;
27 import android.os.UserManager;
28 import android.preference.PreferenceActivity;
29 import android.preference.PreferenceScreen;
30 import android.util.Log;
31 import android.view.MenuItem;
32 import android.widget.Toast;
33 
34 import com.android.internal.telephony.CommandException;
35 import com.android.internal.telephony.Phone;
36 import com.android.internal.telephony.flags.Flags;
37 import com.android.phone.CallFeaturesSetting;
38 import com.android.phone.PhoneGlobals;
39 import com.android.phone.R;
40 import com.android.phone.SubscriptionInfoHelper;
41 
42 /**
43  * FDN settings UI for the Phone app.
44  * Rewritten to look and behave closer to the other preferences.
45  */
46 public class FdnSetting extends PreferenceActivity
47         implements EditPinPreference.OnPinEnteredListener, Pin2LockedDialogFragment.Listener {
48 
49     private static final String LOG_TAG = PhoneGlobals.LOG_TAG;
50     private static final boolean DBG = false;
51 
52     private SubscriptionInfoHelper mSubscriptionInfoHelper;
53     private Phone mPhone;
54 
55     /**
56      * Events we handle.
57      * The first is used for toggling FDN enable, the second for the PIN change.
58      */
59     private static final int EVENT_PIN2_ENTRY_COMPLETE = 100;
60     private static final int EVENT_PIN2_CHANGE_COMPLETE = 200;
61     private static final int EVENT_PIN2_CHANGE_COMPLETE_TOGGLE_FDN = 300;
62 
63     // String keys for preference lookup
64     private static final String BUTTON_FDN_ENABLE_KEY = "button_fdn_enable_key";
65     private static final String BUTTON_CHANGE_PIN2_KEY = "button_change_pin2_key";
66     private static final String FDN_LIST_PREF_SCREEN_KEY = "fdn_list_pref_screen_key";
67 
68     private EditPinPreference mButtonEnableFDN;
69     private EditPinPreference mButtonChangePin2;
70 
71     // State variables
72     private String mOldPin;
73     private String mNewPin;
74     private String mPuk2;
75     private static final int PIN_CHANGE_OLD = 0;
76     private static final int PIN_CHANGE_NEW = 1;
77     private static final int PIN_CHANGE_REENTER = 2;
78     private static final int PIN_CHANGE_PUK = 3;
79     private static final int PIN_CHANGE_NEW_PIN_FOR_PUK = 4;
80     private static final int PIN_CHANGE_REENTER_PIN_FOR_PUK = 5;
81     private int mPinChangeState;
82     private boolean mIsPuk2Locked;    // Indicates we know that we are PUK2 blocked.
83 
84     private static final String SKIP_OLD_PIN_KEY = "skip_old_pin_key";
85     private static final String PIN_CHANGE_STATE_KEY = "pin_change_state_key";
86     private static final String OLD_PIN_KEY = "old_pin_key";
87     private static final String NEW_PIN_KEY = "new_pin_key";
88     private static final String PUK_KEY = "puk_key";
89     private static final String DIALOG_MESSAGE_KEY = "dialog_message_key";
90     private static final String DIALOG_PIN_ENTRY_KEY = "dialog_pin_entry_key";
91     private static final String FDN_DIALOG_MESSAGE_KEY = "fdn_dialog_message_key";
92     private static final String FDN_DIALOG_PIN_ENTRY_KEY = "fdn_dialog_pin_entry_key";
93 
94     // size limits for the pin.
95     private static final int MIN_PIN_LENGTH = 4;
96     private static final int MAX_PIN_LENGTH = 8;
97 
98     /**
99      * Delegate to the respective handlers.
100      */
101     @Override
onPinEntered(EditPinPreference preference, boolean positiveResult)102     public void onPinEntered(EditPinPreference preference, boolean positiveResult) {
103         if (preference == mButtonEnableFDN && (!mIsPuk2Locked || !positiveResult)) {
104             toggleFDNEnable(positiveResult);
105         } else {
106             updatePINChangeState(preference, positiveResult);
107         }
108     }
109 
110     /**
111      * Attempt to toggle FDN activation.
112      */
toggleFDNEnable(boolean positiveResult)113     private void toggleFDNEnable(boolean positiveResult) {
114         if (!positiveResult) {
115             // reset the state on cancel, either to expect PUK2 or PIN2
116             if (!mIsPuk2Locked) {
117                 resetPinChangeState();
118             } else {
119                 resetPinChangeStateForPUK2();
120             }
121             return;
122         }
123 
124         // validate the pin first, before submitting it to the RIL for FDN enable.
125         String password = mButtonEnableFDN.getText();
126         if (validatePin (password, false)) {
127             // get the relevant data for the icc call
128             boolean isEnabled = mPhone.getIccCard().getIccFdnEnabled();
129             Message onComplete = mFDNHandler.obtainMessage(EVENT_PIN2_ENTRY_COMPLETE);
130 
131             // make fdn request
132             mPhone.getIccCard().setIccFdnEnabled(!isEnabled, password, onComplete);
133         } else {
134             // throw up error if the pin is invalid.
135             displayMessage(R.string.invalidPin2);
136         }
137 
138         mButtonEnableFDN.setText("");
139     }
140 
141     /**
142      * Attempt to change the pin.
143      */
updatePINChangeState(EditPinPreference button, boolean positiveResult)144     private void updatePINChangeState(EditPinPreference button, boolean positiveResult) {
145         if (DBG) log("updatePINChangeState positive=" + positiveResult
146                 + " mPinChangeState=" + mPinChangeState
147                 + " mIsPuk2Locked=" + mIsPuk2Locked);
148 
149         if (!positiveResult) {
150             // reset the state on cancel, either to expect PUK2 or PIN2
151             if (!mIsPuk2Locked) {
152                 resetPinChangeState();
153             } else {
154                 resetPinChangeStateForPUK2();
155             }
156             return;
157         }
158 
159         // Progress through the dialog states, generally in this order:
160         //   1. Enter old pin
161         //   2. Enter new pin
162         //   3. Re-Enter new pin
163         // While handling any error conditions that may show up in between.
164         // Also handle the PUK2 entry, if it is requested.
165         //
166         // In general, if any invalid entries are made, the dialog re-
167         // appears with text to indicate what the issue is.
168         switch (mPinChangeState) {
169             case PIN_CHANGE_OLD:
170                 mOldPin = button.getText();
171                 button.setText("");
172                 // if the pin is not valid, display a message and reset the state.
173                 if (validatePin (mOldPin, false)) {
174                     mPinChangeState = PIN_CHANGE_NEW;
175                     displayPinChangeDialog(button);
176                 } else {
177                     displayPinChangeDialog(button, R.string.invalidPin2, true);
178                 }
179                 break;
180             case PIN_CHANGE_NEW:
181                 mNewPin = button.getText();
182                 button.setText("");
183                 // if the new pin is not valid, display a message and reset the state.
184                 if (validatePin (mNewPin, false)) {
185                     mPinChangeState = PIN_CHANGE_REENTER;
186                     displayPinChangeDialog(button);
187                 } else {
188                     displayPinChangeDialog(button, R.string.invalidPin2, true);
189                 }
190                 break;
191             case PIN_CHANGE_REENTER:
192                 if (validatePin(button.getText(), false)) {
193                     // if the re-entered pin is not valid, display a message and reset the state.
194                     if (!mNewPin.equals(button.getText())) {
195                         mPinChangeState = PIN_CHANGE_NEW;
196                         button.setText("");
197                         displayPinChangeDialog(button, R.string.mismatchPin2, true);
198                     } else {
199                         // If the PIN is valid, then we submit the change PIN request or
200                         // display the PUK2 dialog if we KNOW that we're PUK2 locked.
201                         button.setText("");
202                         Message onComplete = mFDNHandler.obtainMessage(
203                                 EVENT_PIN2_CHANGE_COMPLETE);
204                         if (!mIsPuk2Locked) {
205                             mPhone.getIccCard().changeIccFdnPassword(mOldPin,
206                                     mNewPin, onComplete);
207                         } else {
208                             mPhone.getIccCard().supplyPuk2(mPuk2, mNewPin,
209                                     onComplete);
210                         }
211                     }
212                 } else {
213                     button.setText("");
214                     displayPinChangeDialog(button, R.string.invalidPin2, true);
215                 }
216                 break;
217             case PIN_CHANGE_PUK:
218                 // Doh! too many incorrect requests, PUK requested.
219                 mPuk2 = button.getText();
220                 button.setText("");
221                 // if the puk is not valid, display
222                 // a message and reset the state.
223                 if (validatePin(mPuk2, true)) {
224                     mPinChangeState = PIN_CHANGE_NEW_PIN_FOR_PUK;
225                     displayPinChangeDialog(button);
226                 } else {
227                     displayPinChangeDialog(button, R.string.invalidPuk2, true);
228                 }
229                 break;
230             case PIN_CHANGE_NEW_PIN_FOR_PUK:
231                 mNewPin = button.getText();
232                 button.setText("");
233                 // if the new pin is not valid, display
234                 // a message and reset the state.
235                 if (validatePin (mNewPin, false)) {
236                     mPinChangeState = PIN_CHANGE_REENTER_PIN_FOR_PUK;
237                     displayPinChangeDialog(button);
238                 } else {
239                     displayPinChangeDialog(button, R.string.invalidPin2, true);
240                 }
241                 break;
242             case PIN_CHANGE_REENTER_PIN_FOR_PUK:
243                 // if the re-entered pin is not valid, display
244                 // a message and reset the state.
245                 if (!mNewPin.equals(button.getText())) {
246                     mPinChangeState = PIN_CHANGE_NEW_PIN_FOR_PUK;
247                     button.setText("");
248                     displayPinChangeDialog(button, R.string.mismatchPin2, true);
249                 } else {
250                     // Both puk2 and new pin2 are ready to submit
251                     Message onComplete = null;
252                     if (button == mButtonChangePin2) {
253                         button.setText("");
254                         onComplete = mFDNHandler.obtainMessage(EVENT_PIN2_CHANGE_COMPLETE);
255                     } else {
256                         onComplete = mFDNHandler.obtainMessage(
257                                 EVENT_PIN2_CHANGE_COMPLETE_TOGGLE_FDN);
258                     }
259                     mPhone.getIccCard().supplyPuk2(mPuk2, mNewPin, onComplete);
260                 }
261                 break;
262         }
263     }
264 
265     /**
266      * Handler for asynchronous replies from the sim.
267      */
268     private final Handler mFDNHandler = new Handler() {
269         @Override
270         public void handleMessage(Message msg) {
271             switch (msg.what) {
272 
273                 // when we are enabling FDN, either we are unsuccessful and display
274                 // a toast, or just update the UI.
275                 case EVENT_PIN2_ENTRY_COMPLETE: {
276                         if (DBG) log("Handle EVENT_PIN2_ENTRY_COMPLETE");
277                         AsyncResult ar = (AsyncResult) msg.obj;
278                         if (ar.exception != null) {
279                             if (ar.exception instanceof CommandException) {
280                                 int attemptsRemaining = msg.arg1;
281                                 // see if PUK2 is requested and alert the user accordingly.
282                                 CommandException.Error e =
283                                         ((CommandException) ar.exception).getCommandError();
284                                 switch (e) {
285                                     case SIM_PUK2:
286                                         showPin2OrPuk2LockedDialog(Pin2LockedDialogFragment
287                                                 .DIALOG_ID_PUK2_REQUESTED_ON_PIN_ENTRY);
288                                         break;
289                                     case PASSWORD_INCORRECT:
290                                         displayMessage(R.string.pin2_invalid, attemptsRemaining);
291                                         break;
292                                     default:
293                                         displayMessage(R.string.fdn_failed, attemptsRemaining);
294                                         break;
295                                 }
296                             } else {
297                                 displayMessage(R.string.pin2_error_exception);
298                             }
299                         }
300                         updateEnableFDN();
301                     }
302                     break;
303 
304                 // when changing the pin we need to pay attention to whether or not
305                 // the error requests a PUK (usually after too many incorrect tries)
306                 // Set the state accordingly.
307                 case EVENT_PIN2_CHANGE_COMPLETE:
308                 case EVENT_PIN2_CHANGE_COMPLETE_TOGGLE_FDN: {
309                         if (DBG)
310                             log("Handle EVENT_PIN2_CHANGE_COMPLETE");
311                         AsyncResult ar = (AsyncResult) msg.obj;
312                         if (ar.exception != null) {
313                             if (ar.exception instanceof CommandException) {
314                                 int attemptsRemaining = msg.arg1;
315                                 log("Handle EVENT_PIN2_CHANGE_COMPLETE attemptsRemaining="
316                                         + attemptsRemaining);
317                                 CommandException ce = (CommandException) ar.exception;
318                                 if (ce.getCommandError() == CommandException.Error.SIM_PUK2) {
319                                     // throw an alert dialog on the screen, displaying the
320                                     // request for a PUK2.
321                                     showPin2OrPuk2LockedDialog(Pin2LockedDialogFragment
322                                             .DIALOG_ID_PUK2_REQUESTED_ON_PIN_CHANGED);
323                                 } else {
324                                     if (mIsPuk2Locked && attemptsRemaining == 0) {
325                                         showPin2OrPuk2LockedDialog(Pin2LockedDialogFragment
326                                                 .DIALOG_ID_PUK2_LOCKED_OUT);
327                                     } else {
328                                         // set the correct error message depending upon the state.
329                                         // Reset the state depending upon or knowledge of the PUK
330                                         // state.
331                                         if (!mIsPuk2Locked) {
332                                             displayMessage(R.string.badPin2, attemptsRemaining);
333                                             resetPinChangeState();
334                                         } else {
335                                             displayMessage(R.string.badPuk2, attemptsRemaining);
336                                             resetPinChangeStateForPUK2();
337                                         }
338                                     }
339                                 }
340                             } else {
341                                 displayMessage(R.string.pin2_error_exception);
342                             }
343                         } else {
344                             if (mPinChangeState == PIN_CHANGE_PUK) {
345                                 displayMessage(R.string.pin2_unblocked);
346                             } else {
347                                 displayMessage(R.string.pin2_changed);
348                             }
349 
350                             // reset to normal behaviour on successful change.
351                             if (msg.what == EVENT_PIN2_CHANGE_COMPLETE_TOGGLE_FDN) {
352                                 log("Handle EVENT_PIN2_CHANGE_COMPLETE_TOGGLE_FDN");
353                                 // activate/deactivate FDN
354                                 toggleFDNEnable(true);
355                             }
356                             resetPinChangeState();
357                         }
358                     }
359                     mButtonChangePin2.setText("");
360                     mButtonEnableFDN.setText("");
361                     break;
362             }
363         }
364     };
365 
366     /**
367      * Display a toast for message, like the rest of the settings.
368      */
displayMessage(int strId, int attemptsRemaining)369     private void displayMessage(int strId, int attemptsRemaining) {
370         String s = getString(strId);
371         if ((strId == R.string.badPin2) || (strId == R.string.badPuk2) ||
372                 (strId == R.string.pin2_invalid)) {
373             if (attemptsRemaining >= 0) {
374                 s = getString(strId) + getString(R.string.pin2_attempts, attemptsRemaining);
375             } else {
376                 s = getString(strId);
377             }
378         }
379         log("displayMessage: attemptsRemaining=" + attemptsRemaining + " s=" + s);
380         Toast.makeText(this, s, Toast.LENGTH_SHORT).show();
381     }
382 
displayMessage(int strId)383     private void displayMessage(int strId) {
384         displayMessage(strId, -1);
385     }
386 
387     /**
388      * The next two functions are for updating the message field on the dialog.
389      */
displayPinChangeDialog(EditPinPreference button)390     private void displayPinChangeDialog(EditPinPreference button) {
391         displayPinChangeDialog(button, 0, true);
392     }
393 
displayPinChangeDialog(EditPinPreference button, int strId, boolean shouldDisplay)394     private void displayPinChangeDialog(EditPinPreference button,
395             int strId, boolean shouldDisplay) {
396         int msgId;
397         switch (mPinChangeState) {
398             case PIN_CHANGE_OLD:
399                 if (button == mButtonEnableFDN) {
400                     msgId = R.string.enter_pin2_text;
401                 } else {
402                     msgId = R.string.oldPin2Label;
403                 }
404                 break;
405             case PIN_CHANGE_NEW:
406             case PIN_CHANGE_NEW_PIN_FOR_PUK:
407                 msgId = R.string.newPin2Label;
408                 break;
409             case PIN_CHANGE_REENTER:
410             case PIN_CHANGE_REENTER_PIN_FOR_PUK:
411                 msgId = R.string.confirmPin2Label;
412                 break;
413             case PIN_CHANGE_PUK:
414             default:
415                 msgId = R.string.label_puk2_code;
416                 break;
417         }
418 
419         // append the note / additional message, if needed.
420         if (strId != 0) {
421             button.setDialogMessage(getText(msgId) + "\n" + getText(strId));
422         } else {
423             button.setDialogMessage(msgId);
424         }
425 
426         // only display if requested.
427         if (shouldDisplay) {
428             button.showPinDialog();
429         }
430     }
431 
432     /**
433      * Reset the state of the pin change dialog.
434      */
resetPinChangeState()435     private final void resetPinChangeState() {
436         if (DBG) log("resetPinChangeState");
437         mPinChangeState = PIN_CHANGE_OLD;
438         displayPinChangeDialog(mButtonEnableFDN, 0, false);
439         displayPinChangeDialog(mButtonChangePin2, 0, false);
440         mOldPin = mNewPin = "";
441         mIsPuk2Locked = false;
442     }
443 
444     /**
445      * Reset the state of the pin change dialog solely for PUK2 use.
446      */
resetPinChangeStateForPUK2()447     private final void resetPinChangeStateForPUK2() {
448         if (DBG) log("resetPinChangeStateForPUK2");
449         mPinChangeState = PIN_CHANGE_PUK;
450         displayPinChangeDialog(mButtonEnableFDN, 0, false);
451         displayPinChangeDialog(mButtonChangePin2, 0, false);
452         mOldPin = mNewPin = mPuk2 = "";
453         mIsPuk2Locked = true;
454     }
455 
456     /**
457      * Validate the pin entry.
458      *
459      * @param pin This is the pin to validate
460      * @param isPuk Boolean indicating whether we are to treat
461      * the pin input as a puk.
462      */
validatePin(String pin, boolean isPuk)463     private boolean validatePin(String pin, boolean isPuk) {
464 
465         // for pin, we have 4-8 numbers, or puk, we use only 8.
466         int pinMinimum = isPuk ? MAX_PIN_LENGTH : MIN_PIN_LENGTH;
467 
468         // check validity
469         if (pin == null || pin.length() < pinMinimum || pin.length() > MAX_PIN_LENGTH) {
470             return false;
471         } else {
472             return true;
473         }
474     }
475 
476     /**
477      * Reflect the updated FDN state in the UI.
478      */
updateEnableFDN()479     private void updateEnableFDN() {
480         if (mPhone.getIccCard().getIccFdnEnabled()) {
481             mButtonEnableFDN.setTitle(R.string.enable_fdn_ok);
482             mButtonEnableFDN.setSummary(R.string.fdn_enabled);
483             mButtonEnableFDN.setDialogTitle(R.string.disable_fdn);
484         } else {
485             mButtonEnableFDN.setTitle(R.string.disable_fdn_ok);
486             mButtonEnableFDN.setSummary(R.string.fdn_disabled);
487             mButtonEnableFDN.setDialogTitle(R.string.enable_fdn);
488         }
489     }
490 
491     /**
492     * Reflect the updated change PIN2 state in the UI.
493     */
updateChangePIN2()494     private void updateChangePIN2() {
495         if (mPhone.getIccCard().getIccPuk2Blocked()) {
496             showPin2OrPuk2LockedDialog(Pin2LockedDialogFragment.DIALOG_ID_PUK2_LOCKED_OUT);
497             resetPinChangeStateForPUK2();
498         } else if (mPhone.getIccCard().getIccPin2Blocked()) {
499             // If the pin2 is blocked, the state of the change pin2 dialog
500             // should be set for puk2 use (that is, the user should be prompted
501             // to enter puk2 code instead of old pin2).
502             resetPinChangeStateForPUK2();
503         } else {
504             resetPinChangeState();
505         }
506     }
507 
508     @Override
onCreate(Bundle icicle)509     protected void onCreate(Bundle icicle) {
510         super.onCreate(icicle);
511 
512         mSubscriptionInfoHelper = new SubscriptionInfoHelper(this, getIntent());
513         mPhone = mSubscriptionInfoHelper.getPhone();
514 
515         addPreferencesFromResource(R.xml.fdn_setting);
516 
517         //get UI object references
518         PreferenceScreen prefSet = getPreferenceScreen();
519         mButtonEnableFDN = (EditPinPreference) prefSet.findPreference(BUTTON_FDN_ENABLE_KEY);
520         mButtonChangePin2 = (EditPinPreference) prefSet.findPreference(BUTTON_CHANGE_PIN2_KEY);
521 
522         //assign click listener and update state
523         mButtonEnableFDN.setOnPinEnteredListener(this);
524         updateEnableFDN();
525 
526         mButtonChangePin2.setOnPinEnteredListener(this);
527 
528         PreferenceScreen fdnListPref =
529                 (PreferenceScreen) prefSet.findPreference(FDN_LIST_PREF_SCREEN_KEY);
530         fdnListPref.setIntent(mSubscriptionInfoHelper.getIntent(FdnList.class));
531 
532         // Only reset the pin change dialog if we're not in the middle of changing it.
533         if (icicle == null) {
534             resetPinChangeState();
535         } else {
536             mIsPuk2Locked = icicle.getBoolean(SKIP_OLD_PIN_KEY);
537             mPinChangeState = icicle.getInt(PIN_CHANGE_STATE_KEY);
538             mOldPin = icicle.getString(OLD_PIN_KEY);
539             mNewPin = icicle.getString(NEW_PIN_KEY);
540             mPuk2 = icicle.getString(PUK_KEY);
541             mButtonChangePin2.setDialogMessage(
542                     icicle.getString(DIALOG_MESSAGE_KEY));
543             mButtonChangePin2.setText(
544                     icicle.getString(DIALOG_PIN_ENTRY_KEY));
545             mButtonEnableFDN.setDialogMessage(
546                     icicle.getString(FDN_DIALOG_MESSAGE_KEY));
547             mButtonEnableFDN.setText(icicle.getString(FDN_DIALOG_PIN_ENTRY_KEY));
548         }
549 
550         ActionBar actionBar = getActionBar();
551         if (actionBar != null) {
552             // android.R.id.home will be triggered in onOptionsItemSelected()
553             actionBar.setDisplayHomeAsUpEnabled(true);
554             mSubscriptionInfoHelper.setActionBarTitle(
555                     actionBar, getResources(), R.string.fdn_with_label);
556         }
557     }
558 
559     @Override
onResume()560     protected void onResume() {
561         super.onResume();
562         mPhone = mSubscriptionInfoHelper.getPhone();
563         updateEnableFDN();
564         updateChangePIN2();
565     }
566 
567     /**
568      * Save the state of the pin change.
569      */
570     @Override
onSaveInstanceState(Bundle out)571     protected void onSaveInstanceState(Bundle out) {
572         super.onSaveInstanceState(out);
573         out.putBoolean(SKIP_OLD_PIN_KEY, mIsPuk2Locked);
574         out.putInt(PIN_CHANGE_STATE_KEY, mPinChangeState);
575         out.putString(OLD_PIN_KEY, mOldPin);
576         out.putString(NEW_PIN_KEY, mNewPin);
577         out.putString(PUK_KEY, mPuk2);
578         if (mButtonChangePin2.isEnabled()) {
579             out.putString(DIALOG_MESSAGE_KEY, mButtonChangePin2.getDialogMessage().toString());
580             out.putString(DIALOG_PIN_ENTRY_KEY, mButtonChangePin2.getText());
581         }
582         if (mButtonEnableFDN.isEnabled()) {
583             CharSequence dialogMsg = mButtonEnableFDN.getDialogMessage();
584             if (dialogMsg != null) {
585                 out.putString(FDN_DIALOG_MESSAGE_KEY,
586                         mButtonEnableFDN.getDialogMessage().toString());
587             }
588             out.putString(FDN_DIALOG_PIN_ENTRY_KEY, mButtonEnableFDN.getText());
589         }
590     }
591 
592     @Override
onOptionsItemSelected(MenuItem item)593     public boolean onOptionsItemSelected(MenuItem item) {
594         final int itemId = item.getItemId();
595         if (itemId == android.R.id.home) {  // See ActionBar#setDisplayHomeAsUpEnabled()
596             CallFeaturesSetting.goUpToTopLevelSetting(this, mSubscriptionInfoHelper);
597             return true;
598         }
599         return super.onOptionsItemSelected(item);
600     }
601 
log(String msg)602     private void log(String msg) {
603         Log.d(LOG_TAG, "FdnSetting: " + msg);
604     }
605 
606     @Override
onRequestPuk2(int id)607     public void onRequestPuk2(int id) {
608         resetPinChangeStateForPUK2();
609         final EditPinPreference button =
610                 (id == Pin2LockedDialogFragment.DIALOG_ID_PUK2_REQUESTED_ON_PIN_CHANGED)
611                         ? mButtonChangePin2 : mButtonEnableFDN;
612         displayPinChangeDialog(button, 0, true);
613     }
614 
showPin2OrPuk2LockedDialog(int id)615     private void showPin2OrPuk2LockedDialog(int id) {
616         final FragmentManager fragmentManager = getFragmentManager();
617         Pin2LockedDialogFragment dialogFragment = (Pin2LockedDialogFragment) fragmentManager
618                 .findFragmentByTag(Pin2LockedDialogFragment.TAG_PIN2_LOCKED_DIALOG);
619         if (dialogFragment == null) {
620             dialogFragment = new Pin2LockedDialogFragment();
621             Bundle args = new Bundle();
622             args.putInt(Pin2LockedDialogFragment.KEY_DIALOG_ID, id);
623             dialogFragment.setArguments(args);
624             dialogFragment.show(fragmentManager, Pin2LockedDialogFragment.TAG_PIN2_LOCKED_DIALOG);
625         } else {
626             FragmentTransaction transaction = fragmentManager.beginTransaction();
627             transaction.show(dialogFragment);
628             transaction.commitNow();
629         }
630     }
631 }
632 
633