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.Binder;
     31 import android.os.Handler;
     32 import android.os.Message;
     33 import android.os.PowerManager;
     34 import android.os.Registrant;
     35 import android.os.RegistrantList;
     36 import android.preference.PreferenceManager;
     37 import android.telephony.Rlog;
     38 import android.telephony.TelephonyManager;
     39 import android.text.TextUtils;
     40 import android.util.LocalLog;
     41 import android.view.WindowManager;
     42 
     43 import com.android.internal.telephony.CommandsInterface;
     44 import com.android.internal.telephony.PhoneBase;
     45 import com.android.internal.telephony.CommandsInterface.RadioState;
     46 import com.android.internal.telephony.IccCardConstants.State;
     47 import com.android.internal.telephony.gsm.GSMPhone;
     48 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
     49 import com.android.internal.telephony.uicc.IccCardStatus.CardState;
     50 import com.android.internal.telephony.uicc.IccCardStatus.PinState;
     51 import com.android.internal.telephony.cat.CatService;
     52 import com.android.internal.telephony.cdma.CDMALTEPhone;
     53 import com.android.internal.telephony.cdma.CDMAPhone;
     54 import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager;
     55 
     56 import android.os.SystemProperties;
     57 
     58 import com.android.internal.R;
     59 
     60 import java.io.FileDescriptor;
     61 import java.io.PrintWriter;
     62 import java.util.List;
     63 
     64 /**
     65  * {@hide}
     66  */
     67 public class UiccCard {
     68     protected static final String LOG_TAG = "UiccCard";
     69     protected static final boolean DBG = true;
     70 
     71     private static final String OPERATOR_BRAND_OVERRIDE_PREFIX = "operator_branding_";
     72 
     73     private final Object mLock = new Object();
     74     private CardState mCardState;
     75     private PinState mUniversalPinState;
     76     private int mGsmUmtsSubscriptionAppIndex;
     77     private int mCdmaSubscriptionAppIndex;
     78     private int mImsSubscriptionAppIndex;
     79     private UiccCardApplication[] mUiccApplications =
     80             new UiccCardApplication[IccCardStatus.CARD_MAX_APPS];
     81     private Context mContext;
     82     private CommandsInterface mCi;
     83     private CatService mCatService;
     84     private RadioState mLastRadioState =  RadioState.RADIO_UNAVAILABLE;
     85     private UiccCarrierPrivilegeRules mCarrierPrivilegeRules;
     86 
     87     private RegistrantList mAbsentRegistrants = new RegistrantList();
     88     private RegistrantList mCarrierPrivilegeRegistrants = new RegistrantList();
     89 
     90     private static final int EVENT_CARD_REMOVED = 13;
     91     private static final int EVENT_CARD_ADDED = 14;
     92     private static final int EVENT_OPEN_LOGICAL_CHANNEL_DONE = 15;
     93     private static final int EVENT_CLOSE_LOGICAL_CHANNEL_DONE = 16;
     94     private static final int EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE = 17;
     95     private static final int EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE = 18;
     96     private static final int EVENT_SIM_IO_DONE = 19;
     97     private static final int EVENT_CARRIER_PRIVILIGES_LOADED = 20;
     98 
     99     private static final LocalLog mLocalLog = new LocalLog(100);
    100 
    101     private int mPhoneId;
    102 
    103     public UiccCard(Context c, CommandsInterface ci, IccCardStatus ics) {
    104         if (DBG) log("Creating");
    105         mCardState = ics.mCardState;
    106         update(c, ci, ics);
    107     }
    108 
    109     public UiccCard(Context c, CommandsInterface ci, IccCardStatus ics, int phoneId) {
    110         mCardState = ics.mCardState;
    111         mPhoneId = phoneId;
    112         update(c, ci, ics);
    113     }
    114 
    115     protected UiccCard() {
    116     }
    117 
    118     public void dispose() {
    119         synchronized (mLock) {
    120             if (DBG) log("Disposing card");
    121             if (mCatService != null) mCatService.dispose();
    122             for (UiccCardApplication app : mUiccApplications) {
    123                 if (app != null) {
    124                     app.dispose();
    125                 }
    126             }
    127             mCatService = null;
    128             mUiccApplications = null;
    129             mCarrierPrivilegeRules = null;
    130         }
    131     }
    132 
    133     public void update(Context c, CommandsInterface ci, IccCardStatus ics) {
    134         synchronized (mLock) {
    135             CardState oldState = mCardState;
    136             mCardState = ics.mCardState;
    137             mUniversalPinState = ics.mUniversalPinState;
    138             mGsmUmtsSubscriptionAppIndex = ics.mGsmUmtsSubscriptionAppIndex;
    139             mCdmaSubscriptionAppIndex = ics.mCdmaSubscriptionAppIndex;
    140             mImsSubscriptionAppIndex = ics.mImsSubscriptionAppIndex;
    141             mContext = c;
    142             mCi = ci;
    143 
    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, mPhoneId);
    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             switch (msg.what) {
    358                 case EVENT_CARD_REMOVED:
    359                     onIccSwap(false);
    360                     break;
    361                 case EVENT_CARD_ADDED:
    362                     onIccSwap(true);
    363                     break;
    364                 case EVENT_OPEN_LOGICAL_CHANNEL_DONE:
    365                 case EVENT_CLOSE_LOGICAL_CHANNEL_DONE:
    366                 case EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE:
    367                 case EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE:
    368                 case EVENT_SIM_IO_DONE:
    369                     AsyncResult ar = (AsyncResult)msg.obj;
    370                     if (ar.exception != null) {
    371                         loglocal("Exception: " + ar.exception);
    372                         log("Error in SIM access with exception" + ar.exception);
    373                     }
    374                     AsyncResult.forMessage((Message)ar.userObj, ar.result, ar.exception);
    375                     ((Message)ar.userObj).sendToTarget();
    376                     break;
    377                 case EVENT_CARRIER_PRIVILIGES_LOADED:
    378                     onCarrierPriviligesLoadedMessage();
    379                     break;
    380                 default:
    381                     loge("Unknown Event " + msg.what);
    382             }
    383         }
    384     };
    385 
    386     private void onCarrierPriviligesLoadedMessage() {
    387         synchronized (mLock) {
    388             mCarrierPrivilegeRegistrants.notifyRegistrants();
    389         }
    390     }
    391 
    392     public boolean isApplicationOnIcc(IccCardApplicationStatus.AppType type) {
    393         synchronized (mLock) {
    394             for (int i = 0 ; i < mUiccApplications.length; i++) {
    395                 if (mUiccApplications[i] != null && mUiccApplications[i].getType() == type) {
    396                     return true;
    397                 }
    398             }
    399             return false;
    400         }
    401     }
    402 
    403     public CardState getCardState() {
    404         synchronized (mLock) {
    405             return mCardState;
    406         }
    407     }
    408 
    409     public PinState getUniversalPinState() {
    410         synchronized (mLock) {
    411             return mUniversalPinState;
    412         }
    413     }
    414 
    415     public UiccCardApplication getApplication(int family) {
    416         synchronized (mLock) {
    417             int index = IccCardStatus.CARD_MAX_APPS;
    418             switch (family) {
    419                 case UiccController.APP_FAM_3GPP:
    420                     index = mGsmUmtsSubscriptionAppIndex;
    421                     break;
    422                 case UiccController.APP_FAM_3GPP2:
    423                     index = mCdmaSubscriptionAppIndex;
    424                     break;
    425                 case UiccController.APP_FAM_IMS:
    426                     index = mImsSubscriptionAppIndex;
    427                     break;
    428             }
    429             if (index >= 0 && index < mUiccApplications.length) {
    430                 return mUiccApplications[index];
    431             }
    432             return null;
    433         }
    434     }
    435 
    436     public UiccCardApplication getApplicationIndex(int index) {
    437         synchronized (mLock) {
    438             if (index >= 0 && index < mUiccApplications.length) {
    439                 return mUiccApplications[index];
    440             }
    441             return null;
    442         }
    443     }
    444 
    445     /**
    446      * Returns the SIM application of the specified type.
    447      *
    448      * @param type ICC application type (@see com.android.internal.telephony.PhoneConstants#APPTYPE_xxx)
    449      * @return application corresponding to type or a null if no match found
    450      */
    451     public UiccCardApplication getApplicationByType(int type) {
    452         synchronized (mLock) {
    453             for (int i = 0 ; i < mUiccApplications.length; i++) {
    454                 if (mUiccApplications[i] != null &&
    455                         mUiccApplications[i].getType().ordinal() == type) {
    456                     return mUiccApplications[i];
    457                 }
    458             }
    459             return null;
    460         }
    461     }
    462 
    463     /**
    464      * Resets the application with the input AID. Returns true if any changes were made.
    465      *
    466      * A null aid implies a card level reset - all applications must be reset.
    467      */
    468     public boolean resetAppWithAid(String aid) {
    469         synchronized (mLock) {
    470             boolean changed = false;
    471             for (int i = 0; i < mUiccApplications.length; i++) {
    472                 if (mUiccApplications[i] != null &&
    473                     (aid == null || aid.equals(mUiccApplications[i].getAid()))) {
    474                     // Delete removed applications
    475                     mUiccApplications[i].dispose();
    476                     mUiccApplications[i] = null;
    477                     changed = true;
    478                 }
    479             }
    480             return changed;
    481         }
    482         // TODO: For a card level notification, we should delete the CarrierPrivilegeRules and the
    483         // CAT service.
    484     }
    485 
    486     /**
    487      * Exposes {@link CommandsInterface.iccOpenLogicalChannel}
    488      */
    489     public void iccOpenLogicalChannel(String AID, Message response) {
    490         loglocal("Open Logical Channel: " + AID + " by pid:" + Binder.getCallingPid()
    491                 + " uid:" + Binder.getCallingUid());
    492         mCi.iccOpenLogicalChannel(AID,
    493                 mHandler.obtainMessage(EVENT_OPEN_LOGICAL_CHANNEL_DONE, response));
    494     }
    495 
    496     /**
    497      * Exposes {@link CommandsInterface.iccCloseLogicalChannel}
    498      */
    499     public void iccCloseLogicalChannel(int channel, Message response) {
    500         loglocal("Close Logical Channel: " + channel);
    501         mCi.iccCloseLogicalChannel(channel,
    502                 mHandler.obtainMessage(EVENT_CLOSE_LOGICAL_CHANNEL_DONE, response));
    503     }
    504 
    505     /**
    506      * Exposes {@link CommandsInterface.iccTransmitApduLogicalChannel}
    507      */
    508     public void iccTransmitApduLogicalChannel(int channel, int cla, int command,
    509             int p1, int p2, int p3, String data, Message response) {
    510         mCi.iccTransmitApduLogicalChannel(channel, cla, command, p1, p2, p3,
    511                 data, mHandler.obtainMessage(EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE, response));
    512     }
    513 
    514     /**
    515      * Exposes {@link CommandsInterface.iccTransmitApduBasicChannel}
    516      */
    517     public void iccTransmitApduBasicChannel(int cla, int command,
    518             int p1, int p2, int p3, String data, Message response) {
    519         mCi.iccTransmitApduBasicChannel(cla, command, p1, p2, p3,
    520                 data, mHandler.obtainMessage(EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE, response));
    521     }
    522 
    523     /**
    524      * Exposes {@link CommandsInterface.iccIO}
    525      */
    526     public void iccExchangeSimIO(int fileID, int command, int p1, int p2, int p3,
    527             String pathID, Message response) {
    528         mCi.iccIO(command, fileID, pathID, p1, p2, p3, null, null,
    529                 mHandler.obtainMessage(EVENT_SIM_IO_DONE, response));
    530     }
    531 
    532     /**
    533      * Exposes {@link CommandsInterface.sendEnvelopeWithStatus}
    534      */
    535     public void sendEnvelopeWithStatus(String contents, Message response) {
    536         mCi.sendEnvelopeWithStatus(contents, response);
    537     }
    538 
    539     /* Returns number of applications on this card */
    540     public int getNumApplications() {
    541         int count = 0;
    542         for (UiccCardApplication a : mUiccApplications) {
    543             if (a != null) {
    544                 count++;
    545             }
    546         }
    547         return count;
    548     }
    549 
    550     public int getPhoneId() {
    551         return mPhoneId;
    552     }
    553 
    554     /**
    555      * Returns true iff carrier priveleges rules are null (dont need to be loaded) or loaded.
    556      */
    557     public boolean areCarrierPriviligeRulesLoaded() {
    558         return mCarrierPrivilegeRules == null
    559             || mCarrierPrivilegeRules.areCarrierPriviligeRulesLoaded();
    560     }
    561 
    562     /**
    563      * Exposes {@link UiccCarrierPrivilegeRules.getCarrierPrivilegeStatus}.
    564      */
    565     public int getCarrierPrivilegeStatus(Signature signature, String packageName) {
    566         return mCarrierPrivilegeRules == null ?
    567             TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED :
    568             mCarrierPrivilegeRules.getCarrierPrivilegeStatus(signature, packageName);
    569     }
    570 
    571     /**
    572      * Exposes {@link UiccCarrierPrivilegeRules.getCarrierPrivilegeStatus}.
    573      */
    574     public int getCarrierPrivilegeStatus(PackageManager packageManager, String packageName) {
    575         return mCarrierPrivilegeRules == null ?
    576             TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED :
    577             mCarrierPrivilegeRules.getCarrierPrivilegeStatus(packageManager, packageName);
    578     }
    579 
    580     /**
    581      * Exposes {@link UiccCarrierPrivilegeRules.getCarrierPrivilegeStatusForCurrentTransaction}.
    582      */
    583     public int getCarrierPrivilegeStatusForCurrentTransaction(PackageManager packageManager) {
    584         return mCarrierPrivilegeRules == null ?
    585             TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED :
    586             mCarrierPrivilegeRules.getCarrierPrivilegeStatusForCurrentTransaction(packageManager);
    587     }
    588 
    589     /**
    590      * Exposes {@link UiccCarrierPrivilegeRules.getCarrierPackageNamesForIntent}.
    591      */
    592     public List<String> getCarrierPackageNamesForIntent(
    593             PackageManager packageManager, Intent intent) {
    594         return mCarrierPrivilegeRules == null ? null :
    595             mCarrierPrivilegeRules.getCarrierPackageNamesForIntent(
    596                     packageManager, intent);
    597     }
    598 
    599     public boolean setOperatorBrandOverride(String brand) {
    600         log("setOperatorBrandOverride: " + brand);
    601         log("current iccId: " + getIccId());
    602 
    603         String iccId = getIccId();
    604         if (TextUtils.isEmpty(iccId)) {
    605             return false;
    606         }
    607 
    608         SharedPreferences.Editor spEditor =
    609                 PreferenceManager.getDefaultSharedPreferences(mContext).edit();
    610         String key = OPERATOR_BRAND_OVERRIDE_PREFIX + iccId;
    611         if (brand == null) {
    612             spEditor.remove(key).commit();
    613         } else {
    614             spEditor.putString(key, brand).commit();
    615         }
    616         return true;
    617     }
    618 
    619     public String getOperatorBrandOverride() {
    620         String iccId = getIccId();
    621         if (TextUtils.isEmpty(iccId)) {
    622             return null;
    623         }
    624         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
    625         return sp.getString(OPERATOR_BRAND_OVERRIDE_PREFIX + iccId, null);
    626     }
    627 
    628     public String getIccId() {
    629         // ICCID should be same across all the apps.
    630         for (UiccCardApplication app : mUiccApplications) {
    631             if (app != null) {
    632                 IccRecords ir = app.getIccRecords();
    633                 if (ir != null && ir.getIccId() != null) {
    634                     return ir.getIccId();
    635                 }
    636             }
    637         }
    638         return null;
    639     }
    640 
    641     private void log(String msg) {
    642         Rlog.d(LOG_TAG, msg);
    643     }
    644 
    645     private void loge(String msg) {
    646         Rlog.e(LOG_TAG, msg);
    647     }
    648 
    649     private void loglocal(String msg) {
    650         if (DBG) mLocalLog.log(msg);
    651     }
    652 
    653     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
    654         pw.println("UiccCard:");
    655         pw.println(" mCi=" + mCi);
    656         pw.println(" mLastRadioState=" + mLastRadioState);
    657         pw.println(" mCatService=" + mCatService);
    658         pw.println(" mAbsentRegistrants: size=" + mAbsentRegistrants.size());
    659         for (int i = 0; i < mAbsentRegistrants.size(); i++) {
    660             pw.println("  mAbsentRegistrants[" + i + "]="
    661                     + ((Registrant)mAbsentRegistrants.get(i)).getHandler());
    662         }
    663         for (int i = 0; i < mCarrierPrivilegeRegistrants.size(); i++) {
    664             pw.println("  mCarrierPrivilegeRegistrants[" + i + "]="
    665                     + ((Registrant)mCarrierPrivilegeRegistrants.get(i)).getHandler());
    666         }
    667         pw.println(" mCardState=" + mCardState);
    668         pw.println(" mUniversalPinState=" + mUniversalPinState);
    669         pw.println(" mGsmUmtsSubscriptionAppIndex=" + mGsmUmtsSubscriptionAppIndex);
    670         pw.println(" mCdmaSubscriptionAppIndex=" + mCdmaSubscriptionAppIndex);
    671         pw.println(" mImsSubscriptionAppIndex=" + mImsSubscriptionAppIndex);
    672         pw.println(" mImsSubscriptionAppIndex=" + mImsSubscriptionAppIndex);
    673         pw.println(" mUiccApplications: length=" + mUiccApplications.length);
    674         for (int i = 0; i < mUiccApplications.length; i++) {
    675             if (mUiccApplications[i] == null) {
    676                 pw.println("  mUiccApplications[" + i + "]=" + null);
    677             } else {
    678                 pw.println("  mUiccApplications[" + i + "]="
    679                         + mUiccApplications[i].getType() + " " + mUiccApplications[i]);
    680             }
    681         }
    682         pw.println();
    683         // Print details of all applications
    684         for (UiccCardApplication app : mUiccApplications) {
    685             if (app != null) {
    686                 app.dump(fd, pw, args);
    687                 pw.println();
    688             }
    689         }
    690         // Print details of all IccRecords
    691         for (UiccCardApplication app : mUiccApplications) {
    692             if (app != null) {
    693                 IccRecords ir = app.getIccRecords();
    694                 if (ir != null) {
    695                     ir.dump(fd, pw, args);
    696                     pw.println();
    697                 }
    698             }
    699         }
    700         // Print UiccCarrierPrivilegeRules and registrants.
    701         if (mCarrierPrivilegeRules == null) {
    702             pw.println(" mCarrierPrivilegeRules: null");
    703         } else {
    704             pw.println(" mCarrierPrivilegeRules: " + mCarrierPrivilegeRules);
    705             mCarrierPrivilegeRules.dump(fd, pw, args);
    706         }
    707         pw.println(" mCarrierPrivilegeRegistrants: size=" + mCarrierPrivilegeRegistrants.size());
    708         for (int i = 0; i < mCarrierPrivilegeRegistrants.size(); i++) {
    709             pw.println("  mCarrierPrivilegeRegistrants[" + i + "]="
    710                     + ((Registrant)mCarrierPrivilegeRegistrants.get(i)).getHandler());
    711         }
    712         pw.flush();
    713         pw.println("mLocalLog:");
    714         mLocalLog.dump(fd, pw, args);
    715         pw.flush();
    716     }
    717 }
    718