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