UiccCard.java revision 05b2e5d2900cc596edf5140321977f151eef7ea1
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 17package com.android.internal.telephony.uicc; 18 19import static android.Manifest.permission.READ_PHONE_STATE; 20import android.app.ActivityManagerNative; 21import android.app.AlertDialog; 22import android.content.Context; 23import android.content.DialogInterface; 24import android.content.Intent; 25import android.content.SharedPreferences; 26import android.content.pm.PackageManager; 27import android.content.pm.Signature; 28import android.content.res.Resources; 29import android.os.AsyncResult; 30import android.os.Handler; 31import android.os.Message; 32import android.os.PowerManager; 33import android.os.Registrant; 34import android.os.RegistrantList; 35import android.preference.PreferenceManager; 36import android.telephony.Rlog; 37import android.telephony.TelephonyManager; 38import android.text.TextUtils; 39import android.view.WindowManager; 40 41import com.android.internal.telephony.CommandsInterface; 42import com.android.internal.telephony.PhoneBase; 43import com.android.internal.telephony.CommandsInterface.RadioState; 44import com.android.internal.telephony.IccCardConstants.State; 45import com.android.internal.telephony.gsm.GSMPhone; 46import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType; 47import com.android.internal.telephony.uicc.IccCardStatus.CardState; 48import com.android.internal.telephony.uicc.IccCardStatus.PinState; 49import com.android.internal.telephony.cat.CatService; 50import com.android.internal.telephony.cdma.CDMALTEPhone; 51import com.android.internal.telephony.cdma.CDMAPhone; 52import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager; 53 54import android.os.SystemProperties; 55 56import com.android.internal.R; 57 58import java.io.FileDescriptor; 59import java.io.PrintWriter; 60import java.util.List; 61 62/** 63 * {@hide} 64 */ 65public 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 private 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 (mCarrierPrivilegeRules == null || 288 mCarrierPrivilegeRules.areCarrierPriviligeRulesLoaded()) { 289 r.notifyRegistrant(); 290 } 291 } 292 } 293 294 public void unregisterForCarrierPrivilegeRulesLoaded(Handler h) { 295 synchronized (mLock) { 296 mCarrierPrivilegeRegistrants.remove(h); 297 } 298 } 299 300 private void onIccSwap(boolean isAdded) { 301 302 boolean isHotSwapSupported = mContext.getResources().getBoolean( 303 com.android.internal.R.bool.config_hotswapCapable); 304 305 if (isHotSwapSupported) { 306 log("onIccSwap: isHotSwapSupported is true, don't prompt for rebooting"); 307 return; 308 } 309 log("onIccSwap: isHotSwapSupported is false, prompt for rebooting"); 310 311 synchronized (mLock) { 312 // TODO: Here we assume the device can't handle SIM hot-swap 313 // and has to reboot. We may want to add a property, 314 // e.g. REBOOT_ON_SIM_SWAP, to indicate if modem support 315 // hot-swap. 316 DialogInterface.OnClickListener listener = null; 317 318 319 // TODO: SimRecords is not reset while SIM ABSENT (only reset while 320 // Radio_off_or_not_available). Have to reset in both both 321 // added or removed situation. 322 listener = new DialogInterface.OnClickListener() { 323 @Override 324 public void onClick(DialogInterface dialog, int which) { 325 synchronized (mLock) { 326 if (which == DialogInterface.BUTTON_POSITIVE) { 327 if (DBG) log("Reboot due to SIM swap"); 328 PowerManager pm = (PowerManager) mContext 329 .getSystemService(Context.POWER_SERVICE); 330 pm.reboot("SIM is added."); 331 } 332 } 333 } 334 335 }; 336 337 Resources r = Resources.getSystem(); 338 339 String title = (isAdded) ? r.getString(R.string.sim_added_title) : 340 r.getString(R.string.sim_removed_title); 341 String message = (isAdded) ? r.getString(R.string.sim_added_message) : 342 r.getString(R.string.sim_removed_message); 343 String buttonTxt = r.getString(R.string.sim_restart_button); 344 345 AlertDialog dialog = new AlertDialog.Builder(mContext) 346 .setTitle(title) 347 .setMessage(message) 348 .setPositiveButton(buttonTxt, listener) 349 .create(); 350 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 351 dialog.show(); 352 } 353 } 354 355 protected Handler mHandler = new Handler() { 356 @Override 357 public void handleMessage(Message msg){ 358 if (mDestroyed) { 359 loge("Received message " + msg + "[" + msg.what 360 + "] while being destroyed. Ignoring."); 361 return; 362 } 363 364 switch (msg.what) { 365 case EVENT_CARD_REMOVED: 366 onIccSwap(false); 367 break; 368 case EVENT_CARD_ADDED: 369 onIccSwap(true); 370 break; 371 case EVENT_OPEN_LOGICAL_CHANNEL_DONE: 372 case EVENT_CLOSE_LOGICAL_CHANNEL_DONE: 373 case EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE: 374 case EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE: 375 case EVENT_SIM_IO_DONE: 376 AsyncResult ar = (AsyncResult)msg.obj; 377 if (ar.exception != null) { 378 if (DBG) 379 log("Error in SIM access with exception" + ar.exception); 380 } 381 AsyncResult.forMessage((Message)ar.userObj, ar.result, ar.exception); 382 ((Message)ar.userObj).sendToTarget(); 383 break; 384 case EVENT_CARRIER_PRIVILIGES_LOADED: 385 onCarrierPriviligesLoadedMessage(); 386 break; 387 default: 388 loge("Unknown Event " + msg.what); 389 } 390 } 391 }; 392 393 private void onCarrierPriviligesLoadedMessage() { 394 synchronized (mLock) { 395 mCarrierPrivilegeRegistrants.notifyRegistrants(); 396 } 397 } 398 399 public boolean isApplicationOnIcc(IccCardApplicationStatus.AppType type) { 400 synchronized (mLock) { 401 for (int i = 0 ; i < mUiccApplications.length; i++) { 402 if (mUiccApplications[i] != null && mUiccApplications[i].getType() == type) { 403 return true; 404 } 405 } 406 return false; 407 } 408 } 409 410 public CardState getCardState() { 411 synchronized (mLock) { 412 return mCardState; 413 } 414 } 415 416 public PinState getUniversalPinState() { 417 synchronized (mLock) { 418 return mUniversalPinState; 419 } 420 } 421 422 public UiccCardApplication getApplication(int family) { 423 synchronized (mLock) { 424 int index = IccCardStatus.CARD_MAX_APPS; 425 switch (family) { 426 case UiccController.APP_FAM_3GPP: 427 index = mGsmUmtsSubscriptionAppIndex; 428 break; 429 case UiccController.APP_FAM_3GPP2: 430 index = mCdmaSubscriptionAppIndex; 431 break; 432 case UiccController.APP_FAM_IMS: 433 index = mImsSubscriptionAppIndex; 434 break; 435 } 436 if (index >= 0 && index < mUiccApplications.length) { 437 return mUiccApplications[index]; 438 } 439 return null; 440 } 441 } 442 443 public UiccCardApplication getApplicationIndex(int index) { 444 synchronized (mLock) { 445 if (index >= 0 && index < mUiccApplications.length) { 446 return mUiccApplications[index]; 447 } 448 return null; 449 } 450 } 451 452 /** 453 * Returns the SIM application of the specified type. 454 * 455 * @param type ICC application type (@see com.android.internal.telephony.PhoneConstants#APPTYPE_xxx) 456 * @return application corresponding to type or a null if no match found 457 */ 458 public UiccCardApplication getApplicationByType(int type) { 459 synchronized (mLock) { 460 for (int i = 0 ; i < mUiccApplications.length; i++) { 461 if (mUiccApplications[i] != null && 462 mUiccApplications[i].getType().ordinal() == type) { 463 return mUiccApplications[i]; 464 } 465 } 466 return null; 467 } 468 } 469 470 /** 471 * Exposes {@link CommandsInterface.iccOpenLogicalChannel} 472 */ 473 public void iccOpenLogicalChannel(String AID, Message response) { 474 mCi.iccOpenLogicalChannel(AID, 475 mHandler.obtainMessage(EVENT_OPEN_LOGICAL_CHANNEL_DONE, response)); 476 } 477 478 /** 479 * Exposes {@link CommandsInterface.iccCloseLogicalChannel} 480 */ 481 public void iccCloseLogicalChannel(int channel, Message response) { 482 mCi.iccCloseLogicalChannel(channel, 483 mHandler.obtainMessage(EVENT_CLOSE_LOGICAL_CHANNEL_DONE, response)); 484 } 485 486 /** 487 * Exposes {@link CommandsInterface.iccTransmitApduLogicalChannel} 488 */ 489 public void iccTransmitApduLogicalChannel(int channel, int cla, int command, 490 int p1, int p2, int p3, String data, Message response) { 491 mCi.iccTransmitApduLogicalChannel(channel, cla, command, p1, p2, p3, 492 data, mHandler.obtainMessage(EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE, response)); 493 } 494 495 /** 496 * Exposes {@link CommandsInterface.iccTransmitApduBasicChannel} 497 */ 498 public void iccTransmitApduBasicChannel(int cla, int command, 499 int p1, int p2, int p3, String data, Message response) { 500 mCi.iccTransmitApduBasicChannel(cla, command, p1, p2, p3, 501 data, mHandler.obtainMessage(EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE, response)); 502 } 503 504 /** 505 * Exposes {@link CommandsInterface.iccIO} 506 */ 507 public void iccExchangeSimIO(int fileID, int command, int p1, int p2, int p3, 508 String pathID, Message response) { 509 mCi.iccIO(command, fileID, pathID, p1, p2, p3, null, null, 510 mHandler.obtainMessage(EVENT_SIM_IO_DONE, response)); 511 } 512 513 /** 514 * Exposes {@link CommandsInterface.sendEnvelopeWithStatus} 515 */ 516 public void sendEnvelopeWithStatus(String contents, Message response) { 517 mCi.sendEnvelopeWithStatus(contents, response); 518 } 519 520 /* Returns number of applications on this card */ 521 public int getNumApplications() { 522 int count = 0; 523 for (UiccCardApplication a : mUiccApplications) { 524 if (a != null) { 525 count++; 526 } 527 } 528 return count; 529 } 530 531 public int getSlotId() { 532 return mSlotId; 533 } 534 535 /** 536 * Exposes {@link UiccCarrierPrivilegeRules.getCarrierPrivilegeStatus}. 537 */ 538 public int getCarrierPrivilegeStatus(Signature signature, String packageName) { 539 return mCarrierPrivilegeRules == null ? 540 TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED : 541 mCarrierPrivilegeRules.getCarrierPrivilegeStatus(signature, packageName); 542 } 543 544 /** 545 * Exposes {@link UiccCarrierPrivilegeRules.getCarrierPrivilegeStatus}. 546 */ 547 public int getCarrierPrivilegeStatus(PackageManager packageManager, String packageName) { 548 return mCarrierPrivilegeRules == null ? 549 TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED : 550 mCarrierPrivilegeRules.getCarrierPrivilegeStatus(packageManager, packageName); 551 } 552 553 /** 554 * Exposes {@link UiccCarrierPrivilegeRules.getCarrierPrivilegeStatusForCurrentTransaction}. 555 */ 556 public int getCarrierPrivilegeStatusForCurrentTransaction(PackageManager packageManager) { 557 return mCarrierPrivilegeRules == null ? 558 TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED : 559 mCarrierPrivilegeRules.getCarrierPrivilegeStatusForCurrentTransaction(packageManager); 560 } 561 562 /** 563 * Exposes {@link UiccCarrierPrivilegeRules.getCarrierPackageNamesForIntent}. 564 */ 565 public List<String> getCarrierPackageNamesForIntent( 566 PackageManager packageManager, Intent intent) { 567 return mCarrierPrivilegeRules == null ? null : 568 mCarrierPrivilegeRules.getCarrierPackageNamesForIntent( 569 packageManager, intent); 570 } 571 572 public boolean setOperatorBrandOverride(String iccId, String brand) { 573 log("setOperatorBrandOverride: " + iccId + " : " + brand); 574 log("current iccId: " + getIccId()); 575 576 if (iccId.isEmpty() || !TextUtils.isDigitsOnly(iccId)) { 577 return false; 578 } 579 580 SharedPreferences.Editor spEditor = 581 PreferenceManager.getDefaultSharedPreferences(mContext).edit(); 582 String key = OPERATOR_BRAND_OVERRIDE_PREFIX + iccId; 583 if (brand == null) { 584 spEditor.remove(key).commit(); 585 } else { 586 spEditor.putString(key, brand).commit(); 587 } 588 return true; 589 } 590 591 public String getOperatorBrandOverride() { 592 String iccId = getIccId(); 593 if (iccId == null) { 594 return null; 595 } 596 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext); 597 return sp.getString(OPERATOR_BRAND_OVERRIDE_PREFIX + iccId, null); 598 } 599 600 private String getIccId() { 601 // ICCID should be same across all the apps. 602 for (UiccCardApplication app : mUiccApplications) { 603 if (app != null) { 604 IccRecords ir = app.getIccRecords(); 605 if (ir != null && ir.getIccId() != null) { 606 return ir.getIccId(); 607 } 608 } 609 } 610 return null; 611 } 612 613 private void log(String msg) { 614 Rlog.d(LOG_TAG, msg); 615 } 616 617 private void loge(String msg) { 618 Rlog.e(LOG_TAG, msg); 619 } 620 621 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 622 pw.println("UiccCard:"); 623 pw.println(" mCi=" + mCi); 624 pw.println(" mDestroyed=" + mDestroyed); 625 pw.println(" mLastRadioState=" + mLastRadioState); 626 pw.println(" mCatService=" + mCatService); 627 pw.println(" mAbsentRegistrants: size=" + mAbsentRegistrants.size()); 628 for (int i = 0; i < mAbsentRegistrants.size(); i++) { 629 pw.println(" mAbsentRegistrants[" + i + "]=" 630 + ((Registrant)mAbsentRegistrants.get(i)).getHandler()); 631 } 632 for (int i = 0; i < mCarrierPrivilegeRegistrants.size(); i++) { 633 pw.println(" mCarrierPrivilegeRegistrants[" + i + "]=" 634 + ((Registrant)mCarrierPrivilegeRegistrants.get(i)).getHandler()); 635 } 636 pw.println(" mCardState=" + mCardState); 637 pw.println(" mUniversalPinState=" + mUniversalPinState); 638 pw.println(" mGsmUmtsSubscriptionAppIndex=" + mGsmUmtsSubscriptionAppIndex); 639 pw.println(" mCdmaSubscriptionAppIndex=" + mCdmaSubscriptionAppIndex); 640 pw.println(" mImsSubscriptionAppIndex=" + mImsSubscriptionAppIndex); 641 pw.println(" mImsSubscriptionAppIndex=" + mImsSubscriptionAppIndex); 642 pw.println(" mUiccApplications: length=" + mUiccApplications.length); 643 for (int i = 0; i < mUiccApplications.length; i++) { 644 if (mUiccApplications[i] == null) { 645 pw.println(" mUiccApplications[" + i + "]=" + null); 646 } else { 647 pw.println(" mUiccApplications[" + i + "]=" 648 + mUiccApplications[i].getType() + " " + mUiccApplications[i]); 649 } 650 } 651 pw.println(); 652 // Print details of all applications 653 for (UiccCardApplication app : mUiccApplications) { 654 if (app != null) { 655 app.dump(fd, pw, args); 656 pw.println(); 657 } 658 } 659 // Print details of all IccRecords 660 for (UiccCardApplication app : mUiccApplications) { 661 if (app != null) { 662 IccRecords ir = app.getIccRecords(); 663 if (ir != null) { 664 ir.dump(fd, pw, args); 665 pw.println(); 666 } 667 } 668 } 669 pw.flush(); 670 } 671} 672