IccCardProxy.java revision 3522c54a64f577f2b657a775dae9b4eb2d8003d5
1/*
2 * Copyright (C) 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 static android.Manifest.permission.READ_PHONE_STATE;
20import android.app.ActivityManagerNative;
21import android.content.Context;
22import android.content.Intent;
23import android.os.AsyncResult;
24import android.os.Handler;
25import android.os.Message;
26import android.os.Registrant;
27import android.os.RegistrantList;
28import android.os.SystemProperties;
29import android.os.UserHandle;
30import android.telephony.Rlog;
31import android.telephony.ServiceState;
32import android.telephony.TelephonyManager;
33
34import com.android.internal.telephony.CommandsInterface;
35import com.android.internal.telephony.IccCard;
36import com.android.internal.telephony.IccCardConstants;
37import com.android.internal.telephony.PhoneConstants;
38import com.android.internal.telephony.RILConstants;
39import com.android.internal.telephony.TelephonyIntents;
40import com.android.internal.telephony.IccCardConstants.State;
41import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager;
42import com.android.internal.telephony.Phone;
43import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppState;
44import com.android.internal.telephony.uicc.IccCardApplicationStatus.PersoSubState;
45import com.android.internal.telephony.uicc.IccCardStatus.CardState;
46import com.android.internal.telephony.uicc.IccCardStatus.PinState;
47import com.android.internal.telephony.uicc.UiccController;
48
49import java.io.FileDescriptor;
50import java.io.PrintWriter;
51
52import static com.android.internal.telephony.TelephonyProperties.PROPERTY_SIM_STATE;
53
54/**
55 * @Deprecated use {@link UiccController}.getUiccCard instead.
56 *
57 * The Phone App assumes that there is only one icc card, and one icc application
58 * available at a time. Moreover, it assumes such object (represented with IccCard)
59 * is available all the time (whether {@link RILConstants#RIL_REQUEST_GET_SIM_STATUS} returned
60 * or not, whether card has desired application or not, whether there really is a card in the
61 * slot or not).
62 *
63 * UiccController, however, can handle multiple instances of icc objects (multiple
64 * {@link UiccCardApplication}, multiple {@link IccFileHandler}, multiple {@link IccRecords})
65 * created and destroyed dynamically during phone operation.
66 *
67 * This class implements the IccCard interface that is always available (right after default
68 * phone object is constructed) to expose the current (based on voice radio technology)
69 * application on the uicc card, so that external apps won't break.
70 */
71
72public class IccCardProxy extends Handler implements IccCard {
73    private static final boolean DBG = true;
74    private static final String LOG_TAG = "IccCardProxy";
75
76    private static final int EVENT_RADIO_OFF_OR_UNAVAILABLE = 1;
77    private static final int EVENT_RADIO_ON = 2;
78    private static final int EVENT_ICC_CHANGED = 3;
79    private static final int EVENT_ICC_ABSENT = 4;
80    private static final int EVENT_ICC_LOCKED = 5;
81    private static final int EVENT_APP_READY = 6;
82    private static final int EVENT_RECORDS_LOADED = 7;
83    private static final int EVENT_IMSI_READY = 8;
84    private static final int EVENT_NETWORK_LOCKED = 9;
85    private static final int EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED = 11;
86
87    private final Object mLock = new Object();
88    private Context mContext;
89    private CommandsInterface mCi;
90
91    private RegistrantList mAbsentRegistrants = new RegistrantList();
92    private RegistrantList mPinLockedRegistrants = new RegistrantList();
93    private RegistrantList mNetworkLockedRegistrants = new RegistrantList();
94
95    private int mCurrentAppType = UiccController.APP_FAM_3GPP; //default to 3gpp?
96    private UiccController mUiccController = null;
97    private UiccCard mUiccCard = null;
98    private UiccCardApplication mUiccApplication = null;
99    private IccRecords mIccRecords = null;
100    private CdmaSubscriptionSourceManager mCdmaSSM = null;
101    private boolean mRadioOn = false;
102    private boolean mQuietMode = false; // when set to true IccCardProxy will not broadcast
103                                        // ACTION_SIM_STATE_CHANGED intents
104    private boolean mInitialized = false;
105    private State mExternalState = State.UNKNOWN;
106
107    public IccCardProxy(Context context, CommandsInterface ci) {
108        log("Creating");
109        mContext = context;
110        mCi = ci;
111        mCdmaSSM = CdmaSubscriptionSourceManager.getInstance(context,
112                ci, this, EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED, null);
113        mUiccController = UiccController.getInstance();
114        mUiccController.registerForIccChanged(this, EVENT_ICC_CHANGED, null);
115        ci.registerForOn(this,EVENT_RADIO_ON, null);
116        ci.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_UNAVAILABLE, null);
117        setExternalState(State.NOT_READY);
118    }
119
120    public void dispose() {
121        synchronized (mLock) {
122            log("Disposing");
123            //Cleanup icc references
124            mUiccController.unregisterForIccChanged(this);
125            mUiccController = null;
126            mCi.unregisterForOn(this);
127            mCi.unregisterForOffOrNotAvailable(this);
128            mCdmaSSM.dispose(this);
129        }
130    }
131
132    /*
133     * The card application that the external world sees will be based on the
134     * voice radio technology only!
135     */
136    public void setVoiceRadioTech(int radioTech) {
137        synchronized (mLock) {
138            if (DBG) {
139                log("Setting radio tech " + ServiceState.rilRadioTechnologyToString(radioTech));
140            }
141            if (ServiceState.isGsm(radioTech)) {
142                mCurrentAppType = UiccController.APP_FAM_3GPP;
143            } else {
144                mCurrentAppType = UiccController.APP_FAM_3GPP2;
145            }
146            updateQuietMode();
147        }
148    }
149
150    /**
151     * In case of 3gpp2 we need to find out if subscription used is coming from
152     * NV in which case we shouldn't broadcast any sim states changes.
153     */
154    private void updateQuietMode() {
155        synchronized (mLock) {
156            boolean oldQuietMode = mQuietMode;
157            boolean newQuietMode;
158            int cdmaSource = Phone.CDMA_SUBSCRIPTION_UNKNOWN;
159            boolean isLteOnCdmaMode = TelephonyManager.getLteOnCdmaModeStatic()
160                    == PhoneConstants.LTE_ON_CDMA_TRUE;
161            if (mCurrentAppType == UiccController.APP_FAM_3GPP) {
162                newQuietMode = false;
163                if (DBG) log("updateQuietMode: 3GPP subscription -> newQuietMode=" + newQuietMode);
164            } else {
165                if (isLteOnCdmaMode) {
166                    log("updateQuietMode: is cdma/lte device, force IccCardProxy into 3gpp mode");
167                    mCurrentAppType = UiccController.APP_FAM_3GPP;
168                }
169                cdmaSource = mCdmaSSM != null ?
170                        mCdmaSSM.getCdmaSubscriptionSource() : Phone.CDMA_SUBSCRIPTION_UNKNOWN;
171
172                newQuietMode = (cdmaSource == Phone.CDMA_SUBSCRIPTION_NV)
173                        && (mCurrentAppType == UiccController.APP_FAM_3GPP2)
174                        && !isLteOnCdmaMode;
175            }
176
177            if (mQuietMode == false && newQuietMode == true) {
178                // Last thing to do before switching to quiet mode is
179                // broadcast ICC_READY
180                log("Switching to QuietMode.");
181                setExternalState(State.READY);
182                mQuietMode = newQuietMode;
183            } else if (mQuietMode == true && newQuietMode == false) {
184                if (DBG) {
185                    log("updateQuietMode: Switching out from QuietMode."
186                            + " Force broadcast of current state=" + mExternalState);
187                }
188                mQuietMode = newQuietMode;
189                setExternalState(mExternalState, true);
190            }
191            if (DBG) {
192                log("updateQuietMode: QuietMode is " + mQuietMode + " (app_type="
193                    + mCurrentAppType + " isLteOnCdmaMode=" + isLteOnCdmaMode
194                    + " cdmaSource=" + cdmaSource + ")");
195            }
196            mInitialized = true;
197            sendMessage(obtainMessage(EVENT_ICC_CHANGED));
198        }
199    }
200
201    @Override
202    public void handleMessage(Message msg) {
203        switch (msg.what) {
204            case EVENT_RADIO_OFF_OR_UNAVAILABLE:
205                mRadioOn = false;
206                break;
207            case EVENT_RADIO_ON:
208                mRadioOn = true;
209                if (!mInitialized) {
210                    updateQuietMode();
211                }
212                break;
213            case EVENT_ICC_CHANGED:
214                if (mInitialized) {
215                    updateIccAvailability();
216                }
217                break;
218            case EVENT_ICC_ABSENT:
219                mAbsentRegistrants.notifyRegistrants();
220                setExternalState(State.ABSENT);
221                break;
222            case EVENT_ICC_LOCKED:
223                processLockedState();
224                break;
225            case EVENT_APP_READY:
226                setExternalState(State.READY);
227                break;
228            case EVENT_RECORDS_LOADED:
229                broadcastIccStateChangedIntent(IccCardConstants.INTENT_VALUE_ICC_LOADED, null);
230                break;
231            case EVENT_IMSI_READY:
232                broadcastIccStateChangedIntent(IccCardConstants.INTENT_VALUE_ICC_IMSI, null);
233                break;
234            case EVENT_NETWORK_LOCKED:
235                mNetworkLockedRegistrants.notifyRegistrants();
236                setExternalState(State.NETWORK_LOCKED);
237                break;
238            case EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED:
239                updateQuietMode();
240                break;
241            default:
242                loge("Unhandled message with number: " + msg.what);
243                break;
244        }
245    }
246
247    private void updateIccAvailability() {
248        synchronized (mLock) {
249            UiccCard newCard = mUiccController.getUiccCard();
250            CardState state = CardState.CARDSTATE_ABSENT;
251            UiccCardApplication newApp = null;
252            IccRecords newRecords = null;
253            if (newCard != null) {
254                state = newCard.getCardState();
255                newApp = newCard.getApplication(mCurrentAppType);
256                if (newApp != null) {
257                    newRecords = newApp.getIccRecords();
258                }
259            }
260
261            if (mIccRecords != newRecords || mUiccApplication != newApp || mUiccCard != newCard) {
262                if (DBG) log("Icc changed. Reregestering.");
263                unregisterUiccCardEvents();
264                mUiccCard = newCard;
265                mUiccApplication = newApp;
266                mIccRecords = newRecords;
267                registerUiccCardEvents();
268            }
269
270            updateExternalState();
271        }
272    }
273
274    private void updateExternalState() {
275        if (mUiccCard == null || mUiccCard.getCardState() == CardState.CARDSTATE_ABSENT) {
276            if (mRadioOn) {
277                setExternalState(State.ABSENT);
278            } else {
279                setExternalState(State.NOT_READY);
280            }
281            return;
282        }
283
284        if (mUiccCard.getCardState() == CardState.CARDSTATE_ERROR ||
285                mUiccApplication == null) {
286            setExternalState(State.UNKNOWN);
287            return;
288        }
289
290        switch (mUiccApplication.getState()) {
291            case APPSTATE_UNKNOWN:
292            case APPSTATE_DETECTED:
293                setExternalState(State.UNKNOWN);
294                break;
295            case APPSTATE_PIN:
296                setExternalState(State.PIN_REQUIRED);
297                break;
298            case APPSTATE_PUK:
299                setExternalState(State.PUK_REQUIRED);
300                break;
301            case APPSTATE_SUBSCRIPTION_PERSO:
302                if (mUiccApplication.getPersoSubState() == PersoSubState.PERSOSUBSTATE_SIM_NETWORK) {
303                    setExternalState(State.NETWORK_LOCKED);
304                } else {
305                    setExternalState(State.UNKNOWN);
306                }
307                break;
308            case APPSTATE_READY:
309                setExternalState(State.READY);
310                break;
311        }
312    }
313
314    private void registerUiccCardEvents() {
315        if (mUiccCard != null) mUiccCard.registerForAbsent(this, EVENT_ICC_ABSENT, null);
316        if (mUiccApplication != null) {
317            mUiccApplication.registerForReady(this, EVENT_APP_READY, null);
318            mUiccApplication.registerForLocked(this, EVENT_ICC_LOCKED, null);
319            mUiccApplication.registerForNetworkLocked(this, EVENT_NETWORK_LOCKED, null);
320        }
321        if (mIccRecords != null) {
322            mIccRecords.registerForImsiReady(this, EVENT_IMSI_READY, null);
323            mIccRecords.registerForRecordsLoaded(this, EVENT_RECORDS_LOADED, null);
324        }
325    }
326
327    private void unregisterUiccCardEvents() {
328        if (mUiccCard != null) mUiccCard.unregisterForAbsent(this);
329        if (mUiccApplication != null) mUiccApplication.unregisterForReady(this);
330        if (mUiccApplication != null) mUiccApplication.unregisterForLocked(this);
331        if (mUiccApplication != null) mUiccApplication.unregisterForNetworkLocked(this);
332        if (mIccRecords != null) mIccRecords.unregisterForImsiReady(this);
333        if (mIccRecords != null) mIccRecords.unregisterForRecordsLoaded(this);
334    }
335
336    private void broadcastIccStateChangedIntent(String value, String reason) {
337        synchronized (mLock) {
338            if (mQuietMode) {
339                log("QuietMode: NOT Broadcasting intent ACTION_SIM_STATE_CHANGED " +  value
340                        + " reason " + reason);
341                return;
342            }
343
344            Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
345            intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
346            intent.putExtra(PhoneConstants.PHONE_NAME_KEY, "Phone");
347            intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, value);
348            intent.putExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON, reason);
349
350            if (DBG) log("Broadcasting intent ACTION_SIM_STATE_CHANGED " +  value
351                    + " reason " + reason);
352            ActivityManagerNative.broadcastStickyIntent(intent, READ_PHONE_STATE,
353                    UserHandle.USER_ALL);
354        }
355    }
356
357    private void processLockedState() {
358        synchronized (mLock) {
359            if (mUiccApplication == null) {
360                //Don't need to do anything if non-existent application is locked
361                return;
362            }
363            PinState pin1State = mUiccApplication.getPin1State();
364            if (pin1State == PinState.PINSTATE_ENABLED_PERM_BLOCKED) {
365                setExternalState(State.PERM_DISABLED);
366                return;
367            }
368
369            AppState appState = mUiccApplication.getState();
370            switch (appState) {
371                case APPSTATE_PIN:
372                    mPinLockedRegistrants.notifyRegistrants();
373                    setExternalState(State.PIN_REQUIRED);
374                    break;
375                case APPSTATE_PUK:
376                    setExternalState(State.PUK_REQUIRED);
377                    break;
378                case APPSTATE_DETECTED:
379                case APPSTATE_READY:
380                case APPSTATE_SUBSCRIPTION_PERSO:
381                case APPSTATE_UNKNOWN:
382                    // Neither required
383                    break;
384            }
385        }
386    }
387
388    private void setExternalState(State newState, boolean override) {
389        synchronized (mLock) {
390            if (!override && newState == mExternalState) {
391                return;
392            }
393            mExternalState = newState;
394            SystemProperties.set(PROPERTY_SIM_STATE, mExternalState.toString());
395            broadcastIccStateChangedIntent(getIccStateIntentString(mExternalState),
396                    getIccStateReason(mExternalState));
397        }
398    }
399
400    private void setExternalState(State newState) {
401        setExternalState(newState, false);
402    }
403
404    public boolean getIccRecordsLoaded() {
405        synchronized (mLock) {
406            if (mIccRecords != null) {
407                return mIccRecords.getRecordsLoaded();
408            }
409            return false;
410        }
411    }
412
413    private String getIccStateIntentString(State state) {
414        switch (state) {
415            case ABSENT: return IccCardConstants.INTENT_VALUE_ICC_ABSENT;
416            case PIN_REQUIRED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED;
417            case PUK_REQUIRED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED;
418            case NETWORK_LOCKED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED;
419            case READY: return IccCardConstants.INTENT_VALUE_ICC_READY;
420            case NOT_READY: return IccCardConstants.INTENT_VALUE_ICC_NOT_READY;
421            case PERM_DISABLED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED;
422            default: return IccCardConstants.INTENT_VALUE_ICC_UNKNOWN;
423        }
424    }
425
426    /**
427     * Locked state have a reason (PIN, PUK, NETWORK, PERM_DISABLED)
428     * @return reason
429     */
430    private String getIccStateReason(State state) {
431        switch (state) {
432            case PIN_REQUIRED: return IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN;
433            case PUK_REQUIRED: return IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK;
434            case NETWORK_LOCKED: return IccCardConstants.INTENT_VALUE_LOCKED_NETWORK;
435            case PERM_DISABLED: return IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED;
436            default: return null;
437       }
438    }
439
440    /* IccCard interface implementation */
441    @Override
442    public State getState() {
443        synchronized (mLock) {
444            return mExternalState;
445        }
446    }
447
448    @Override
449    public IccRecords getIccRecords() {
450        synchronized (mLock) {
451            return mIccRecords;
452        }
453    }
454
455    @Override
456    public IccFileHandler getIccFileHandler() {
457        synchronized (mLock) {
458            if (mUiccApplication != null) {
459                return mUiccApplication.getIccFileHandler();
460            }
461            return null;
462        }
463    }
464
465    /**
466     * Notifies handler of any transition into State.ABSENT
467     */
468    @Override
469    public void registerForAbsent(Handler h, int what, Object obj) {
470        synchronized (mLock) {
471            Registrant r = new Registrant (h, what, obj);
472
473            mAbsentRegistrants.add(r);
474
475            if (getState() == State.ABSENT) {
476                r.notifyRegistrant();
477            }
478        }
479    }
480
481    @Override
482    public void unregisterForAbsent(Handler h) {
483        synchronized (mLock) {
484            mAbsentRegistrants.remove(h);
485        }
486    }
487
488    /**
489     * Notifies handler of any transition into State.NETWORK_LOCKED
490     */
491    @Override
492    public void registerForNetworkLocked(Handler h, int what, Object obj) {
493        synchronized (mLock) {
494            Registrant r = new Registrant (h, what, obj);
495
496            mNetworkLockedRegistrants.add(r);
497
498            if (getState() == State.NETWORK_LOCKED) {
499                r.notifyRegistrant();
500            }
501        }
502    }
503
504    @Override
505    public void unregisterForNetworkLocked(Handler h) {
506        synchronized (mLock) {
507            mNetworkLockedRegistrants.remove(h);
508        }
509    }
510
511    /**
512     * Notifies handler of any transition into State.isPinLocked()
513     */
514    @Override
515    public void registerForLocked(Handler h, int what, Object obj) {
516        synchronized (mLock) {
517            Registrant r = new Registrant (h, what, obj);
518
519            mPinLockedRegistrants.add(r);
520
521            if (getState().isPinLocked()) {
522                r.notifyRegistrant();
523            }
524        }
525    }
526
527    @Override
528    public void unregisterForLocked(Handler h) {
529        synchronized (mLock) {
530            mPinLockedRegistrants.remove(h);
531        }
532    }
533
534    @Override
535    public void supplyPin(String pin, Message onComplete) {
536        synchronized (mLock) {
537            if (mUiccApplication != null) {
538                mUiccApplication.supplyPin(pin, onComplete);
539            } else if (onComplete != null) {
540                Exception e = new RuntimeException("ICC card is absent.");
541                AsyncResult.forMessage(onComplete).exception = e;
542                onComplete.sendToTarget();
543                return;
544            }
545        }
546    }
547
548    @Override
549    public void supplyPuk(String puk, String newPin, Message onComplete) {
550        synchronized (mLock) {
551            if (mUiccApplication != null) {
552                mUiccApplication.supplyPuk(puk, newPin, onComplete);
553            } else if (onComplete != null) {
554                Exception e = new RuntimeException("ICC card is absent.");
555                AsyncResult.forMessage(onComplete).exception = e;
556                onComplete.sendToTarget();
557                return;
558            }
559        }
560    }
561
562    @Override
563    public void supplyPin2(String pin2, Message onComplete) {
564        synchronized (mLock) {
565            if (mUiccApplication != null) {
566                mUiccApplication.supplyPin2(pin2, onComplete);
567            } else if (onComplete != null) {
568                Exception e = new RuntimeException("ICC card is absent.");
569                AsyncResult.forMessage(onComplete).exception = e;
570                onComplete.sendToTarget();
571                return;
572            }
573        }
574    }
575
576    @Override
577    public void supplyPuk2(String puk2, String newPin2, Message onComplete) {
578        synchronized (mLock) {
579            if (mUiccApplication != null) {
580                mUiccApplication.supplyPuk2(puk2, newPin2, onComplete);
581            } else if (onComplete != null) {
582                Exception e = new RuntimeException("ICC card is absent.");
583                AsyncResult.forMessage(onComplete).exception = e;
584                onComplete.sendToTarget();
585                return;
586            }
587        }
588    }
589
590    @Override
591    public void supplyNetworkDepersonalization(String pin, Message onComplete) {
592        synchronized (mLock) {
593            if (mUiccApplication != null) {
594                mUiccApplication.supplyNetworkDepersonalization(pin, onComplete);
595            } else if (onComplete != null) {
596                Exception e = new RuntimeException("CommandsInterface is not set.");
597                AsyncResult.forMessage(onComplete).exception = e;
598                onComplete.sendToTarget();
599                return;
600            }
601        }
602    }
603
604    @Override
605    public boolean getIccLockEnabled() {
606        synchronized (mLock) {
607            /* defaults to false, if ICC is absent/deactivated */
608            Boolean retValue = mUiccApplication != null ?
609                    mUiccApplication.getIccLockEnabled() : false;
610            return retValue;
611        }
612    }
613
614    @Override
615    public boolean getIccFdnEnabled() {
616        synchronized (mLock) {
617            Boolean retValue = mUiccApplication != null ?
618                    mUiccApplication.getIccFdnEnabled() : false;
619            return retValue;
620        }
621    }
622
623    public boolean getIccFdnAvailable() {
624        boolean retValue = mUiccApplication != null ? mUiccApplication.getIccFdnAvailable() : false;
625        return retValue;
626    }
627
628    public boolean getIccPin2Blocked() {
629        /* defaults to disabled */
630        Boolean retValue = mUiccApplication != null ? mUiccApplication.getIccPin2Blocked() : false;
631        return retValue;
632    }
633
634    public boolean getIccPuk2Blocked() {
635        /* defaults to disabled */
636        Boolean retValue = mUiccApplication != null ? mUiccApplication.getIccPuk2Blocked() : false;
637        return retValue;
638    }
639
640    @Override
641    public void setIccLockEnabled(boolean enabled, String password, Message onComplete) {
642        synchronized (mLock) {
643            if (mUiccApplication != null) {
644                mUiccApplication.setIccLockEnabled(enabled, password, onComplete);
645            } else if (onComplete != null) {
646                Exception e = new RuntimeException("ICC card is absent.");
647                AsyncResult.forMessage(onComplete).exception = e;
648                onComplete.sendToTarget();
649                return;
650            }
651        }
652    }
653
654    @Override
655    public void setIccFdnEnabled(boolean enabled, String password, Message onComplete) {
656        synchronized (mLock) {
657            if (mUiccApplication != null) {
658                mUiccApplication.setIccFdnEnabled(enabled, password, onComplete);
659            } else if (onComplete != null) {
660                Exception e = new RuntimeException("ICC card is absent.");
661                AsyncResult.forMessage(onComplete).exception = e;
662                onComplete.sendToTarget();
663                return;
664            }
665        }
666    }
667
668    @Override
669    public void changeIccLockPassword(String oldPassword, String newPassword, Message onComplete) {
670        synchronized (mLock) {
671            if (mUiccApplication != null) {
672                mUiccApplication.changeIccLockPassword(oldPassword, newPassword, onComplete);
673            } else if (onComplete != null) {
674                Exception e = new RuntimeException("ICC card is absent.");
675                AsyncResult.forMessage(onComplete).exception = e;
676                onComplete.sendToTarget();
677                return;
678            }
679        }
680    }
681
682    @Override
683    public void changeIccFdnPassword(String oldPassword, String newPassword, Message onComplete) {
684        synchronized (mLock) {
685            if (mUiccApplication != null) {
686                mUiccApplication.changeIccFdnPassword(oldPassword, newPassword, onComplete);
687            } else if (onComplete != null) {
688                Exception e = new RuntimeException("ICC card is absent.");
689                AsyncResult.forMessage(onComplete).exception = e;
690                onComplete.sendToTarget();
691                return;
692            }
693        }
694    }
695
696    @Override
697    public String getServiceProviderName() {
698        synchronized (mLock) {
699            if (mIccRecords != null) {
700                return mIccRecords.getServiceProviderName();
701            }
702            return null;
703        }
704    }
705
706    @Override
707    public boolean isApplicationOnIcc(IccCardApplicationStatus.AppType type) {
708        synchronized (mLock) {
709            Boolean retValue = mUiccCard != null ? mUiccCard.isApplicationOnIcc(type) : false;
710            return retValue;
711        }
712    }
713
714    @Override
715    public boolean hasIccCard() {
716        synchronized (mLock) {
717            if (mUiccCard != null && mUiccCard.getCardState() != CardState.CARDSTATE_ABSENT) {
718                return true;
719            }
720            return false;
721        }
722    }
723
724    private void log(String s) {
725        Rlog.d(LOG_TAG, s);
726    }
727
728    private void loge(String msg) {
729        Rlog.e(LOG_TAG, msg);
730    }
731
732    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
733        pw.println("IccCardProxy: " + this);
734        pw.println(" mContext=" + mContext);
735        pw.println(" mCi=" + mCi);
736        pw.println(" mAbsentRegistrants: size=" + mAbsentRegistrants.size());
737        for (int i = 0; i < mAbsentRegistrants.size(); i++) {
738            pw.println("  mAbsentRegistrants[" + i + "]="
739                    + ((Registrant)mAbsentRegistrants.get(i)).getHandler());
740        }
741        pw.println(" mPinLockedRegistrants: size=" + mPinLockedRegistrants.size());
742        for (int i = 0; i < mPinLockedRegistrants.size(); i++) {
743            pw.println("  mPinLockedRegistrants[" + i + "]="
744                    + ((Registrant)mPinLockedRegistrants.get(i)).getHandler());
745        }
746        pw.println(" mNetworkLockedRegistrants: size=" + mNetworkLockedRegistrants.size());
747        for (int i = 0; i < mNetworkLockedRegistrants.size(); i++) {
748            pw.println("  mNetworkLockedRegistrants[" + i + "]="
749                    + ((Registrant)mNetworkLockedRegistrants.get(i)).getHandler());
750        }
751        pw.println(" mCurrentAppType=" + mCurrentAppType);
752        pw.println(" mUiccController=" + mUiccController);
753        pw.println(" mUiccCard=" + mUiccCard);
754        pw.println(" mUiccApplication=" + mUiccApplication);
755        pw.println(" mIccRecords=" + mIccRecords);
756        pw.println(" mCdmaSSM=" + mCdmaSSM);
757        pw.println(" mRadioOn=" + mRadioOn);
758        pw.println(" mQuietMode=" + mQuietMode);
759        pw.println(" mInitialized=" + mInitialized);
760        pw.println(" mExternalState=" + mExternalState);
761
762        pw.flush();
763    }
764}
765