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