Home | History | Annotate | Download | only in uicc
      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 
     17 package com.android.internal.telephony.uicc;
     18 
     19 import static android.Manifest.permission.READ_PHONE_STATE;
     20 import android.app.ActivityManagerNative;
     21 import android.content.Context;
     22 import android.content.Intent;
     23 import android.os.AsyncResult;
     24 import android.os.Handler;
     25 import android.os.Message;
     26 import android.os.Registrant;
     27 import android.os.RegistrantList;
     28 import android.os.SystemProperties;
     29 import android.os.UserHandle;
     30 import android.telephony.Rlog;
     31 import android.telephony.ServiceState;
     32 import android.telephony.TelephonyManager;
     33 
     34 import com.android.internal.telephony.CommandsInterface;
     35 import com.android.internal.telephony.IccCard;
     36 import com.android.internal.telephony.IccCardConstants;
     37 import com.android.internal.telephony.PhoneConstants;
     38 import com.android.internal.telephony.RILConstants;
     39 import com.android.internal.telephony.TelephonyIntents;
     40 import com.android.internal.telephony.IccCardConstants.State;
     41 import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager;
     42 import com.android.internal.telephony.Phone;
     43 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppState;
     44 import com.android.internal.telephony.uicc.IccCardApplicationStatus.PersoSubState;
     45 import com.android.internal.telephony.uicc.IccCardStatus.CardState;
     46 import com.android.internal.telephony.uicc.IccCardStatus.PinState;
     47 import com.android.internal.telephony.uicc.UiccController;
     48 
     49 import java.io.FileDescriptor;
     50 import java.io.PrintWriter;
     51 
     52 import 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 
     72 public 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 true, if ICC is absent */
    608             Boolean retValue = mUiccApplication != null ? mUiccApplication.getIccLockEnabled() : true;
    609             return retValue;
    610         }
    611     }
    612 
    613     @Override
    614     public boolean getIccFdnEnabled() {
    615         synchronized (mLock) {
    616             Boolean retValue = mUiccApplication != null ? mUiccApplication.getIccFdnEnabled() : false;
    617             return retValue;
    618         }
    619     }
    620 
    621     @Override
    622     public void setIccLockEnabled(boolean enabled, String password, Message onComplete) {
    623         synchronized (mLock) {
    624             if (mUiccApplication != null) {
    625                 mUiccApplication.setIccLockEnabled(enabled, password, onComplete);
    626             } else if (onComplete != null) {
    627                 Exception e = new RuntimeException("ICC card is absent.");
    628                 AsyncResult.forMessage(onComplete).exception = e;
    629                 onComplete.sendToTarget();
    630                 return;
    631             }
    632         }
    633     }
    634 
    635     @Override
    636     public void setIccFdnEnabled(boolean enabled, String password, Message onComplete) {
    637         synchronized (mLock) {
    638             if (mUiccApplication != null) {
    639                 mUiccApplication.setIccFdnEnabled(enabled, password, onComplete);
    640             } else if (onComplete != null) {
    641                 Exception e = new RuntimeException("ICC card is absent.");
    642                 AsyncResult.forMessage(onComplete).exception = e;
    643                 onComplete.sendToTarget();
    644                 return;
    645             }
    646         }
    647     }
    648 
    649     @Override
    650     public void changeIccLockPassword(String oldPassword, String newPassword, Message onComplete) {
    651         synchronized (mLock) {
    652             if (mUiccApplication != null) {
    653                 mUiccApplication.changeIccLockPassword(oldPassword, newPassword, onComplete);
    654             } else if (onComplete != null) {
    655                 Exception e = new RuntimeException("ICC card is absent.");
    656                 AsyncResult.forMessage(onComplete).exception = e;
    657                 onComplete.sendToTarget();
    658                 return;
    659             }
    660         }
    661     }
    662 
    663     @Override
    664     public void changeIccFdnPassword(String oldPassword, String newPassword, Message onComplete) {
    665         synchronized (mLock) {
    666             if (mUiccApplication != null) {
    667                 mUiccApplication.changeIccFdnPassword(oldPassword, newPassword, onComplete);
    668             } else if (onComplete != null) {
    669                 Exception e = new RuntimeException("ICC card is absent.");
    670                 AsyncResult.forMessage(onComplete).exception = e;
    671                 onComplete.sendToTarget();
    672                 return;
    673             }
    674         }
    675     }
    676 
    677     @Override
    678     public String getServiceProviderName() {
    679         synchronized (mLock) {
    680             if (mIccRecords != null) {
    681                 return mIccRecords.getServiceProviderName();
    682             }
    683             return null;
    684         }
    685     }
    686 
    687     @Override
    688     public boolean isApplicationOnIcc(IccCardApplicationStatus.AppType type) {
    689         synchronized (mLock) {
    690             Boolean retValue = mUiccCard != null ? mUiccCard.isApplicationOnIcc(type) : false;
    691             return retValue;
    692         }
    693     }
    694 
    695     @Override
    696     public boolean hasIccCard() {
    697         synchronized (mLock) {
    698             if (mUiccCard != null && mUiccCard.getCardState() != CardState.CARDSTATE_ABSENT) {
    699                 return true;
    700             }
    701             return false;
    702         }
    703     }
    704 
    705     private void log(String s) {
    706         Rlog.d(LOG_TAG, s);
    707     }
    708 
    709     private void loge(String msg) {
    710         Rlog.e(LOG_TAG, msg);
    711     }
    712 
    713     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
    714         pw.println("IccCardProxy: " + this);
    715         pw.println(" mContext=" + mContext);
    716         pw.println(" mCi=" + mCi);
    717         pw.println(" mAbsentRegistrants: size=" + mAbsentRegistrants.size());
    718         for (int i = 0; i < mAbsentRegistrants.size(); i++) {
    719             pw.println("  mAbsentRegistrants[" + i + "]="
    720                     + ((Registrant)mAbsentRegistrants.get(i)).getHandler());
    721         }
    722         pw.println(" mPinLockedRegistrants: size=" + mPinLockedRegistrants.size());
    723         for (int i = 0; i < mPinLockedRegistrants.size(); i++) {
    724             pw.println("  mPinLockedRegistrants[" + i + "]="
    725                     + ((Registrant)mPinLockedRegistrants.get(i)).getHandler());
    726         }
    727         pw.println(" mNetworkLockedRegistrants: size=" + mNetworkLockedRegistrants.size());
    728         for (int i = 0; i < mNetworkLockedRegistrants.size(); i++) {
    729             pw.println("  mNetworkLockedRegistrants[" + i + "]="
    730                     + ((Registrant)mNetworkLockedRegistrants.get(i)).getHandler());
    731         }
    732         pw.println(" mCurrentAppType=" + mCurrentAppType);
    733         pw.println(" mUiccController=" + mUiccController);
    734         pw.println(" mUiccCard=" + mUiccCard);
    735         pw.println(" mUiccApplication=" + mUiccApplication);
    736         pw.println(" mIccRecords=" + mIccRecords);
    737         pw.println(" mCdmaSSM=" + mCdmaSSM);
    738         pw.println(" mRadioOn=" + mRadioOn);
    739         pw.println(" mQuietMode=" + mQuietMode);
    740         pw.println(" mInitialized=" + mInitialized);
    741         pw.println(" mExternalState=" + mExternalState);
    742 
    743         pw.flush();
    744     }
    745 }
    746