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