IccCardProxy.java revision e16ec244df35cec3ce69b513ee48e0906edf1999
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            setExternalState(State.CARD_IO_ERROR);
286            return;
287        }
288
289        if (mUiccApplication == null) {
290            setExternalState(State.NOT_READY);
291            return;
292        }
293
294        switch (mUiccApplication.getState()) {
295            case APPSTATE_UNKNOWN:
296            case APPSTATE_DETECTED:
297                setExternalState(State.UNKNOWN);
298                break;
299            case APPSTATE_PIN:
300                setExternalState(State.PIN_REQUIRED);
301                break;
302            case APPSTATE_PUK:
303                setExternalState(State.PUK_REQUIRED);
304                break;
305            case APPSTATE_SUBSCRIPTION_PERSO:
306                if (mUiccApplication.getPersoSubState() == PersoSubState.PERSOSUBSTATE_SIM_NETWORK) {
307                    setExternalState(State.NETWORK_LOCKED);
308                } else {
309                    setExternalState(State.UNKNOWN);
310                }
311                break;
312            case APPSTATE_READY:
313                setExternalState(State.READY);
314                break;
315        }
316    }
317
318    private void registerUiccCardEvents() {
319        if (mUiccCard != null) mUiccCard.registerForAbsent(this, EVENT_ICC_ABSENT, null);
320        if (mUiccApplication != null) {
321            mUiccApplication.registerForReady(this, EVENT_APP_READY, null);
322            mUiccApplication.registerForLocked(this, EVENT_ICC_LOCKED, null);
323            mUiccApplication.registerForNetworkLocked(this, EVENT_NETWORK_LOCKED, null);
324        }
325        if (mIccRecords != null) {
326            mIccRecords.registerForImsiReady(this, EVENT_IMSI_READY, null);
327            mIccRecords.registerForRecordsLoaded(this, EVENT_RECORDS_LOADED, null);
328        }
329    }
330
331    private void unregisterUiccCardEvents() {
332        if (mUiccCard != null) mUiccCard.unregisterForAbsent(this);
333        if (mUiccApplication != null) mUiccApplication.unregisterForReady(this);
334        if (mUiccApplication != null) mUiccApplication.unregisterForLocked(this);
335        if (mUiccApplication != null) mUiccApplication.unregisterForNetworkLocked(this);
336        if (mIccRecords != null) mIccRecords.unregisterForImsiReady(this);
337        if (mIccRecords != null) mIccRecords.unregisterForRecordsLoaded(this);
338    }
339
340    private void broadcastIccStateChangedIntent(String value, String reason) {
341        synchronized (mLock) {
342            if (mQuietMode) {
343                log("QuietMode: NOT Broadcasting intent ACTION_SIM_STATE_CHANGED " +  value
344                        + " reason " + reason);
345                return;
346            }
347
348            Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
349            intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
350            intent.putExtra(PhoneConstants.PHONE_NAME_KEY, "Phone");
351            intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, value);
352            intent.putExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON, reason);
353
354            if (DBG) log("Broadcasting intent ACTION_SIM_STATE_CHANGED " +  value
355                    + " reason " + reason);
356            ActivityManagerNative.broadcastStickyIntent(intent, READ_PHONE_STATE,
357                    UserHandle.USER_ALL);
358        }
359    }
360
361    private void processLockedState() {
362        synchronized (mLock) {
363            if (mUiccApplication == null) {
364                //Don't need to do anything if non-existent application is locked
365                return;
366            }
367            PinState pin1State = mUiccApplication.getPin1State();
368            if (pin1State == PinState.PINSTATE_ENABLED_PERM_BLOCKED) {
369                setExternalState(State.PERM_DISABLED);
370                return;
371            }
372
373            AppState appState = mUiccApplication.getState();
374            switch (appState) {
375                case APPSTATE_PIN:
376                    mPinLockedRegistrants.notifyRegistrants();
377                    setExternalState(State.PIN_REQUIRED);
378                    break;
379                case APPSTATE_PUK:
380                    setExternalState(State.PUK_REQUIRED);
381                    break;
382                case APPSTATE_DETECTED:
383                case APPSTATE_READY:
384                case APPSTATE_SUBSCRIPTION_PERSO:
385                case APPSTATE_UNKNOWN:
386                    // Neither required
387                    break;
388            }
389        }
390    }
391
392    private void setExternalState(State newState, boolean override) {
393        synchronized (mLock) {
394            if (!override && newState == mExternalState) {
395                return;
396            }
397            mExternalState = newState;
398            SystemProperties.set(PROPERTY_SIM_STATE, mExternalState.toString());
399            broadcastIccStateChangedIntent(getIccStateIntentString(mExternalState),
400                    getIccStateReason(mExternalState));
401        }
402    }
403
404    private void setExternalState(State newState) {
405        setExternalState(newState, false);
406    }
407
408    public boolean getIccRecordsLoaded() {
409        synchronized (mLock) {
410            if (mIccRecords != null) {
411                return mIccRecords.getRecordsLoaded();
412            }
413            return false;
414        }
415    }
416
417    private String getIccStateIntentString(State state) {
418        switch (state) {
419            case ABSENT: return IccCardConstants.INTENT_VALUE_ICC_ABSENT;
420            case PIN_REQUIRED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED;
421            case PUK_REQUIRED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED;
422            case NETWORK_LOCKED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED;
423            case READY: return IccCardConstants.INTENT_VALUE_ICC_READY;
424            case NOT_READY: return IccCardConstants.INTENT_VALUE_ICC_NOT_READY;
425            case PERM_DISABLED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED;
426            case CARD_IO_ERROR: return IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR;
427            default: return IccCardConstants.INTENT_VALUE_ICC_UNKNOWN;
428        }
429    }
430
431    /**
432     * Locked state have a reason (PIN, PUK, NETWORK, PERM_DISABLED, CARD_IO_ERROR)
433     * @return reason
434     */
435    private String getIccStateReason(State state) {
436        switch (state) {
437            case PIN_REQUIRED: return IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN;
438            case PUK_REQUIRED: return IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK;
439            case NETWORK_LOCKED: return IccCardConstants.INTENT_VALUE_LOCKED_NETWORK;
440            case PERM_DISABLED: return IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED;
441            case CARD_IO_ERROR: return IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR;
442            default: return null;
443       }
444    }
445
446    /* IccCard interface implementation */
447    @Override
448    public State getState() {
449        synchronized (mLock) {
450            return mExternalState;
451        }
452    }
453
454    @Override
455    public IccRecords getIccRecords() {
456        synchronized (mLock) {
457            return mIccRecords;
458        }
459    }
460
461    @Override
462    public IccFileHandler getIccFileHandler() {
463        synchronized (mLock) {
464            if (mUiccApplication != null) {
465                return mUiccApplication.getIccFileHandler();
466            }
467            return null;
468        }
469    }
470
471    /**
472     * Notifies handler of any transition into State.ABSENT
473     */
474    @Override
475    public void registerForAbsent(Handler h, int what, Object obj) {
476        synchronized (mLock) {
477            Registrant r = new Registrant (h, what, obj);
478
479            mAbsentRegistrants.add(r);
480
481            if (getState() == State.ABSENT) {
482                r.notifyRegistrant();
483            }
484        }
485    }
486
487    @Override
488    public void unregisterForAbsent(Handler h) {
489        synchronized (mLock) {
490            mAbsentRegistrants.remove(h);
491        }
492    }
493
494    /**
495     * Notifies handler of any transition into State.NETWORK_LOCKED
496     */
497    @Override
498    public void registerForNetworkLocked(Handler h, int what, Object obj) {
499        synchronized (mLock) {
500            Registrant r = new Registrant (h, what, obj);
501
502            mNetworkLockedRegistrants.add(r);
503
504            if (getState() == State.NETWORK_LOCKED) {
505                r.notifyRegistrant();
506            }
507        }
508    }
509
510    @Override
511    public void unregisterForNetworkLocked(Handler h) {
512        synchronized (mLock) {
513            mNetworkLockedRegistrants.remove(h);
514        }
515    }
516
517    /**
518     * Notifies handler of any transition into State.isPinLocked()
519     */
520    @Override
521    public void registerForLocked(Handler h, int what, Object obj) {
522        synchronized (mLock) {
523            Registrant r = new Registrant (h, what, obj);
524
525            mPinLockedRegistrants.add(r);
526
527            if (getState().isPinLocked()) {
528                r.notifyRegistrant();
529            }
530        }
531    }
532
533    @Override
534    public void unregisterForLocked(Handler h) {
535        synchronized (mLock) {
536            mPinLockedRegistrants.remove(h);
537        }
538    }
539
540    @Override
541    public void supplyPin(String pin, Message onComplete) {
542        synchronized (mLock) {
543            if (mUiccApplication != null) {
544                mUiccApplication.supplyPin(pin, onComplete);
545            } else if (onComplete != null) {
546                Exception e = new RuntimeException("ICC card is absent.");
547                AsyncResult.forMessage(onComplete).exception = e;
548                onComplete.sendToTarget();
549                return;
550            }
551        }
552    }
553
554    @Override
555    public void supplyPuk(String puk, String newPin, Message onComplete) {
556        synchronized (mLock) {
557            if (mUiccApplication != null) {
558                mUiccApplication.supplyPuk(puk, newPin, onComplete);
559            } else if (onComplete != null) {
560                Exception e = new RuntimeException("ICC card is absent.");
561                AsyncResult.forMessage(onComplete).exception = e;
562                onComplete.sendToTarget();
563                return;
564            }
565        }
566    }
567
568    @Override
569    public void supplyPin2(String pin2, Message onComplete) {
570        synchronized (mLock) {
571            if (mUiccApplication != null) {
572                mUiccApplication.supplyPin2(pin2, onComplete);
573            } else if (onComplete != null) {
574                Exception e = new RuntimeException("ICC card is absent.");
575                AsyncResult.forMessage(onComplete).exception = e;
576                onComplete.sendToTarget();
577                return;
578            }
579        }
580    }
581
582    @Override
583    public void supplyPuk2(String puk2, String newPin2, Message onComplete) {
584        synchronized (mLock) {
585            if (mUiccApplication != null) {
586                mUiccApplication.supplyPuk2(puk2, newPin2, onComplete);
587            } else if (onComplete != null) {
588                Exception e = new RuntimeException("ICC card is absent.");
589                AsyncResult.forMessage(onComplete).exception = e;
590                onComplete.sendToTarget();
591                return;
592            }
593        }
594    }
595
596    @Override
597    public void supplyNetworkDepersonalization(String pin, Message onComplete) {
598        synchronized (mLock) {
599            if (mUiccApplication != null) {
600                mUiccApplication.supplyNetworkDepersonalization(pin, onComplete);
601            } else if (onComplete != null) {
602                Exception e = new RuntimeException("CommandsInterface is not set.");
603                AsyncResult.forMessage(onComplete).exception = e;
604                onComplete.sendToTarget();
605                return;
606            }
607        }
608    }
609
610    @Override
611    public boolean getIccLockEnabled() {
612        synchronized (mLock) {
613            /* defaults to false, if ICC is absent/deactivated */
614            Boolean retValue = mUiccApplication != null ?
615                    mUiccApplication.getIccLockEnabled() : false;
616            return retValue;
617        }
618    }
619
620    @Override
621    public boolean getIccFdnEnabled() {
622        synchronized (mLock) {
623            Boolean retValue = mUiccApplication != null ?
624                    mUiccApplication.getIccFdnEnabled() : false;
625            return retValue;
626        }
627    }
628
629    public boolean getIccFdnAvailable() {
630        boolean retValue = mUiccApplication != null ? mUiccApplication.getIccFdnAvailable() : false;
631        return retValue;
632    }
633
634    public boolean getIccPin2Blocked() {
635        /* defaults to disabled */
636        Boolean retValue = mUiccApplication != null ? mUiccApplication.getIccPin2Blocked() : false;
637        return retValue;
638    }
639
640    public boolean getIccPuk2Blocked() {
641        /* defaults to disabled */
642        Boolean retValue = mUiccApplication != null ? mUiccApplication.getIccPuk2Blocked() : false;
643        return retValue;
644    }
645
646    @Override
647    public void setIccLockEnabled(boolean enabled, String password, Message onComplete) {
648        synchronized (mLock) {
649            if (mUiccApplication != null) {
650                mUiccApplication.setIccLockEnabled(enabled, password, onComplete);
651            } else if (onComplete != null) {
652                Exception e = new RuntimeException("ICC card is absent.");
653                AsyncResult.forMessage(onComplete).exception = e;
654                onComplete.sendToTarget();
655                return;
656            }
657        }
658    }
659
660    @Override
661    public void setIccFdnEnabled(boolean enabled, String password, Message onComplete) {
662        synchronized (mLock) {
663            if (mUiccApplication != null) {
664                mUiccApplication.setIccFdnEnabled(enabled, password, onComplete);
665            } else if (onComplete != null) {
666                Exception e = new RuntimeException("ICC card is absent.");
667                AsyncResult.forMessage(onComplete).exception = e;
668                onComplete.sendToTarget();
669                return;
670            }
671        }
672    }
673
674    @Override
675    public void changeIccLockPassword(String oldPassword, String newPassword, Message onComplete) {
676        synchronized (mLock) {
677            if (mUiccApplication != null) {
678                mUiccApplication.changeIccLockPassword(oldPassword, newPassword, onComplete);
679            } else if (onComplete != null) {
680                Exception e = new RuntimeException("ICC card is absent.");
681                AsyncResult.forMessage(onComplete).exception = e;
682                onComplete.sendToTarget();
683                return;
684            }
685        }
686    }
687
688    @Override
689    public void changeIccFdnPassword(String oldPassword, String newPassword, Message onComplete) {
690        synchronized (mLock) {
691            if (mUiccApplication != null) {
692                mUiccApplication.changeIccFdnPassword(oldPassword, newPassword, onComplete);
693            } else if (onComplete != null) {
694                Exception e = new RuntimeException("ICC card is absent.");
695                AsyncResult.forMessage(onComplete).exception = e;
696                onComplete.sendToTarget();
697                return;
698            }
699        }
700    }
701
702    @Override
703    public String getServiceProviderName() {
704        synchronized (mLock) {
705            if (mIccRecords != null) {
706                return mIccRecords.getServiceProviderName();
707            }
708            return null;
709        }
710    }
711
712    @Override
713    public boolean isApplicationOnIcc(IccCardApplicationStatus.AppType type) {
714        synchronized (mLock) {
715            Boolean retValue = mUiccCard != null ? mUiccCard.isApplicationOnIcc(type) : false;
716            return retValue;
717        }
718    }
719
720    @Override
721    public boolean hasIccCard() {
722        synchronized (mLock) {
723            if (mUiccCard != null && mUiccCard.getCardState() != CardState.CARDSTATE_ABSENT) {
724                return true;
725            }
726            return false;
727        }
728    }
729
730    private void log(String s) {
731        Rlog.d(LOG_TAG, s);
732    }
733
734    private void loge(String msg) {
735        Rlog.e(LOG_TAG, msg);
736    }
737
738    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
739        pw.println("IccCardProxy: " + this);
740        pw.println(" mContext=" + mContext);
741        pw.println(" mCi=" + mCi);
742        pw.println(" mAbsentRegistrants: size=" + mAbsentRegistrants.size());
743        for (int i = 0; i < mAbsentRegistrants.size(); i++) {
744            pw.println("  mAbsentRegistrants[" + i + "]="
745                    + ((Registrant)mAbsentRegistrants.get(i)).getHandler());
746        }
747        pw.println(" mPinLockedRegistrants: size=" + mPinLockedRegistrants.size());
748        for (int i = 0; i < mPinLockedRegistrants.size(); i++) {
749            pw.println("  mPinLockedRegistrants[" + i + "]="
750                    + ((Registrant)mPinLockedRegistrants.get(i)).getHandler());
751        }
752        pw.println(" mNetworkLockedRegistrants: size=" + mNetworkLockedRegistrants.size());
753        for (int i = 0; i < mNetworkLockedRegistrants.size(); i++) {
754            pw.println("  mNetworkLockedRegistrants[" + i + "]="
755                    + ((Registrant)mNetworkLockedRegistrants.get(i)).getHandler());
756        }
757        pw.println(" mCurrentAppType=" + mCurrentAppType);
758        pw.println(" mUiccController=" + mUiccController);
759        pw.println(" mUiccCard=" + mUiccCard);
760        pw.println(" mUiccApplication=" + mUiccApplication);
761        pw.println(" mIccRecords=" + mIccRecords);
762        pw.println(" mCdmaSSM=" + mCdmaSSM);
763        pw.println(" mRadioOn=" + mRadioOn);
764        pw.println(" mQuietMode=" + mQuietMode);
765        pw.println(" mInitialized=" + mInitialized);
766        pw.println(" mExternalState=" + mExternalState);
767
768        pw.flush();
769    }
770}
771