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