Home | History | Annotate | Download | only in uicc
      1 /*
      2  * Copyright (C) 2006, 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.internal.telephony.uicc;
     18 
     19 import static android.Manifest.permission.READ_PHONE_STATE;
     20 import android.app.ActivityManagerNative;
     21 import android.app.AlertDialog;
     22 import android.content.Context;
     23 import android.content.DialogInterface;
     24 import android.content.Intent;
     25 import android.content.SharedPreferences;
     26 import android.content.pm.PackageManager;
     27 import android.content.pm.Signature;
     28 import android.content.res.Resources;
     29 import android.os.AsyncResult;
     30 import android.os.Handler;
     31 import android.os.Message;
     32 import android.os.PowerManager;
     33 import android.os.Registrant;
     34 import android.os.RegistrantList;
     35 import android.preference.PreferenceManager;
     36 import android.telephony.Rlog;
     37 import android.telephony.TelephonyManager;
     38 import android.text.TextUtils;
     39 import android.view.WindowManager;
     40 
     41 import com.android.internal.telephony.CommandsInterface;
     42 import com.android.internal.telephony.PhoneBase;
     43 import com.android.internal.telephony.CommandsInterface.RadioState;
     44 import com.android.internal.telephony.IccCardConstants.State;
     45 import com.android.internal.telephony.gsm.GSMPhone;
     46 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
     47 import com.android.internal.telephony.uicc.IccCardStatus.CardState;
     48 import com.android.internal.telephony.uicc.IccCardStatus.PinState;
     49 import com.android.internal.telephony.cat.CatService;
     50 import com.android.internal.telephony.cdma.CDMALTEPhone;
     51 import com.android.internal.telephony.cdma.CDMAPhone;
     52 import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager;
     53 
     54 import android.os.SystemProperties;
     55 
     56 import com.android.internal.R;
     57 
     58 import java.io.FileDescriptor;
     59 import java.io.PrintWriter;
     60 import java.util.List;
     61 
     62 /**
     63  * {@hide}
     64  */
     65 public class UiccCard {
     66     protected static final String LOG_TAG = "UiccCard";
     67     protected static final boolean DBG = true;
     68 
     69     private static final String OPERATOR_BRAND_OVERRIDE_PREFIX = "operator_branding_";
     70 
     71     private final Object mLock = new Object();
     72     private CardState mCardState;
     73     private PinState mUniversalPinState;
     74     private int mGsmUmtsSubscriptionAppIndex;
     75     private int mCdmaSubscriptionAppIndex;
     76     private int mImsSubscriptionAppIndex;
     77     private UiccCardApplication[] mUiccApplications =
     78             new UiccCardApplication[IccCardStatus.CARD_MAX_APPS];
     79     private Context mContext;
     80     private CommandsInterface mCi;
     81     private CatService mCatService;
     82     private boolean mDestroyed = false; //set to true once this card is commanded to be disposed of.
     83     private RadioState mLastRadioState =  RadioState.RADIO_UNAVAILABLE;
     84     private UiccCarrierPrivilegeRules mCarrierPrivilegeRules;
     85 
     86     private RegistrantList mAbsentRegistrants = new RegistrantList();
     87     private RegistrantList mCarrierPrivilegeRegistrants = new RegistrantList();
     88 
     89     private static final int EVENT_CARD_REMOVED = 13;
     90     private static final int EVENT_CARD_ADDED = 14;
     91     private static final int EVENT_OPEN_LOGICAL_CHANNEL_DONE = 15;
     92     private static final int EVENT_CLOSE_LOGICAL_CHANNEL_DONE = 16;
     93     private static final int EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE = 17;
     94     private static final int EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE = 18;
     95     private static final int EVENT_SIM_IO_DONE = 19;
     96     private static final int EVENT_CARRIER_PRIVILIGES_LOADED = 20;
     97 
     98     int mSlotId;
     99 
    100     public UiccCard(Context c, CommandsInterface ci, IccCardStatus ics) {
    101         if (DBG) log("Creating");
    102         mCardState = ics.mCardState;
    103         update(c, ci, ics);
    104     }
    105 
    106     public UiccCard(Context c, CommandsInterface ci, IccCardStatus ics, int slotId) {
    107         mCardState = ics.mCardState;
    108         mSlotId = slotId;
    109         update(c, ci, ics);
    110     }
    111 
    112     protected UiccCard() {
    113     }
    114 
    115     public void dispose() {
    116         synchronized (mLock) {
    117             if (DBG) log("Disposing card");
    118             if (mCatService != null) mCatService.dispose();
    119             for (UiccCardApplication app : mUiccApplications) {
    120                 if (app != null) {
    121                     app.dispose();
    122                 }
    123             }
    124             mCatService = null;
    125             mUiccApplications = null;
    126             mCarrierPrivilegeRules = null;
    127         }
    128     }
    129 
    130     public void update(Context c, CommandsInterface ci, IccCardStatus ics) {
    131         synchronized (mLock) {
    132             if (mDestroyed) {
    133                 loge("Updated after destroyed! Fix me!");
    134                 return;
    135             }
    136             CardState oldState = mCardState;
    137             mCardState = ics.mCardState;
    138             mUniversalPinState = ics.mUniversalPinState;
    139             mGsmUmtsSubscriptionAppIndex = ics.mGsmUmtsSubscriptionAppIndex;
    140             mCdmaSubscriptionAppIndex = ics.mCdmaSubscriptionAppIndex;
    141             mImsSubscriptionAppIndex = ics.mImsSubscriptionAppIndex;
    142             mContext = c;
    143             mCi = ci;
    144             //update applications
    145             if (DBG) log(ics.mApplications.length + " applications");
    146             for ( int i = 0; i < mUiccApplications.length; i++) {
    147                 if (mUiccApplications[i] == null) {
    148                     //Create newly added Applications
    149                     if (i < ics.mApplications.length) {
    150                         mUiccApplications[i] = new UiccCardApplication(this,
    151                                 ics.mApplications[i], mContext, mCi);
    152                     }
    153                 } else if (i >= ics.mApplications.length) {
    154                     //Delete removed applications
    155                     mUiccApplications[i].dispose();
    156                     mUiccApplications[i] = null;
    157                 } else {
    158                     //Update the rest
    159                     mUiccApplications[i].update(ics.mApplications[i], mContext, mCi);
    160                 }
    161             }
    162 
    163             createAndUpdateCatService();
    164 
    165             // Reload the carrier privilege rules if necessary.
    166             log("Before privilege rules: " + mCarrierPrivilegeRules + " : " + mCardState);
    167             if (mCarrierPrivilegeRules == null && mCardState == CardState.CARDSTATE_PRESENT) {
    168                 mCarrierPrivilegeRules = new UiccCarrierPrivilegeRules(this,
    169                         mHandler.obtainMessage(EVENT_CARRIER_PRIVILIGES_LOADED));
    170             } else if (mCarrierPrivilegeRules != null && mCardState != CardState.CARDSTATE_PRESENT) {
    171                 mCarrierPrivilegeRules = null;
    172             }
    173 
    174             sanitizeApplicationIndexes();
    175 
    176             RadioState radioState = mCi.getRadioState();
    177             if (DBG) log("update: radioState=" + radioState + " mLastRadioState="
    178                     + mLastRadioState);
    179             // No notifications while radio is off or we just powering up
    180             if (radioState == RadioState.RADIO_ON && mLastRadioState == RadioState.RADIO_ON) {
    181                 if (oldState != CardState.CARDSTATE_ABSENT &&
    182                         mCardState == CardState.CARDSTATE_ABSENT) {
    183                     if (DBG) log("update: notify card removed");
    184                     mAbsentRegistrants.notifyRegistrants();
    185                     mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARD_REMOVED, null));
    186                 } else if (oldState == CardState.CARDSTATE_ABSENT &&
    187                         mCardState != CardState.CARDSTATE_ABSENT) {
    188                     if (DBG) log("update: notify card added");
    189                     mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARD_ADDED, null));
    190                 }
    191             }
    192             mLastRadioState = radioState;
    193         }
    194     }
    195 
    196     protected void createAndUpdateCatService() {
    197         if (mUiccApplications.length > 0 && mUiccApplications[0] != null) {
    198             // Initialize or Reinitialize CatService
    199             if (mCatService == null) {
    200                 mCatService = CatService.getInstance(mCi, mContext, this, mSlotId);
    201             } else {
    202                 ((CatService)mCatService).update(mCi, mContext, this);
    203             }
    204         } else {
    205             if (mCatService != null) {
    206                 mCatService.dispose();
    207             }
    208             mCatService = null;
    209         }
    210     }
    211 
    212     public CatService getCatService() {
    213         return mCatService;
    214     }
    215 
    216     @Override
    217     protected void finalize() {
    218         if (DBG) log("UiccCard finalized");
    219     }
    220 
    221     /**
    222      * This function makes sure that application indexes are valid
    223      * and resets invalid indexes. (This should never happen, but in case
    224      * RIL misbehaves we need to manage situation gracefully)
    225      */
    226     private void sanitizeApplicationIndexes() {
    227         mGsmUmtsSubscriptionAppIndex =
    228                 checkIndex(mGsmUmtsSubscriptionAppIndex, AppType.APPTYPE_SIM, AppType.APPTYPE_USIM);
    229         mCdmaSubscriptionAppIndex =
    230                 checkIndex(mCdmaSubscriptionAppIndex, AppType.APPTYPE_RUIM, AppType.APPTYPE_CSIM);
    231         mImsSubscriptionAppIndex =
    232                 checkIndex(mImsSubscriptionAppIndex, AppType.APPTYPE_ISIM, null);
    233     }
    234 
    235     private int checkIndex(int index, AppType expectedAppType, AppType altExpectedAppType) {
    236         if (mUiccApplications == null || index >= mUiccApplications.length) {
    237             loge("App index " + index + " is invalid since there are no applications");
    238             return -1;
    239         }
    240 
    241         if (index < 0) {
    242             // This is normal. (i.e. no application of this type)
    243             return -1;
    244         }
    245 
    246         if (mUiccApplications[index].getType() != expectedAppType &&
    247             mUiccApplications[index].getType() != altExpectedAppType) {
    248             loge("App index " + index + " is invalid since it's not " +
    249                     expectedAppType + " and not " + altExpectedAppType);
    250             return -1;
    251         }
    252 
    253         // Seems to be valid
    254         return index;
    255     }
    256 
    257     /**
    258      * Notifies handler of any transition into State.ABSENT
    259      */
    260     public void registerForAbsent(Handler h, int what, Object obj) {
    261         synchronized (mLock) {
    262             Registrant r = new Registrant (h, what, obj);
    263 
    264             mAbsentRegistrants.add(r);
    265 
    266             if (mCardState == CardState.CARDSTATE_ABSENT) {
    267                 r.notifyRegistrant();
    268             }
    269         }
    270     }
    271 
    272     public void unregisterForAbsent(Handler h) {
    273         synchronized (mLock) {
    274             mAbsentRegistrants.remove(h);
    275         }
    276     }
    277 
    278     /**
    279      * Notifies handler when carrier privilege rules are loaded.
    280      */
    281     public void registerForCarrierPrivilegeRulesLoaded(Handler h, int what, Object obj) {
    282         synchronized (mLock) {
    283             Registrant r = new Registrant (h, what, obj);
    284 
    285             mCarrierPrivilegeRegistrants.add(r);
    286 
    287             if (areCarrierPriviligeRulesLoaded()) {
    288                 r.notifyRegistrant();
    289             }
    290         }
    291     }
    292 
    293     public void unregisterForCarrierPrivilegeRulesLoaded(Handler h) {
    294         synchronized (mLock) {
    295             mCarrierPrivilegeRegistrants.remove(h);
    296         }
    297     }
    298 
    299     private void onIccSwap(boolean isAdded) {
    300 
    301         boolean isHotSwapSupported = mContext.getResources().getBoolean(
    302                 com.android.internal.R.bool.config_hotswapCapable);
    303 
    304         if (isHotSwapSupported) {
    305             log("onIccSwap: isHotSwapSupported is true, don't prompt for rebooting");
    306             return;
    307         }
    308         log("onIccSwap: isHotSwapSupported is false, prompt for rebooting");
    309 
    310         synchronized (mLock) {
    311             // TODO: Here we assume the device can't handle SIM hot-swap
    312             //      and has to reboot. We may want to add a property,
    313             //      e.g. REBOOT_ON_SIM_SWAP, to indicate if modem support
    314             //      hot-swap.
    315             DialogInterface.OnClickListener listener = null;
    316 
    317 
    318             // TODO: SimRecords is not reset while SIM ABSENT (only reset while
    319             //       Radio_off_or_not_available). Have to reset in both both
    320             //       added or removed situation.
    321             listener = new DialogInterface.OnClickListener() {
    322                 @Override
    323                 public void onClick(DialogInterface dialog, int which) {
    324                     synchronized (mLock) {
    325                         if (which == DialogInterface.BUTTON_POSITIVE) {
    326                             if (DBG) log("Reboot due to SIM swap");
    327                             PowerManager pm = (PowerManager) mContext
    328                                     .getSystemService(Context.POWER_SERVICE);
    329                             pm.reboot("SIM is added.");
    330                         }
    331                     }
    332                 }
    333 
    334             };
    335 
    336             Resources r = Resources.getSystem();
    337 
    338             String title = (isAdded) ? r.getString(R.string.sim_added_title) :
    339                 r.getString(R.string.sim_removed_title);
    340             String message = (isAdded) ? r.getString(R.string.sim_added_message) :
    341                 r.getString(R.string.sim_removed_message);
    342             String buttonTxt = r.getString(R.string.sim_restart_button);
    343 
    344             AlertDialog dialog = new AlertDialog.Builder(mContext)
    345             .setTitle(title)
    346             .setMessage(message)
    347             .setPositiveButton(buttonTxt, listener)
    348             .create();
    349             dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
    350             dialog.show();
    351         }
    352     }
    353 
    354     protected Handler mHandler = new Handler() {
    355         @Override
    356         public void handleMessage(Message msg){
    357             if (mDestroyed) {
    358                 loge("Received message " + msg + "[" + msg.what
    359                         + "] while being destroyed. Ignoring.");
    360                 return;
    361             }
    362 
    363             switch (msg.what) {
    364                 case EVENT_CARD_REMOVED:
    365                     onIccSwap(false);
    366                     break;
    367                 case EVENT_CARD_ADDED:
    368                     onIccSwap(true);
    369                     break;
    370                 case EVENT_OPEN_LOGICAL_CHANNEL_DONE:
    371                 case EVENT_CLOSE_LOGICAL_CHANNEL_DONE:
    372                 case EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE:
    373                 case EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE:
    374                 case EVENT_SIM_IO_DONE:
    375                     AsyncResult ar = (AsyncResult)msg.obj;
    376                     if (ar.exception != null) {
    377                        if (DBG)
    378                          log("Error in SIM access with exception" + ar.exception);
    379                     }
    380                     AsyncResult.forMessage((Message)ar.userObj, ar.result, ar.exception);
    381                     ((Message)ar.userObj).sendToTarget();
    382                     break;
    383                 case EVENT_CARRIER_PRIVILIGES_LOADED:
    384                     onCarrierPriviligesLoadedMessage();
    385                     break;
    386                 default:
    387                     loge("Unknown Event " + msg.what);
    388             }
    389         }
    390     };
    391 
    392     private void onCarrierPriviligesLoadedMessage() {
    393         synchronized (mLock) {
    394             mCarrierPrivilegeRegistrants.notifyRegistrants();
    395         }
    396     }
    397 
    398     public boolean isApplicationOnIcc(IccCardApplicationStatus.AppType type) {
    399         synchronized (mLock) {
    400             for (int i = 0 ; i < mUiccApplications.length; i++) {
    401                 if (mUiccApplications[i] != null && mUiccApplications[i].getType() == type) {
    402                     return true;
    403                 }
    404             }
    405             return false;
    406         }
    407     }
    408 
    409     public CardState getCardState() {
    410         synchronized (mLock) {
    411             return mCardState;
    412         }
    413     }
    414 
    415     public PinState getUniversalPinState() {
    416         synchronized (mLock) {
    417             return mUniversalPinState;
    418         }
    419     }
    420 
    421     public UiccCardApplication getApplication(int family) {
    422         synchronized (mLock) {
    423             int index = IccCardStatus.CARD_MAX_APPS;
    424             switch (family) {
    425                 case UiccController.APP_FAM_3GPP:
    426                     index = mGsmUmtsSubscriptionAppIndex;
    427                     break;
    428                 case UiccController.APP_FAM_3GPP2:
    429                     index = mCdmaSubscriptionAppIndex;
    430                     break;
    431                 case UiccController.APP_FAM_IMS:
    432                     index = mImsSubscriptionAppIndex;
    433                     break;
    434             }
    435             if (index >= 0 && index < mUiccApplications.length) {
    436                 return mUiccApplications[index];
    437             }
    438             return null;
    439         }
    440     }
    441 
    442     public UiccCardApplication getApplicationIndex(int index) {
    443         synchronized (mLock) {
    444             if (index >= 0 && index < mUiccApplications.length) {
    445                 return mUiccApplications[index];
    446             }
    447             return null;
    448         }
    449     }
    450 
    451     /**
    452      * Returns the SIM application of the specified type.
    453      *
    454      * @param type ICC application type (@see com.android.internal.telephony.PhoneConstants#APPTYPE_xxx)
    455      * @return application corresponding to type or a null if no match found
    456      */
    457     public UiccCardApplication getApplicationByType(int type) {
    458         synchronized (mLock) {
    459             for (int i = 0 ; i < mUiccApplications.length; i++) {
    460                 if (mUiccApplications[i] != null &&
    461                         mUiccApplications[i].getType().ordinal() == type) {
    462                     return mUiccApplications[i];
    463                 }
    464             }
    465             return null;
    466         }
    467     }
    468 
    469     /**
    470      * Exposes {@link CommandsInterface.iccOpenLogicalChannel}
    471      */
    472     public void iccOpenLogicalChannel(String AID, Message response) {
    473         mCi.iccOpenLogicalChannel(AID,
    474                 mHandler.obtainMessage(EVENT_OPEN_LOGICAL_CHANNEL_DONE, response));
    475     }
    476 
    477     /**
    478      * Exposes {@link CommandsInterface.iccCloseLogicalChannel}
    479      */
    480     public void iccCloseLogicalChannel(int channel, Message response) {
    481         mCi.iccCloseLogicalChannel(channel,
    482                 mHandler.obtainMessage(EVENT_CLOSE_LOGICAL_CHANNEL_DONE, response));
    483     }
    484 
    485     /**
    486      * Exposes {@link CommandsInterface.iccTransmitApduLogicalChannel}
    487      */
    488     public void iccTransmitApduLogicalChannel(int channel, int cla, int command,
    489             int p1, int p2, int p3, String data, Message response) {
    490         mCi.iccTransmitApduLogicalChannel(channel, cla, command, p1, p2, p3,
    491                 data, mHandler.obtainMessage(EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE, response));
    492     }
    493 
    494     /**
    495      * Exposes {@link CommandsInterface.iccTransmitApduBasicChannel}
    496      */
    497     public void iccTransmitApduBasicChannel(int cla, int command,
    498             int p1, int p2, int p3, String data, Message response) {
    499         mCi.iccTransmitApduBasicChannel(cla, command, p1, p2, p3,
    500                 data, mHandler.obtainMessage(EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE, response));
    501     }
    502 
    503     /**
    504      * Exposes {@link CommandsInterface.iccIO}
    505      */
    506     public void iccExchangeSimIO(int fileID, int command, int p1, int p2, int p3,
    507             String pathID, Message response) {
    508         mCi.iccIO(command, fileID, pathID, p1, p2, p3, null, null,
    509                 mHandler.obtainMessage(EVENT_SIM_IO_DONE, response));
    510     }
    511 
    512     /**
    513      * Exposes {@link CommandsInterface.sendEnvelopeWithStatus}
    514      */
    515     public void sendEnvelopeWithStatus(String contents, Message response) {
    516         mCi.sendEnvelopeWithStatus(contents, response);
    517     }
    518 
    519     /* Returns number of applications on this card */
    520     public int getNumApplications() {
    521         int count = 0;
    522         for (UiccCardApplication a : mUiccApplications) {
    523             if (a != null) {
    524                 count++;
    525             }
    526         }
    527         return count;
    528     }
    529 
    530     /**
    531      * Returns true iff carrier priveleges rules are null (dont need to be loaded) or loaded.
    532      */
    533     public boolean areCarrierPriviligeRulesLoaded() {
    534         return mCarrierPrivilegeRules == null
    535             || mCarrierPrivilegeRules.areCarrierPriviligeRulesLoaded();
    536     }
    537 
    538     /**
    539      * Exposes {@link UiccCarrierPrivilegeRules.getCarrierPrivilegeStatus}.
    540      */
    541     public int getCarrierPrivilegeStatus(Signature signature, String packageName) {
    542         return mCarrierPrivilegeRules == null ?
    543             TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED :
    544             mCarrierPrivilegeRules.getCarrierPrivilegeStatus(signature, packageName);
    545     }
    546 
    547     /**
    548      * Exposes {@link UiccCarrierPrivilegeRules.getCarrierPrivilegeStatus}.
    549      */
    550     public int getCarrierPrivilegeStatus(PackageManager packageManager, String packageName) {
    551         return mCarrierPrivilegeRules == null ?
    552             TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED :
    553             mCarrierPrivilegeRules.getCarrierPrivilegeStatus(packageManager, packageName);
    554     }
    555 
    556     /**
    557      * Exposes {@link UiccCarrierPrivilegeRules.getCarrierPrivilegeStatusForCurrentTransaction}.
    558      */
    559     public int getCarrierPrivilegeStatusForCurrentTransaction(PackageManager packageManager) {
    560         return mCarrierPrivilegeRules == null ?
    561             TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED :
    562             mCarrierPrivilegeRules.getCarrierPrivilegeStatusForCurrentTransaction(packageManager);
    563     }
    564 
    565     /**
    566      * Exposes {@link UiccCarrierPrivilegeRules.getCarrierPackageNamesForIntent}.
    567      */
    568     public List<String> getCarrierPackageNamesForIntent(
    569             PackageManager packageManager, Intent intent) {
    570         return mCarrierPrivilegeRules == null ? null :
    571             mCarrierPrivilegeRules.getCarrierPackageNamesForIntent(
    572                     packageManager, intent);
    573     }
    574 
    575     public boolean setOperatorBrandOverride(String brand) {
    576         log("setOperatorBrandOverride: " + brand);
    577         log("current iccId: " + getIccId());
    578 
    579         String iccId = getIccId();
    580         if (TextUtils.isEmpty(iccId)) {
    581             return false;
    582         }
    583 
    584         SharedPreferences.Editor spEditor =
    585                 PreferenceManager.getDefaultSharedPreferences(mContext).edit();
    586         String key = OPERATOR_BRAND_OVERRIDE_PREFIX + iccId;
    587         if (brand == null) {
    588             spEditor.remove(key).commit();
    589         } else {
    590             spEditor.putString(key, brand).commit();
    591         }
    592         return true;
    593     }
    594 
    595     public String getOperatorBrandOverride() {
    596         String iccId = getIccId();
    597         if (TextUtils.isEmpty(iccId)) {
    598             return null;
    599         }
    600         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
    601         return sp.getString(OPERATOR_BRAND_OVERRIDE_PREFIX + iccId, null);
    602     }
    603 
    604     public String getIccId() {
    605         // ICCID should be same across all the apps.
    606         for (UiccCardApplication app : mUiccApplications) {
    607             if (app != null) {
    608                 IccRecords ir = app.getIccRecords();
    609                 if (ir != null && ir.getIccId() != null) {
    610                     return ir.getIccId();
    611                 }
    612             }
    613         }
    614         return null;
    615     }
    616 
    617     private void log(String msg) {
    618         Rlog.d(LOG_TAG, msg);
    619     }
    620 
    621     private void loge(String msg) {
    622         Rlog.e(LOG_TAG, msg);
    623     }
    624 
    625     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
    626         pw.println("UiccCard:");
    627         pw.println(" mCi=" + mCi);
    628         pw.println(" mDestroyed=" + mDestroyed);
    629         pw.println(" mLastRadioState=" + mLastRadioState);
    630         pw.println(" mCatService=" + mCatService);
    631         pw.println(" mAbsentRegistrants: size=" + mAbsentRegistrants.size());
    632         for (int i = 0; i < mAbsentRegistrants.size(); i++) {
    633             pw.println("  mAbsentRegistrants[" + i + "]="
    634                     + ((Registrant)mAbsentRegistrants.get(i)).getHandler());
    635         }
    636         for (int i = 0; i < mCarrierPrivilegeRegistrants.size(); i++) {
    637             pw.println("  mCarrierPrivilegeRegistrants[" + i + "]="
    638                     + ((Registrant)mCarrierPrivilegeRegistrants.get(i)).getHandler());
    639         }
    640         pw.println(" mCardState=" + mCardState);
    641         pw.println(" mUniversalPinState=" + mUniversalPinState);
    642         pw.println(" mGsmUmtsSubscriptionAppIndex=" + mGsmUmtsSubscriptionAppIndex);
    643         pw.println(" mCdmaSubscriptionAppIndex=" + mCdmaSubscriptionAppIndex);
    644         pw.println(" mImsSubscriptionAppIndex=" + mImsSubscriptionAppIndex);
    645         pw.println(" mImsSubscriptionAppIndex=" + mImsSubscriptionAppIndex);
    646         pw.println(" mUiccApplications: length=" + mUiccApplications.length);
    647         for (int i = 0; i < mUiccApplications.length; i++) {
    648             if (mUiccApplications[i] == null) {
    649                 pw.println("  mUiccApplications[" + i + "]=" + null);
    650             } else {
    651                 pw.println("  mUiccApplications[" + i + "]="
    652                         + mUiccApplications[i].getType() + " " + mUiccApplications[i]);
    653             }
    654         }
    655         pw.println();
    656         // Print details of all applications
    657         for (UiccCardApplication app : mUiccApplications) {
    658             if (app != null) {
    659                 app.dump(fd, pw, args);
    660                 pw.println();
    661             }
    662         }
    663         // Print details of all IccRecords
    664         for (UiccCardApplication app : mUiccApplications) {
    665             if (app != null) {
    666                 IccRecords ir = app.getIccRecords();
    667                 if (ir != null) {
    668                     ir.dump(fd, pw, args);
    669                     pw.println();
    670                 }
    671             }
    672         }
    673         pw.flush();
    674     }
    675 }
    676