UiccCardApplication.java revision cbaa45bbf2cab852b6c9c3a887e9f803d4e857ea
1/*
2 * Copyright (C) 2006, 2012 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.internal.telephony.uicc;
18
19import android.content.Context;
20import android.os.AsyncResult;
21import android.os.Handler;
22import android.os.Message;
23import android.os.Registrant;
24import android.os.RegistrantList;
25import android.telephony.Rlog;
26
27import com.android.internal.telephony.CommandsInterface;
28import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppState;
29import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
30import com.android.internal.telephony.uicc.IccCardApplicationStatus.PersoSubState;
31import com.android.internal.telephony.uicc.IccCardStatus.PinState;
32
33import java.io.FileDescriptor;
34import java.io.PrintWriter;
35
36/**
37 * {@hide}
38 */
39public class UiccCardApplication {
40    private static final String LOG_TAG = "UiccCardApplication";
41    private static final boolean DBG = true;
42
43    private static final int EVENT_QUERY_FACILITY_FDN_DONE = 1;
44    private static final int EVENT_CHANGE_FACILITY_FDN_DONE = 2;
45    private static final int EVENT_QUERY_FACILITY_LOCK_DONE = 3;
46    private static final int EVENT_CHANGE_FACILITY_LOCK_DONE = 4;
47
48    private final Object  mLock = new Object();
49    private UiccCard      mUiccCard; //parent
50    private AppState      mAppState;
51    private AppType       mAppType;
52    private PersoSubState mPersoSubState;
53    private String        mAid;
54    private String        mAppLabel;
55    private boolean       mPin1Replaced;
56    private PinState      mPin1State;
57    private PinState      mPin2State;
58    private boolean       mIccFdnEnabled;
59    private boolean       mDesiredFdnEnabled;
60    private boolean       mIccLockEnabled;
61    private boolean       mDesiredPinLocked;
62
63    private CommandsInterface mCi;
64    private Context mContext;
65    private IccRecords mIccRecords;
66    private IccFileHandler mIccFh;
67
68    private boolean mDestroyed;//set to true once this App is commanded to be disposed of.
69
70    private RegistrantList mReadyRegistrants = new RegistrantList();
71    private RegistrantList mPinLockedRegistrants = new RegistrantList();
72    private RegistrantList mNetworkLockedRegistrants = new RegistrantList();
73
74    UiccCardApplication(UiccCard uiccCard,
75                        IccCardApplicationStatus as,
76                        Context c,
77                        CommandsInterface ci) {
78        if (DBG) log("Creating UiccApp: " + as);
79        mUiccCard = uiccCard;
80        mAppState = as.app_state;
81        mAppType = as.app_type;
82        mPersoSubState = as.perso_substate;
83        mAid = as.aid;
84        mAppLabel = as.app_label;
85        mPin1Replaced = (as.pin1_replaced != 0);
86        mPin1State = as.pin1;
87        mPin2State = as.pin2;
88
89        mContext = c;
90        mCi = ci;
91
92        mIccFh = createIccFileHandler(as.app_type);
93        mIccRecords = createIccRecords(as.app_type, mContext, mCi);
94        if (mAppState == AppState.APPSTATE_READY) {
95            queryFdn();
96            queryPin1State();
97        }
98    }
99
100    void update (IccCardApplicationStatus as, Context c, CommandsInterface ci) {
101        synchronized (mLock) {
102            if (mDestroyed) {
103                loge("Application updated after destroyed! Fix me!");
104                return;
105            }
106
107            if (DBG) log(mAppType + " update. New " + as);
108            mContext = c;
109            mCi = ci;
110            AppType oldAppType = mAppType;
111            AppState oldAppState = mAppState;
112            PersoSubState oldPersoSubState = mPersoSubState;
113            mAppType = as.app_type;
114            mAppState = as.app_state;
115            mPersoSubState = as.perso_substate;
116            mAid = as.aid;
117            mAppLabel = as.app_label;
118            mPin1Replaced = (as.pin1_replaced != 0);
119            mPin1State = as.pin1;
120            mPin2State = as.pin2;
121
122            if (mAppType != oldAppType) {
123                if (mIccFh != null) { mIccFh.dispose();}
124                if (mIccRecords != null) { mIccRecords.dispose();}
125                mIccFh = createIccFileHandler(as.app_type);
126                mIccRecords = createIccRecords(as.app_type, c, ci);
127            }
128
129            if (mPersoSubState != oldPersoSubState &&
130                    mPersoSubState == PersoSubState.PERSOSUBSTATE_SIM_NETWORK) {
131                notifyNetworkLockedRegistrantsIfNeeded(null);
132            }
133
134            if (mAppState != oldAppState) {
135                if (DBG) log(oldAppType + " changed state: " + oldAppState + " -> " + mAppState);
136                // If the app state turns to APPSTATE_READY, then query FDN status,
137                //as it might have failed in earlier attempt.
138                if (mAppState == AppState.APPSTATE_READY) {
139                    queryFdn();
140                    queryPin1State();
141                }
142                notifyPinLockedRegistrantsIfNeeded(null);
143                notifyReadyRegistrantsIfNeeded(null);
144            }
145        }
146    }
147
148    void dispose() {
149        synchronized (mLock) {
150            if (DBG) log(mAppType + " being Disposed");
151            mDestroyed = true;
152            if (mIccRecords != null) { mIccRecords.dispose();}
153            if (mIccFh != null) { mIccFh.dispose();}
154            mIccRecords = null;
155            mIccFh = null;
156        }
157    }
158
159    private IccRecords createIccRecords(AppType type, Context c, CommandsInterface ci) {
160        if (type == AppType.APPTYPE_USIM || type == AppType.APPTYPE_SIM) {
161            return new SIMRecords(this, c, ci);
162        } else if (type == AppType.APPTYPE_RUIM || type == AppType.APPTYPE_CSIM){
163            return new RuimRecords(this, c, ci);
164        } else if (type == AppType.APPTYPE_ISIM) {
165            return new IsimUiccRecords(this, c, ci);
166        } else {
167            // Unknown app type (maybe detection is still in progress)
168            return null;
169        }
170    }
171
172    private IccFileHandler createIccFileHandler(AppType type) {
173        switch (type) {
174            case APPTYPE_SIM:
175                return new SIMFileHandler(this, mAid, mCi);
176            case APPTYPE_RUIM:
177                return new RuimFileHandler(this, mAid, mCi);
178            case APPTYPE_USIM:
179                return new UsimFileHandler(this, mAid, mCi);
180            case APPTYPE_CSIM:
181                return new CsimFileHandler(this, mAid, mCi);
182            case APPTYPE_ISIM:
183                return new IsimFileHandler(this, mAid, mCi);
184            default:
185                return null;
186        }
187    }
188
189    /** Assumes mLock is held. */
190    private void queryFdn() {
191        //This shouldn't change run-time. So needs to be called only once.
192        int serviceClassX;
193
194        serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE +
195                        CommandsInterface.SERVICE_CLASS_DATA +
196                        CommandsInterface.SERVICE_CLASS_FAX;
197        mCi.queryFacilityLockForApp (
198                CommandsInterface.CB_FACILITY_BA_FD, "", serviceClassX,
199                mAid, mHandler.obtainMessage(EVENT_QUERY_FACILITY_FDN_DONE));
200    }
201    /**
202     * Interpret EVENT_QUERY_FACILITY_LOCK_DONE
203     * @param ar is asyncResult of Query_Facility_Locked
204     */
205    private void onQueryFdnEnabled(AsyncResult ar) {
206        synchronized (mLock) {
207            if (ar.exception != null) {
208                if (DBG) log("Error in querying facility lock:" + ar.exception);
209                return;
210            }
211
212            int[] ints = (int[])ar.result;
213            if(ints.length != 0) {
214                mIccFdnEnabled = (0!=ints[0]);
215                if (DBG) log("Query facility lock : "  + mIccFdnEnabled);
216            } else {
217                loge("Bogus facility lock response");
218            }
219        }
220    }
221
222    private void onChangeFdnDone(AsyncResult ar) {
223        synchronized (mLock) {
224            if (ar.exception == null) {
225                mIccFdnEnabled = mDesiredFdnEnabled;
226                if (DBG) log("EVENT_CHANGE_FACILITY_FDN_DONE: " +
227                        "mIccFdnEnabled=" + mIccFdnEnabled);
228            } else {
229                loge("Error change facility fdn with exception " + ar.exception);
230            }
231            Message response = (Message)ar.userObj;
232            AsyncResult.forMessage(response).exception = ar.exception;
233            response.sendToTarget();
234        }
235    }
236
237    /** REMOVE when mIccLockEnabled is not needed, assumes mLock is held */
238    private void queryPin1State() {
239        int serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE +
240                CommandsInterface.SERVICE_CLASS_DATA +
241                CommandsInterface.SERVICE_CLASS_FAX;
242        mCi.queryFacilityLockForApp (
243            CommandsInterface.CB_FACILITY_BA_SIM, "", serviceClassX,
244            mAid, mHandler.obtainMessage(EVENT_QUERY_FACILITY_LOCK_DONE));
245    }
246
247    /** REMOVE when mIccLockEnabled is not needed*/
248    private void onQueryFacilityLock(AsyncResult ar) {
249        synchronized (mLock) {
250            if(ar.exception != null) {
251                if (DBG) log("Error in querying facility lock:" + ar.exception);
252                return;
253            }
254
255            int[] ints = (int[])ar.result;
256            if(ints.length != 0) {
257                if (DBG) log("Query facility lock : "  + ints[0]);
258
259                mIccLockEnabled = (ints[0] != 0);
260
261                if (mIccLockEnabled) {
262                    mPinLockedRegistrants.notifyRegistrants();
263                }
264
265                // Sanity check: we expect mPin1State to match mIccLockEnabled.
266                // When mPin1State is DISABLED mIccLockEanbled should be false.
267                // When mPin1State is ENABLED mIccLockEnabled should be true.
268                //
269                // Here we validate these assumptions to assist in identifying which ril/radio's
270                // have not correctly implemented GET_SIM_STATUS
271                switch (mPin1State) {
272                    case PINSTATE_DISABLED:
273                        if (mIccLockEnabled) {
274                            loge("QUERY_FACILITY_LOCK:enabled GET_SIM_STATUS.Pin1:disabled."
275                                    + " Fixme");
276                        }
277                        break;
278                    case PINSTATE_ENABLED_NOT_VERIFIED:
279                    case PINSTATE_ENABLED_VERIFIED:
280                    case PINSTATE_ENABLED_BLOCKED:
281                    case PINSTATE_ENABLED_PERM_BLOCKED:
282                        if (!mIccLockEnabled) {
283                            loge("QUERY_FACILITY_LOCK:disabled GET_SIM_STATUS.Pin1:enabled."
284                                    + " Fixme");
285                        }
286                    case PINSTATE_UNKNOWN:
287                    default:
288                        if (DBG) log("Ignoring: pin1state=" + mPin1State);
289                        break;
290                }
291            } else {
292                loge("Bogus facility lock response");
293            }
294        }
295    }
296
297    /** REMOVE when mIccLockEnabled is not needed */
298    private void onChangeFacilityLock(AsyncResult ar) {
299        synchronized (mLock) {
300            if (ar.exception == null) {
301                mIccLockEnabled = mDesiredPinLocked;
302                if (DBG) log( "EVENT_CHANGE_FACILITY_LOCK_DONE: mIccLockEnabled= "
303                        + mIccLockEnabled);
304            } else {
305                loge("Error change facility lock with exception " + ar.exception);
306            }
307            AsyncResult.forMessage(((Message)ar.userObj)).exception = ar.exception;
308            ((Message)ar.userObj).sendToTarget();
309        }
310    }
311
312    private Handler mHandler = new Handler() {
313        @Override
314        public void handleMessage(Message msg){
315            AsyncResult ar;
316
317            if (mDestroyed) {
318                loge("Received message " + msg + "[" + msg.what
319                        + "] while being destroyed. Ignoring.");
320                return;
321            }
322
323            switch (msg.what) {
324                case EVENT_QUERY_FACILITY_FDN_DONE:
325                    ar = (AsyncResult)msg.obj;
326                    onQueryFdnEnabled(ar);
327                    break;
328                case EVENT_CHANGE_FACILITY_FDN_DONE:
329                    ar = (AsyncResult)msg.obj;
330                    onChangeFdnDone(ar);
331                    break;
332                case EVENT_QUERY_FACILITY_LOCK_DONE:
333                    ar = (AsyncResult)msg.obj;
334                    onQueryFacilityLock(ar);
335                    break;
336                case EVENT_CHANGE_FACILITY_LOCK_DONE:
337                    ar = (AsyncResult)msg.obj;
338                    onChangeFacilityLock(ar);
339                    break;
340                default:
341                    loge("Unknown Event " + msg.what);
342            }
343        }
344    };
345
346    public void registerForReady(Handler h, int what, Object obj) {
347        synchronized (mLock) {
348            Registrant r = new Registrant (h, what, obj);
349            mReadyRegistrants.add(r);
350            notifyReadyRegistrantsIfNeeded(r);
351        }
352    }
353
354    public void unregisterForReady(Handler h) {
355        synchronized (mLock) {
356            mReadyRegistrants.remove(h);
357        }
358    }
359
360    /**
361     * Notifies handler of any transition into State.isPinLocked()
362     */
363    public void registerForLocked(Handler h, int what, Object obj) {
364        synchronized (mLock) {
365            Registrant r = new Registrant (h, what, obj);
366            mPinLockedRegistrants.add(r);
367            notifyPinLockedRegistrantsIfNeeded(r);
368        }
369    }
370
371    public void unregisterForLocked(Handler h) {
372        synchronized (mLock) {
373            mPinLockedRegistrants.remove(h);
374        }
375    }
376
377    /**
378     * Notifies handler of any transition into State.NETWORK_LOCKED
379     */
380    public void registerForNetworkLocked(Handler h, int what, Object obj) {
381        synchronized (mLock) {
382            Registrant r = new Registrant (h, what, obj);
383            mNetworkLockedRegistrants.add(r);
384            notifyNetworkLockedRegistrantsIfNeeded(r);
385        }
386    }
387
388    public void unregisterForNetworkLocked(Handler h) {
389        synchronized (mLock) {
390            mNetworkLockedRegistrants.remove(h);
391        }
392    }
393
394    /**
395     * Notifies specified registrant, assume mLock is held.
396     *
397     * @param r Registrant to be notified. If null - all registrants will be notified
398     */
399    private void notifyReadyRegistrantsIfNeeded(Registrant r) {
400        if (mDestroyed) {
401            return;
402        }
403        if (mAppState == AppState.APPSTATE_READY) {
404            if (mPin1State == PinState.PINSTATE_ENABLED_NOT_VERIFIED ||
405                    mPin1State == PinState.PINSTATE_ENABLED_BLOCKED ||
406                    mPin1State == PinState.PINSTATE_ENABLED_PERM_BLOCKED) {
407                loge("Sanity check failed! APPSTATE is ready while PIN1 is not verified!!!");
408                // Don't notify if application is in insane state
409                return;
410            }
411            if (r == null) {
412                if (DBG) log("Notifying registrants: READY");
413                mReadyRegistrants.notifyRegistrants();
414            } else {
415                if (DBG) log("Notifying 1 registrant: READY");
416                r.notifyRegistrant(new AsyncResult(null, null, null));
417            }
418        }
419    }
420
421    /**
422     * Notifies specified registrant, assume mLock is held.
423     *
424     * @param r Registrant to be notified. If null - all registrants will be notified
425     */
426    private void notifyPinLockedRegistrantsIfNeeded(Registrant r) {
427        if (mDestroyed) {
428            return;
429        }
430
431        if (mAppState == AppState.APPSTATE_PIN ||
432                mAppState == AppState.APPSTATE_PUK) {
433            if (mPin1State == PinState.PINSTATE_ENABLED_VERIFIED ||
434                    mPin1State == PinState.PINSTATE_DISABLED) {
435                loge("Sanity check failed! APPSTATE is locked while PIN1 is not!!!");
436                //Don't notify if application is in insane state
437                return;
438            }
439            if (r == null) {
440                if (DBG) log("Notifying registrants: LOCKED");
441                mPinLockedRegistrants.notifyRegistrants();
442            } else {
443                if (DBG) log("Notifying 1 registrant: LOCKED");
444                r.notifyRegistrant(new AsyncResult(null, null, null));
445            }
446        }
447    }
448
449    /**
450     * Notifies specified registrant, assume mLock is held.
451     *
452     * @param r Registrant to be notified. If null - all registrants will be notified
453     */
454    private void notifyNetworkLockedRegistrantsIfNeeded(Registrant r) {
455        if (mDestroyed) {
456            return;
457        }
458
459        if (mAppState == AppState.APPSTATE_SUBSCRIPTION_PERSO &&
460                mPersoSubState == PersoSubState.PERSOSUBSTATE_SIM_NETWORK) {
461            if (r == null) {
462                if (DBG) log("Notifying registrants: NETWORK_LOCKED");
463                mNetworkLockedRegistrants.notifyRegistrants();
464            } else {
465                if (DBG) log("Notifying 1 registrant: NETWORK_LOCED");
466                r.notifyRegistrant(new AsyncResult(null, null, null));
467            }
468        }
469    }
470
471    public AppState getState() {
472        synchronized (mLock) {
473            return mAppState;
474        }
475    }
476
477    public AppType getType() {
478        synchronized (mLock) {
479            return mAppType;
480        }
481    }
482
483    public PersoSubState getPersoSubState() {
484        synchronized (mLock) {
485            return mPersoSubState;
486        }
487    }
488
489    public String getAid() {
490        synchronized (mLock) {
491            return mAid;
492        }
493    }
494
495    public PinState getPin1State() {
496        synchronized (mLock) {
497            if (mPin1Replaced) {
498                return mUiccCard.getUniversalPinState();
499            }
500            return mPin1State;
501        }
502    }
503
504    public IccFileHandler getIccFileHandler() {
505        synchronized (mLock) {
506            return mIccFh;
507        }
508    }
509
510    public IccRecords getIccRecords() {
511        synchronized (mLock) {
512            return mIccRecords;
513        }
514    }
515
516    /**
517     * Supply the ICC PIN to the ICC
518     *
519     * When the operation is complete, onComplete will be sent to its
520     * Handler.
521     *
522     * onComplete.obj will be an AsyncResult
523     *
524     * ((AsyncResult)onComplete.obj).exception == null on success
525     * ((AsyncResult)onComplete.obj).exception != null on fail
526     *
527     * If the supplied PIN is incorrect:
528     * ((AsyncResult)onComplete.obj).exception != null
529     * && ((AsyncResult)onComplete.obj).exception
530     *       instanceof com.android.internal.telephony.gsm.CommandException)
531     * && ((CommandException)(((AsyncResult)onComplete.obj).exception))
532     *          .getCommandError() == CommandException.Error.PASSWORD_INCORRECT
533     *
534     *
535     */
536    public void supplyPin (String pin, Message onComplete) {
537        synchronized (mLock) {
538            mCi.supplyIccPin(pin, onComplete);
539        }
540    }
541
542    public void supplyPuk (String puk, String newPin, Message onComplete) {
543        synchronized (mLock) {
544            mCi.supplyIccPuk(puk, newPin, onComplete);
545        }
546    }
547
548    public void supplyPin2 (String pin2, Message onComplete) {
549        synchronized (mLock) {
550            mCi.supplyIccPin2(pin2, onComplete);
551        }
552    }
553
554    public void supplyPuk2 (String puk2, String newPin2, Message onComplete) {
555        synchronized (mLock) {
556            mCi.supplyIccPuk2(puk2, newPin2, onComplete);
557        }
558    }
559
560    public void supplyNetworkDepersonalization (String pin, Message onComplete) {
561        synchronized (mLock) {
562            if (DBG) log("supplyNetworkDepersonalization");
563            mCi.supplyNetworkDepersonalization(pin, onComplete);
564        }
565    }
566
567    /**
568     * Check whether ICC pin lock is enabled
569     * This is a sync call which returns the cached pin enabled state
570     *
571     * @return true for ICC locked enabled
572     *         false for ICC locked disabled
573     */
574    public boolean getIccLockEnabled() {
575        return mIccLockEnabled;
576        /* STOPSHIP: Remove line above and all code associated with setting
577           mIccLockEanbled once all RIL correctly sends the pin1 state.
578        // Use getPin1State to take into account pin1Replaced flag
579        PinState pinState = getPin1State();
580        return pinState == PinState.PINSTATE_ENABLED_NOT_VERIFIED ||
581               pinState == PinState.PINSTATE_ENABLED_VERIFIED ||
582               pinState == PinState.PINSTATE_ENABLED_BLOCKED ||
583               pinState == PinState.PINSTATE_ENABLED_PERM_BLOCKED;*/
584     }
585
586    /**
587     * Check whether ICC fdn (fixed dialing number) is enabled
588     * This is a sync call which returns the cached pin enabled state
589     *
590     * @return true for ICC fdn enabled
591     *         false for ICC fdn disabled
592     */
593    public boolean getIccFdnEnabled() {
594        synchronized (mLock) {
595            return mIccFdnEnabled;
596        }
597    }
598
599    /**
600     * Set the ICC pin lock enabled or disabled
601     * When the operation is complete, onComplete will be sent to its handler
602     *
603     * @param enabled "true" for locked "false" for unlocked.
604     * @param password needed to change the ICC pin state, aka. Pin1
605     * @param onComplete
606     *        onComplete.obj will be an AsyncResult
607     *        ((AsyncResult)onComplete.obj).exception == null on success
608     *        ((AsyncResult)onComplete.obj).exception != null on fail
609     */
610    public void setIccLockEnabled (boolean enabled,
611            String password, Message onComplete) {
612        synchronized (mLock) {
613            int serviceClassX;
614            serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE +
615                    CommandsInterface.SERVICE_CLASS_DATA +
616                    CommandsInterface.SERVICE_CLASS_FAX;
617
618            mDesiredPinLocked = enabled;
619
620            mCi.setFacilityLockForApp(CommandsInterface.CB_FACILITY_BA_SIM,
621                    enabled, password, serviceClassX, mAid,
622                    mHandler.obtainMessage(EVENT_CHANGE_FACILITY_LOCK_DONE, onComplete));
623        }
624    }
625
626    /**
627     * Set the ICC fdn enabled or disabled
628     * When the operation is complete, onComplete will be sent to its handler
629     *
630     * @param enabled "true" for locked "false" for unlocked.
631     * @param password needed to change the ICC fdn enable, aka Pin2
632     * @param onComplete
633     *        onComplete.obj will be an AsyncResult
634     *        ((AsyncResult)onComplete.obj).exception == null on success
635     *        ((AsyncResult)onComplete.obj).exception != null on fail
636     */
637    public void setIccFdnEnabled (boolean enabled,
638            String password, Message onComplete) {
639        synchronized (mLock) {
640            int serviceClassX;
641            serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE +
642                    CommandsInterface.SERVICE_CLASS_DATA +
643                    CommandsInterface.SERVICE_CLASS_FAX +
644                    CommandsInterface.SERVICE_CLASS_SMS;
645
646            mDesiredFdnEnabled = enabled;
647
648            mCi.setFacilityLockForApp(CommandsInterface.CB_FACILITY_BA_FD,
649                    enabled, password, serviceClassX, mAid,
650                    mHandler.obtainMessage(EVENT_CHANGE_FACILITY_FDN_DONE, onComplete));
651        }
652    }
653
654    /**
655     * Change the ICC password used in ICC pin lock
656     * When the operation is complete, onComplete will be sent to its handler
657     *
658     * @param oldPassword is the old password
659     * @param newPassword is the new password
660     * @param onComplete
661     *        onComplete.obj will be an AsyncResult
662     *        ((AsyncResult)onComplete.obj).exception == null on success
663     *        ((AsyncResult)onComplete.obj).exception != null on fail
664     */
665    public void changeIccLockPassword(String oldPassword, String newPassword,
666            Message onComplete) {
667        synchronized (mLock) {
668            if (DBG) log("changeIccLockPassword");
669            mCi.changeIccPinForApp(oldPassword, newPassword, mAid,
670                    onComplete);
671        }
672    }
673
674    /**
675     * Change the ICC password used in ICC fdn enable
676     * When the operation is complete, onComplete will be sent to its handler
677     *
678     * @param oldPassword is the old password
679     * @param newPassword is the new password
680     * @param onComplete
681     *        onComplete.obj will be an AsyncResult
682     *        ((AsyncResult)onComplete.obj).exception == null on success
683     *        ((AsyncResult)onComplete.obj).exception != null on fail
684     */
685    public void changeIccFdnPassword(String oldPassword, String newPassword,
686            Message onComplete) {
687        synchronized (mLock) {
688            if (DBG) log("changeIccFdnPassword");
689            mCi.changeIccPin2ForApp(oldPassword, newPassword, mAid,
690                    onComplete);
691        }
692    }
693
694    private void log(String msg) {
695        Rlog.d(LOG_TAG, msg);
696    }
697
698    private void loge(String msg) {
699        Rlog.e(LOG_TAG, msg);
700    }
701
702    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
703        pw.println("UiccCardApplication: " + this);
704        pw.println(" mUiccCard=" + mUiccCard);
705        pw.println(" mAppState=" + mAppState);
706        pw.println(" mAppType=" + mAppType);
707        pw.println(" mPersoSubState=" + mPersoSubState);
708        pw.println(" mAid=" + mAid);
709        pw.println(" mAppLabel=" + mAppLabel);
710        pw.println(" mPin1Replaced=" + mPin1Replaced);
711        pw.println(" mPin1State=" + mPin1State);
712        pw.println(" mPin2State=" + mPin2State);
713        pw.println(" mIccFdnEnabled=" + mIccFdnEnabled);
714        pw.println(" mDesiredFdnEnabled=" + mDesiredFdnEnabled);
715        pw.println(" mIccLockEnabled=" + mIccLockEnabled);
716        pw.println(" mDesiredPinLocked=" + mDesiredPinLocked);
717        pw.println(" mCi=" + mCi);
718        pw.println(" mIccRecords=" + mIccRecords);
719        pw.println(" mIccFh=" + mIccFh);
720        pw.println(" mDestroyed=" + mDestroyed);
721        pw.println(" mReadyRegistrants: size=" + mReadyRegistrants.size());
722        for (int i = 0; i < mReadyRegistrants.size(); i++) {
723            pw.println("  mReadyRegistrants[" + i + "]="
724                    + ((Registrant)mReadyRegistrants.get(i)).getHandler());
725        }
726        pw.println(" mPinLockedRegistrants: size=" + mPinLockedRegistrants.size());
727        for (int i = 0; i < mPinLockedRegistrants.size(); i++) {
728            pw.println("  mPinLockedRegistrants[" + i + "]="
729                    + ((Registrant)mPinLockedRegistrants.get(i)).getHandler());
730        }
731        pw.println(" mNetworkLockedRegistrants: size=" + mNetworkLockedRegistrants.size());
732        for (int i = 0; i < mNetworkLockedRegistrants.size(); i++) {
733            pw.println("  mNetworkLockedRegistrants[" + i + "]="
734                    + ((Registrant)mNetworkLockedRegistrants.get(i)).getHandler());
735        }
736        pw.flush();
737    }
738}
739