0715b0e0e496b462a8d4e2294f8857cd2f9a5083
[android/platform/frameworks/opt/telephony.git] / src / java / com / android / internal / telephony / uicc / UiccCardApplication.java
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
17 package com.android.internal.telephony.uicc;
18
19 import android.content.Context;
20 import android.os.AsyncResult;
21 import android.os.Handler;
22 import android.os.Message;
23 import android.os.Registrant;
24 import android.os.RegistrantList;
25 import android.telephony.Rlog;
26
27 import com.android.internal.telephony.CommandsInterface;
28 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppState;
29 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
30 import com.android.internal.telephony.uicc.IccCardApplicationStatus.PersoSubState;
31 import com.android.internal.telephony.uicc.IccCardStatus.PinState;
32
33 import java.io.FileDescriptor;
34 import java.io.PrintWriter;
35
36 /**
37  * {@hide}
38  */
39 public 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 }