UiccCardApplication.java revision b93bb3538c55f173f94a4ee7510d9d1521d8f731
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_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    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 String getAppLabel() {
552        return mAppLabel;
553    }
554
555    public PinState getPin1State() {
556        synchronized (mLock) {
557            if (mPin1Replaced) {
558                return mUiccCard.getUniversalPinState();
559            }
560            return mPin1State;
561        }
562    }
563
564    public IccFileHandler getIccFileHandler() {
565        synchronized (mLock) {
566            return mIccFh;
567        }
568    }
569
570    public IccRecords getIccRecords() {
571        synchronized (mLock) {
572            return mIccRecords;
573        }
574    }
575
576    /**
577     * Supply the ICC PIN to the ICC
578     *
579     * When the operation is complete, onComplete will be sent to its
580     * Handler.
581     *
582     * onComplete.obj will be an AsyncResult
583     * onComplete.arg1 = remaining attempts before puk locked or -1 if unknown
584     *
585     * ((AsyncResult)onComplete.obj).exception == null on success
586     * ((AsyncResult)onComplete.obj).exception != null on fail
587     *
588     * If the supplied PIN is incorrect:
589     * ((AsyncResult)onComplete.obj).exception != null
590     * && ((AsyncResult)onComplete.obj).exception
591     *       instanceof com.android.internal.telephony.gsm.CommandException)
592     * && ((CommandException)(((AsyncResult)onComplete.obj).exception))
593     *          .getCommandError() == CommandException.Error.PASSWORD_INCORRECT
594     */
595    public void supplyPin (String pin, Message onComplete) {
596        synchronized (mLock) {
597            mCi.supplyIccPinForApp(pin, mAid, mHandler.obtainMessage(EVENT_PIN1_PUK1_DONE,
598                    onComplete));
599        }
600    }
601
602    /**
603     * Supply the ICC PUK to the ICC
604     *
605     * When the operation is complete, onComplete will be sent to its
606     * Handler.
607     *
608     * onComplete.obj will be an AsyncResult
609     * onComplete.arg1 = remaining attempts before Icc will be permanently unusable
610     * or -1 if unknown
611     *
612     * ((AsyncResult)onComplete.obj).exception == null on success
613     * ((AsyncResult)onComplete.obj).exception != null on fail
614     *
615     * If the supplied PIN is incorrect:
616     * ((AsyncResult)onComplete.obj).exception != null
617     * && ((AsyncResult)onComplete.obj).exception
618     *       instanceof com.android.internal.telephony.gsm.CommandException)
619     * && ((CommandException)(((AsyncResult)onComplete.obj).exception))
620     *          .getCommandError() == CommandException.Error.PASSWORD_INCORRECT
621     *
622     *
623     */
624    public void supplyPuk (String puk, String newPin, Message onComplete) {
625        synchronized (mLock) {
626        mCi.supplyIccPukForApp(puk, newPin, mAid,
627                mHandler.obtainMessage(EVENT_PIN1_PUK1_DONE, onComplete));
628        }
629    }
630
631    public void supplyPin2 (String pin2, Message onComplete) {
632        synchronized (mLock) {
633            mCi.supplyIccPin2ForApp(pin2, mAid,
634                    mHandler.obtainMessage(EVENT_PIN2_PUK2_DONE, onComplete));
635        }
636    }
637
638    public void supplyPuk2 (String puk2, String newPin2, Message onComplete) {
639        synchronized (mLock) {
640            mCi.supplyIccPuk2ForApp(puk2, newPin2, mAid,
641                    mHandler.obtainMessage(EVENT_PIN2_PUK2_DONE, onComplete));
642        }
643    }
644
645    public void supplyNetworkDepersonalization (String pin, Message onComplete) {
646        synchronized (mLock) {
647            if (DBG) log("supplyNetworkDepersonalization");
648            mCi.supplyNetworkDepersonalization(pin, onComplete);
649        }
650    }
651
652    /**
653     * Check whether ICC pin lock is enabled
654     * This is a sync call which returns the cached pin enabled state
655     *
656     * @return true for ICC locked enabled
657     *         false for ICC locked disabled
658     */
659    public boolean getIccLockEnabled() {
660        return mIccLockEnabled;
661        /* STOPSHIP: Remove line above and all code associated with setting
662           mIccLockEanbled once all RIL correctly sends the pin1 state.
663        // Use getPin1State to take into account pin1Replaced flag
664        PinState pinState = getPin1State();
665        return pinState == PinState.PINSTATE_ENABLED_NOT_VERIFIED ||
666               pinState == PinState.PINSTATE_ENABLED_VERIFIED ||
667               pinState == PinState.PINSTATE_ENABLED_BLOCKED ||
668               pinState == PinState.PINSTATE_ENABLED_PERM_BLOCKED;*/
669     }
670
671    /**
672     * Check whether ICC fdn (fixed dialing number) is enabled
673     * This is a sync call which returns the cached pin enabled state
674     *
675     * @return true for ICC fdn enabled
676     *         false for ICC fdn disabled
677     */
678    public boolean getIccFdnEnabled() {
679        synchronized (mLock) {
680            return mIccFdnEnabled;
681        }
682    }
683
684    /**
685     * Check whether fdn (fixed dialing number) service is available.
686     * @return true if ICC fdn service available
687     *         false if ICC fdn service not available
688     */
689    public boolean getIccFdnAvailable() {
690        return mIccFdnAvailable;
691    }
692
693    /**
694     * Set the ICC pin lock enabled or disabled
695     * When the operation is complete, onComplete will be sent to its handler
696     *
697     * @param enabled "true" for locked "false" for unlocked.
698     * @param password needed to change the ICC pin state, aka. Pin1
699     * @param onComplete
700     *        onComplete.obj will be an AsyncResult
701     *        ((AsyncResult)onComplete.obj).exception == null on success
702     *        ((AsyncResult)onComplete.obj).exception != null on fail
703     */
704    public void setIccLockEnabled (boolean enabled,
705            String password, Message onComplete) {
706        synchronized (mLock) {
707            int serviceClassX;
708            serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE +
709                    CommandsInterface.SERVICE_CLASS_DATA +
710                    CommandsInterface.SERVICE_CLASS_FAX;
711
712            mDesiredPinLocked = enabled;
713
714            mCi.setFacilityLockForApp(CommandsInterface.CB_FACILITY_BA_SIM,
715                    enabled, password, serviceClassX, mAid,
716                    mHandler.obtainMessage(EVENT_CHANGE_FACILITY_LOCK_DONE, onComplete));
717        }
718    }
719
720    /**
721     * Set the ICC fdn enabled or disabled
722     * When the operation is complete, onComplete will be sent to its handler
723     *
724     * @param enabled "true" for locked "false" for unlocked.
725     * @param password needed to change the ICC fdn enable, aka Pin2
726     * @param onComplete
727     *        onComplete.obj will be an AsyncResult
728     *        ((AsyncResult)onComplete.obj).exception == null on success
729     *        ((AsyncResult)onComplete.obj).exception != null on fail
730     */
731    public void setIccFdnEnabled (boolean enabled,
732            String password, Message onComplete) {
733        synchronized (mLock) {
734            int serviceClassX;
735            serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE +
736                    CommandsInterface.SERVICE_CLASS_DATA +
737                    CommandsInterface.SERVICE_CLASS_FAX +
738                    CommandsInterface.SERVICE_CLASS_SMS;
739
740            mDesiredFdnEnabled = enabled;
741
742            mCi.setFacilityLockForApp(CommandsInterface.CB_FACILITY_BA_FD,
743                    enabled, password, serviceClassX, mAid,
744                    mHandler.obtainMessage(EVENT_CHANGE_FACILITY_FDN_DONE, onComplete));
745        }
746    }
747
748    /**
749     * Change the ICC password used in ICC pin lock
750     * When the operation is complete, onComplete will be sent to its handler
751     *
752     * @param oldPassword is the old password
753     * @param newPassword is the new password
754     * @param onComplete
755     *        onComplete.obj will be an AsyncResult
756     *        onComplete.arg1 = attempts remaining or -1 if unknown
757     *        ((AsyncResult)onComplete.obj).exception == null on success
758     *        ((AsyncResult)onComplete.obj).exception != null on fail
759     */
760    public void changeIccLockPassword(String oldPassword, String newPassword,
761            Message onComplete) {
762        synchronized (mLock) {
763            if (DBG) log("changeIccLockPassword");
764            mCi.changeIccPinForApp(oldPassword, newPassword, mAid,
765                    mHandler.obtainMessage(EVENT_CHANGE_PIN1_DONE, onComplete));
766        }
767    }
768
769    /**
770     * Change the ICC password used in ICC fdn enable
771     * When the operation is complete, onComplete will be sent to its handler
772     *
773     * @param oldPassword is the old password
774     * @param newPassword is the new password
775     * @param onComplete
776     *        onComplete.obj will be an AsyncResult
777     *        ((AsyncResult)onComplete.obj).exception == null on success
778     *        ((AsyncResult)onComplete.obj).exception != null on fail
779     */
780    public void changeIccFdnPassword(String oldPassword, String newPassword,
781            Message onComplete) {
782        synchronized (mLock) {
783            if (DBG) log("changeIccFdnPassword");
784            mCi.changeIccPin2ForApp(oldPassword, newPassword, mAid,
785                    mHandler.obtainMessage(EVENT_CHANGE_PIN2_DONE, onComplete));
786        }
787    }
788
789    /**
790     * @return true if ICC card is PIN2 blocked
791     */
792    public boolean getIccPin2Blocked() {
793        synchronized (mLock) {
794            return mPin2State == PinState.PINSTATE_ENABLED_BLOCKED;
795        }
796    }
797
798    /**
799     * @return true if ICC card is PUK2 blocked
800     */
801    public boolean getIccPuk2Blocked() {
802        synchronized (mLock) {
803            return mPin2State == PinState.PINSTATE_ENABLED_PERM_BLOCKED;
804        }
805    }
806
807    protected UiccCard getUiccCard() {
808        return mUiccCard;
809    }
810
811    private void log(String msg) {
812        Rlog.d(LOG_TAG, msg);
813    }
814
815    private void loge(String msg) {
816        Rlog.e(LOG_TAG, msg);
817    }
818
819    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
820        pw.println("UiccCardApplication: " + this);
821        pw.println(" mUiccCard=" + mUiccCard);
822        pw.println(" mAppState=" + mAppState);
823        pw.println(" mAppType=" + mAppType);
824        pw.println(" mPersoSubState=" + mPersoSubState);
825        pw.println(" mAid=" + mAid);
826        pw.println(" mAppLabel=" + mAppLabel);
827        pw.println(" mPin1Replaced=" + mPin1Replaced);
828        pw.println(" mPin1State=" + mPin1State);
829        pw.println(" mPin2State=" + mPin2State);
830        pw.println(" mIccFdnEnabled=" + mIccFdnEnabled);
831        pw.println(" mDesiredFdnEnabled=" + mDesiredFdnEnabled);
832        pw.println(" mIccLockEnabled=" + mIccLockEnabled);
833        pw.println(" mDesiredPinLocked=" + mDesiredPinLocked);
834        pw.println(" mCi=" + mCi);
835        pw.println(" mIccRecords=" + mIccRecords);
836        pw.println(" mIccFh=" + mIccFh);
837        pw.println(" mDestroyed=" + mDestroyed);
838        pw.println(" mReadyRegistrants: size=" + mReadyRegistrants.size());
839        for (int i = 0; i < mReadyRegistrants.size(); i++) {
840            pw.println("  mReadyRegistrants[" + i + "]="
841                    + ((Registrant)mReadyRegistrants.get(i)).getHandler());
842        }
843        pw.println(" mPinLockedRegistrants: size=" + mPinLockedRegistrants.size());
844        for (int i = 0; i < mPinLockedRegistrants.size(); i++) {
845            pw.println("  mPinLockedRegistrants[" + i + "]="
846                    + ((Registrant)mPinLockedRegistrants.get(i)).getHandler());
847        }
848        pw.println(" mNetworkLockedRegistrants: size=" + mNetworkLockedRegistrants.size());
849        for (int i = 0; i < mNetworkLockedRegistrants.size(); i++) {
850            pw.println("  mNetworkLockedRegistrants[" + i + "]="
851                    + ((Registrant)mNetworkLockedRegistrants.get(i)).getHandler());
852        }
853        pw.flush();
854    }
855}
856