1 /* 2 * Copyright (C) 2006 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 android.content.Context; 20 import android.os.AsyncResult; 21 import android.os.Handler; 22 import android.os.Message; 23 import android.os.Registrant; 24 import android.os.RegistrantList; 25 26 import android.telephony.TelephonyManager; 27 import com.android.internal.telephony.CommandsInterface; 28 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppState; 29 30 import java.io.FileDescriptor; 31 import java.io.PrintWriter; 32 import java.util.concurrent.atomic.AtomicBoolean; 33 34 /** 35 * {@hide} 36 */ 37 public abstract class IccRecords extends Handler implements IccConstants { 38 protected static final boolean DBG = true; 39 40 // ***** Instance Variables 41 protected AtomicBoolean mDestroyed = new AtomicBoolean(false); 42 protected Context mContext; 43 protected CommandsInterface mCi; 44 protected IccFileHandler mFh; 45 protected UiccCardApplication mParentApp; 46 protected TelephonyManager mTelephonyManager; 47 48 protected RegistrantList mRecordsLoadedRegistrants = new RegistrantList(); 49 protected RegistrantList mImsiReadyRegistrants = new RegistrantList(); 50 protected RegistrantList mRecordsEventsRegistrants = new RegistrantList(); 51 protected RegistrantList mNewSmsRegistrants = new RegistrantList(); 52 protected RegistrantList mNetworkSelectionModeAutomaticRegistrants = new RegistrantList(); 53 54 protected int mRecordsToLoad; // number of pending load requests 55 56 protected AdnRecordCache mAdnCache; 57 58 // ***** Cached SIM State; cleared on channel close 59 60 protected boolean mRecordsRequested = false; // true if we've made requests for the sim records 61 62 protected String mIccId; 63 protected String mMsisdn = null; // My mobile number 64 protected String mMsisdnTag = null; 65 protected String mNewMsisdn = null; 66 protected String mNewMsisdnTag = null; 67 protected String mVoiceMailNum = null; 68 protected String mVoiceMailTag = null; 69 protected String mNewVoiceMailNum = null; 70 protected String mNewVoiceMailTag = null; 71 protected boolean mIsVoiceMailFixed = false; 72 protected String mImsi; 73 private IccIoResult auth_rsp; 74 75 protected int mMncLength = UNINITIALIZED; 76 protected int mMailboxIndex = 0; // 0 is no mailbox dailing number associated 77 78 private String mSpn; 79 80 protected String mGid1; 81 82 private final Object mLock = new Object(); 83 84 // ***** Constants 85 86 // Markers for mncLength 87 protected static final int UNINITIALIZED = -1; 88 protected static final int UNKNOWN = 0; 89 90 // Bitmasks for SPN display rules. 91 public static final int SPN_RULE_SHOW_SPN = 0x01; 92 public static final int SPN_RULE_SHOW_PLMN = 0x02; 93 94 // ***** Event Constants 95 protected static final int EVENT_SET_MSISDN_DONE = 30; 96 public static final int EVENT_MWI = 0; // Message Waiting indication 97 public static final int EVENT_CFI = 1; // Call Forwarding indication 98 public static final int EVENT_SPN = 2; // Service Provider Name 99 100 public static final int EVENT_GET_ICC_RECORD_DONE = 100; 101 protected static final int EVENT_APP_READY = 1; 102 private static final int EVENT_AKA_AUTHENTICATE_DONE = 90; 103 104 @Override toString()105 public String toString() { 106 return "mDestroyed=" + mDestroyed 107 + " mContext=" + mContext 108 + " mCi=" + mCi 109 + " mFh=" + mFh 110 + " mParentApp=" + mParentApp 111 + " recordsLoadedRegistrants=" + mRecordsLoadedRegistrants 112 + " mImsiReadyRegistrants=" + mImsiReadyRegistrants 113 + " mRecordsEventsRegistrants=" + mRecordsEventsRegistrants 114 + " mNewSmsRegistrants=" + mNewSmsRegistrants 115 + " mNetworkSelectionModeAutomaticRegistrants=" 116 + mNetworkSelectionModeAutomaticRegistrants 117 + " recordsToLoad=" + mRecordsToLoad 118 + " adnCache=" + mAdnCache 119 + " recordsRequested=" + mRecordsRequested 120 + " iccid=" + mIccId 121 + " msisdnTag=" + mMsisdnTag 122 + " voiceMailNum=" + mVoiceMailNum 123 + " voiceMailTag=" + mVoiceMailTag 124 + " newVoiceMailNum=" + mNewVoiceMailNum 125 + " newVoiceMailTag=" + mNewVoiceMailTag 126 + " isVoiceMailFixed=" + mIsVoiceMailFixed 127 + " mImsi=" + mImsi 128 + " mncLength=" + mMncLength 129 + " mailboxIndex=" + mMailboxIndex 130 + " spn=" + mSpn; 131 132 } 133 134 /** 135 * Generic ICC record loaded callback. Subclasses can call EF load methods on 136 * {@link IccFileHandler} passing a Message for onLoaded with the what field set to 137 * {@link #EVENT_GET_ICC_RECORD_DONE} and the obj field set to an instance 138 * of this interface. The {@link #handleMessage} method in this class will print a 139 * log message using {@link #getEfName()} and decrement {@link #mRecordsToLoad}. 140 * 141 * If the record load was successful, {@link #onRecordLoaded} will be called with the result. 142 * Otherwise, an error log message will be output by {@link #handleMessage} and 143 * {@link #onRecordLoaded} will not be called. 144 */ 145 public interface IccRecordLoaded { getEfName()146 String getEfName(); onRecordLoaded(AsyncResult ar)147 void onRecordLoaded(AsyncResult ar); 148 } 149 150 // ***** Constructor IccRecords(UiccCardApplication app, Context c, CommandsInterface ci)151 public IccRecords(UiccCardApplication app, Context c, CommandsInterface ci) { 152 mContext = c; 153 mCi = ci; 154 mFh = app.getIccFileHandler(); 155 mParentApp = app; 156 mTelephonyManager = (TelephonyManager) mContext.getSystemService( 157 Context.TELEPHONY_SERVICE); 158 } 159 160 /** 161 * Call when the IccRecords object is no longer going to be used. 162 */ dispose()163 public void dispose() { 164 mDestroyed.set(true); 165 mParentApp = null; 166 mFh = null; 167 mCi = null; 168 mContext = null; 169 } 170 onReady()171 public abstract void onReady(); 172 173 //***** Public Methods getAdnCache()174 public AdnRecordCache getAdnCache() { 175 return mAdnCache; 176 } 177 getIccId()178 public String getIccId() { 179 return mIccId; 180 } 181 registerForRecordsLoaded(Handler h, int what, Object obj)182 public void registerForRecordsLoaded(Handler h, int what, Object obj) { 183 if (mDestroyed.get()) { 184 return; 185 } 186 187 Registrant r = new Registrant(h, what, obj); 188 mRecordsLoadedRegistrants.add(r); 189 190 if (mRecordsToLoad == 0 && mRecordsRequested == true) { 191 r.notifyRegistrant(new AsyncResult(null, null, null)); 192 } 193 } unregisterForRecordsLoaded(Handler h)194 public void unregisterForRecordsLoaded(Handler h) { 195 mRecordsLoadedRegistrants.remove(h); 196 } 197 registerForImsiReady(Handler h, int what, Object obj)198 public void registerForImsiReady(Handler h, int what, Object obj) { 199 if (mDestroyed.get()) { 200 return; 201 } 202 203 Registrant r = new Registrant(h, what, obj); 204 mImsiReadyRegistrants.add(r); 205 206 if (mImsi != null) { 207 r.notifyRegistrant(new AsyncResult(null, null, null)); 208 } 209 } unregisterForImsiReady(Handler h)210 public void unregisterForImsiReady(Handler h) { 211 mImsiReadyRegistrants.remove(h); 212 } 213 registerForRecordsEvents(Handler h, int what, Object obj)214 public void registerForRecordsEvents(Handler h, int what, Object obj) { 215 Registrant r = new Registrant (h, what, obj); 216 mRecordsEventsRegistrants.add(r); 217 218 /* Notify registrant of all the possible events. This is to make sure registrant is 219 notified even if event occurred in the past. */ 220 r.notifyResult(EVENT_MWI); 221 r.notifyResult(EVENT_CFI); 222 } unregisterForRecordsEvents(Handler h)223 public void unregisterForRecordsEvents(Handler h) { 224 mRecordsEventsRegistrants.remove(h); 225 } 226 registerForNewSms(Handler h, int what, Object obj)227 public void registerForNewSms(Handler h, int what, Object obj) { 228 Registrant r = new Registrant (h, what, obj); 229 mNewSmsRegistrants.add(r); 230 } unregisterForNewSms(Handler h)231 public void unregisterForNewSms(Handler h) { 232 mNewSmsRegistrants.remove(h); 233 } 234 registerForNetworkSelectionModeAutomatic( Handler h, int what, Object obj)235 public void registerForNetworkSelectionModeAutomatic( 236 Handler h, int what, Object obj) { 237 Registrant r = new Registrant (h, what, obj); 238 mNetworkSelectionModeAutomaticRegistrants.add(r); 239 } unregisterForNetworkSelectionModeAutomatic(Handler h)240 public void unregisterForNetworkSelectionModeAutomatic(Handler h) { 241 mNetworkSelectionModeAutomaticRegistrants.remove(h); 242 } 243 244 /** 245 * Get the International Mobile Subscriber ID (IMSI) on a SIM 246 * for GSM, UMTS and like networks. Default is null if IMSI is 247 * not supported or unavailable. 248 * 249 * @return null if SIM is not yet ready or unavailable 250 */ getIMSI()251 public String getIMSI() { 252 return null; 253 } 254 255 /** 256 * Imsi could be set by ServiceStateTrackers in case of cdma 257 * @param imsi 258 */ setImsi(String imsi)259 public void setImsi(String imsi) { 260 mImsi = imsi; 261 mImsiReadyRegistrants.notifyRegistrants(); 262 } 263 264 /** 265 * Get the Network Access ID (NAI) on a CSIM for CDMA like networks. Default is null if IMSI is 266 * not supported or unavailable. 267 * 268 * @return null if NAI is not yet ready or unavailable 269 */ getNAI()270 public String getNAI() { 271 return null; 272 } 273 getMsisdnNumber()274 public String getMsisdnNumber() { 275 return mMsisdn; 276 } 277 278 /** 279 * Get the Group Identifier Level 1 (GID1) on a SIM for GSM. 280 * @return null if SIM is not yet ready 281 */ getGid1()282 public String getGid1() { 283 return null; 284 } 285 286 /** 287 * Set subscriber number to SIM record 288 * 289 * The subscriber number is stored in EF_MSISDN (TS 51.011) 290 * 291 * When the operation is complete, onComplete will be sent to its handler 292 * 293 * @param alphaTag alpha-tagging of the dailing nubmer (up to 10 characters) 294 * @param number dailing nubmer (up to 20 digits) 295 * if the number starts with '+', then set to international TOA 296 * @param onComplete 297 * onComplete.obj will be an AsyncResult 298 * ((AsyncResult)onComplete.obj).exception == null on success 299 * ((AsyncResult)onComplete.obj).exception != null on fail 300 */ setMsisdnNumber(String alphaTag, String number, Message onComplete)301 public void setMsisdnNumber(String alphaTag, String number, 302 Message onComplete) { 303 304 mMsisdn = number; 305 mMsisdnTag = alphaTag; 306 307 if (DBG) log("Set MSISDN: " + mMsisdnTag +" " + mMsisdn); 308 309 310 AdnRecord adn = new AdnRecord(mMsisdnTag, mMsisdn); 311 312 new AdnRecordLoader(mFh).updateEF(adn, EF_MSISDN, EF_EXT1, 1, null, 313 obtainMessage(EVENT_SET_MSISDN_DONE, onComplete)); 314 } 315 getMsisdnAlphaTag()316 public String getMsisdnAlphaTag() { 317 return mMsisdnTag; 318 } 319 getVoiceMailNumber()320 public String getVoiceMailNumber() { 321 return mVoiceMailNum; 322 } 323 324 /** 325 * Return Service Provider Name stored in SIM (EF_SPN=0x6F46) or in RUIM (EF_RUIM_SPN=0x6F41). 326 * 327 * @return null if SIM is not yet ready or no RUIM entry 328 */ getServiceProviderName()329 public String getServiceProviderName() { 330 String providerName = mSpn; 331 332 // Check for null pointers, mParentApp can be null after dispose, 333 // which did occur after removing a SIM. 334 UiccCardApplication parentApp = mParentApp; 335 if (parentApp != null) { 336 UiccCard card = parentApp.getUiccCard(); 337 if (card != null) { 338 String brandOverride = card.getOperatorBrandOverride(); 339 if (brandOverride != null) { 340 log("getServiceProviderName: override"); 341 providerName = brandOverride; 342 } else { 343 log("getServiceProviderName: no brandOverride"); 344 } 345 } else { 346 log("getServiceProviderName: card is null"); 347 } 348 } else { 349 log("getServiceProviderName: mParentApp is null"); 350 } 351 log("getServiceProviderName: providerName=" + providerName); 352 return providerName; 353 } 354 setServiceProviderName(String spn)355 protected void setServiceProviderName(String spn) { 356 mSpn = spn; 357 } 358 359 /** 360 * Set voice mail number to SIM record 361 * 362 * The voice mail number can be stored either in EF_MBDN (TS 51.011) or 363 * EF_MAILBOX_CPHS (CPHS 4.2) 364 * 365 * If EF_MBDN is available, store the voice mail number to EF_MBDN 366 * 367 * If EF_MAILBOX_CPHS is enabled, store the voice mail number to EF_CHPS 368 * 369 * So the voice mail number will be stored in both EFs if both are available 370 * 371 * Return error only if both EF_MBDN and EF_MAILBOX_CPHS fail. 372 * 373 * When the operation is complete, onComplete will be sent to its handler 374 * 375 * @param alphaTag alpha-tagging of the dailing nubmer (upto 10 characters) 376 * @param voiceNumber dailing nubmer (upto 20 digits) 377 * if the number is start with '+', then set to international TOA 378 * @param onComplete 379 * onComplete.obj will be an AsyncResult 380 * ((AsyncResult)onComplete.obj).exception == null on success 381 * ((AsyncResult)onComplete.obj).exception != null on fail 382 */ setVoiceMailNumber(String alphaTag, String voiceNumber, Message onComplete)383 public abstract void setVoiceMailNumber(String alphaTag, String voiceNumber, 384 Message onComplete); 385 getVoiceMailAlphaTag()386 public String getVoiceMailAlphaTag() { 387 return mVoiceMailTag; 388 } 389 390 /** 391 * Sets the SIM voice message waiting indicator records 392 * @param line GSM Subscriber Profile Number, one-based. Only '1' is supported 393 * @param countWaiting The number of messages waiting, if known. Use 394 * -1 to indicate that an unknown number of 395 * messages are waiting 396 */ setVoiceMessageWaiting(int line, int countWaiting)397 public abstract void setVoiceMessageWaiting(int line, int countWaiting); 398 399 /** 400 * Called by GsmPhone to update VoiceMail count 401 */ getVoiceMessageCount()402 public abstract int getVoiceMessageCount(); 403 404 /** 405 * Called by STK Service when REFRESH is received. 406 * @param fileChanged indicates whether any files changed 407 * @param fileList if non-null, a list of EF files that changed 408 */ onRefresh(boolean fileChanged, int[] fileList)409 public abstract void onRefresh(boolean fileChanged, int[] fileList); 410 411 /** 412 * Called by subclasses (SimRecords and RuimRecords) whenever 413 * IccRefreshResponse.REFRESH_RESULT_INIT event received 414 */ onIccRefreshInit()415 protected void onIccRefreshInit() { 416 mAdnCache.reset(); 417 UiccCardApplication parentApp = mParentApp; 418 if ((parentApp != null) && 419 (parentApp.getState() == AppState.APPSTATE_READY)) { 420 // This will cause files to be reread 421 sendMessage(obtainMessage(EVENT_APP_READY)); 422 } 423 } 424 getRecordsLoaded()425 public boolean getRecordsLoaded() { 426 if (mRecordsToLoad == 0 && mRecordsRequested == true) { 427 return true; 428 } else { 429 return false; 430 } 431 } 432 433 //***** Overridden from Handler 434 @Override handleMessage(Message msg)435 public void handleMessage(Message msg) { 436 AsyncResult ar; 437 438 switch (msg.what) { 439 case EVENT_GET_ICC_RECORD_DONE: 440 try { 441 ar = (AsyncResult) msg.obj; 442 IccRecordLoaded recordLoaded = (IccRecordLoaded) ar.userObj; 443 if (DBG) log(recordLoaded.getEfName() + " LOADED"); 444 445 if (ar.exception != null) { 446 loge("Record Load Exception: " + ar.exception); 447 } else { 448 recordLoaded.onRecordLoaded(ar); 449 } 450 }catch (RuntimeException exc) { 451 // I don't want these exceptions to be fatal 452 loge("Exception parsing SIM record: " + exc); 453 } finally { 454 // Count up record load responses even if they are fails 455 onRecordLoaded(); 456 } 457 break; 458 459 case EVENT_AKA_AUTHENTICATE_DONE: 460 ar = (AsyncResult)msg.obj; 461 auth_rsp = null; 462 if (DBG) log("EVENT_AKA_AUTHENTICATE_DONE"); 463 if (ar.exception != null) { 464 loge("Exception ICC SIM AKA: " + ar.exception); 465 } else { 466 try { 467 auth_rsp = (IccIoResult)ar.result; 468 if (DBG) log("ICC SIM AKA: auth_rsp = " + auth_rsp); 469 } catch (Exception e) { 470 loge("Failed to parse ICC SIM AKA contents: " + e); 471 } 472 } 473 synchronized (mLock) { 474 mLock.notifyAll(); 475 } 476 477 break; 478 479 default: 480 super.handleMessage(msg); 481 } 482 } 483 onRecordLoaded()484 protected abstract void onRecordLoaded(); 485 onAllRecordsLoaded()486 protected abstract void onAllRecordsLoaded(); 487 488 /** 489 * Returns the SpnDisplayRule based on settings on the SIM and the 490 * specified plmn (currently-registered PLMN). See TS 22.101 Annex A 491 * and TS 51.011 10.3.11 for details. 492 * 493 * If the SPN is not found on the SIM, the rule is always PLMN_ONLY. 494 * Generally used for GSM/UMTS and the like SIMs. 495 */ getDisplayRule(String plmn)496 public abstract int getDisplayRule(String plmn); 497 498 /** 499 * Return true if "Restriction of menu options for manual PLMN selection" 500 * bit is set or EF_CSP data is unavailable, return false otherwise. 501 * Generally used for GSM/UMTS and the like SIMs. 502 */ isCspPlmnEnabled()503 public boolean isCspPlmnEnabled() { 504 return false; 505 } 506 507 /** 508 * Returns the 5 or 6 digit MCC/MNC of the operator that 509 * provided the SIM card. Returns null of SIM is not yet ready 510 * or is not valid for the type of IccCard. Generally used for 511 * GSM/UMTS and the like SIMS 512 */ getOperatorNumeric()513 public String getOperatorNumeric() { 514 return null; 515 } 516 517 /** 518 * Get the current Voice call forwarding flag for GSM/UMTS and the like SIMs 519 * 520 * @return true if enabled 521 */ getVoiceCallForwardingFlag()522 public boolean getVoiceCallForwardingFlag() { 523 return false; 524 } 525 526 /** 527 * Set the voice call forwarding flag for GSM/UMTS and the like SIMs 528 * 529 * @param line to enable/disable 530 * @param enable 531 * @param number to which CFU is enabled 532 */ setVoiceCallForwardingFlag(int line, boolean enable, String number)533 public void setVoiceCallForwardingFlag(int line, boolean enable, String number) { 534 } 535 536 /** 537 * Indicates wether SIM is in provisioned state or not. 538 * Overridden only if SIM can be dynamically provisioned via OTA. 539 * 540 * @return true if provisioned 541 */ isProvisioned()542 public boolean isProvisioned () { 543 return true; 544 } 545 546 /** 547 * Write string to log file 548 * 549 * @param s is the string to write 550 */ log(String s)551 protected abstract void log(String s); 552 553 /** 554 * Write error string to log file. 555 * 556 * @param s is the string to write 557 */ loge(String s)558 protected abstract void loge(String s); 559 560 /** 561 * Return an interface to retrieve the ISIM records for IMS, if available. 562 * @return the interface to retrieve the ISIM records, or null if not supported 563 */ getIsimRecords()564 public IsimRecords getIsimRecords() { 565 return null; 566 } 567 getUsimServiceTable()568 public UsimServiceTable getUsimServiceTable() { 569 return null; 570 } 571 setSystemProperty(String key, String val)572 protected void setSystemProperty(String key, String val) { 573 TelephonyManager.getDefault().setTelephonyProperty(mParentApp.getPhoneId(), key, val); 574 575 log("[key, value]=" + key + ", " + val); 576 } 577 578 /** 579 * Returns the response of the SIM application on the UICC to authentication 580 * challenge/response algorithm. The data string and challenge response are 581 * Base64 encoded Strings. 582 * Can support EAP-SIM, EAP-AKA with results encoded per 3GPP TS 31.102. 583 * 584 * @param authContext parameter P2 that specifies the authentication context per 3GPP TS 31.102 (Section 7.1.2) 585 * @param data authentication challenge data 586 * @return challenge response 587 */ getIccSimChallengeResponse(int authContext, String data)588 public String getIccSimChallengeResponse(int authContext, String data) { 589 if (DBG) log("getIccSimChallengeResponse:"); 590 591 try { 592 synchronized(mLock) { 593 CommandsInterface ci = mCi; 594 UiccCardApplication parentApp = mParentApp; 595 if (ci != null && parentApp != null) { 596 ci.requestIccSimAuthentication(authContext, data, 597 parentApp.getAid(), 598 obtainMessage(EVENT_AKA_AUTHENTICATE_DONE)); 599 try { 600 mLock.wait(); 601 } catch (InterruptedException e) { 602 loge("getIccSimChallengeResponse: Fail, interrupted" 603 + " while trying to request Icc Sim Auth"); 604 return null; 605 } 606 } else { 607 loge( "getIccSimChallengeResponse: " 608 + "Fail, ci or parentApp is null"); 609 return null; 610 } 611 } 612 } catch(Exception e) { 613 loge( "getIccSimChallengeResponse: " 614 + "Fail while trying to request Icc Sim Auth"); 615 return null; 616 } 617 618 if (DBG) log("getIccSimChallengeResponse: return auth_rsp"); 619 620 return android.util.Base64.encodeToString(auth_rsp.payload, android.util.Base64.NO_WRAP); 621 } 622 dump(FileDescriptor fd, PrintWriter pw, String[] args)623 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 624 pw.println("IccRecords: " + this); 625 pw.println(" mDestroyed=" + mDestroyed); 626 pw.println(" mCi=" + mCi); 627 pw.println(" mFh=" + mFh); 628 pw.println(" mParentApp=" + mParentApp); 629 pw.println(" recordsLoadedRegistrants: size=" + mRecordsLoadedRegistrants.size()); 630 for (int i = 0; i < mRecordsLoadedRegistrants.size(); i++) { 631 pw.println(" recordsLoadedRegistrants[" + i + "]=" 632 + ((Registrant)mRecordsLoadedRegistrants.get(i)).getHandler()); 633 } 634 pw.println(" mImsiReadyRegistrants: size=" + mImsiReadyRegistrants.size()); 635 for (int i = 0; i < mImsiReadyRegistrants.size(); i++) { 636 pw.println(" mImsiReadyRegistrants[" + i + "]=" 637 + ((Registrant)mImsiReadyRegistrants.get(i)).getHandler()); 638 } 639 pw.println(" mRecordsEventsRegistrants: size=" + mRecordsEventsRegistrants.size()); 640 for (int i = 0; i < mRecordsEventsRegistrants.size(); i++) { 641 pw.println(" mRecordsEventsRegistrants[" + i + "]=" 642 + ((Registrant)mRecordsEventsRegistrants.get(i)).getHandler()); 643 } 644 pw.println(" mNewSmsRegistrants: size=" + mNewSmsRegistrants.size()); 645 for (int i = 0; i < mNewSmsRegistrants.size(); i++) { 646 pw.println(" mNewSmsRegistrants[" + i + "]=" 647 + ((Registrant)mNewSmsRegistrants.get(i)).getHandler()); 648 } 649 pw.println(" mNetworkSelectionModeAutomaticRegistrants: size=" 650 + mNetworkSelectionModeAutomaticRegistrants.size()); 651 for (int i = 0; i < mNetworkSelectionModeAutomaticRegistrants.size(); i++) { 652 pw.println(" mNetworkSelectionModeAutomaticRegistrants[" + i + "]=" 653 + ((Registrant)mNetworkSelectionModeAutomaticRegistrants.get(i)).getHandler()); 654 } 655 pw.println(" mRecordsRequested=" + mRecordsRequested); 656 pw.println(" mRecordsToLoad=" + mRecordsToLoad); 657 pw.println(" mRdnCache=" + mAdnCache); 658 pw.println(" iccid=" + mIccId); 659 pw.println(" mMsisdn=" + mMsisdn); 660 pw.println(" mMsisdnTag=" + mMsisdnTag); 661 pw.println(" mVoiceMailNum=" + mVoiceMailNum); 662 pw.println(" mVoiceMailTag=" + mVoiceMailTag); 663 pw.println(" mNewVoiceMailNum=" + mNewVoiceMailNum); 664 pw.println(" mNewVoiceMailTag=" + mNewVoiceMailTag); 665 pw.println(" mIsVoiceMailFixed=" + mIsVoiceMailFixed); 666 pw.println(" mImsi=" + mImsi); 667 pw.println(" mMncLength=" + mMncLength); 668 pw.println(" mMailboxIndex=" + mMailboxIndex); 669 pw.println(" mSpn=" + mSpn); 670 pw.flush(); 671 } 672 } 673