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.annotation.IntDef; 20 import android.annotation.UnsupportedAppUsage; 21 import android.content.Context; 22 import android.os.AsyncResult; 23 import android.os.Handler; 24 import android.os.Message; 25 import android.os.Registrant; 26 import android.os.RegistrantList; 27 import android.telephony.Rlog; 28 import android.telephony.SubscriptionInfo; 29 import android.telephony.TelephonyManager; 30 import android.text.TextUtils; 31 32 import com.android.internal.telephony.CommandsInterface; 33 import com.android.internal.telephony.MccTable; 34 import com.android.internal.util.ArrayUtils; 35 36 import java.io.FileDescriptor; 37 import java.io.PrintWriter; 38 import java.io.UnsupportedEncodingException; 39 import java.lang.annotation.Retention; 40 import java.lang.annotation.RetentionPolicy; 41 import java.util.Arrays; 42 import java.util.HashMap; 43 import java.util.Objects; 44 import java.util.concurrent.atomic.AtomicBoolean; 45 import java.util.concurrent.atomic.AtomicInteger; 46 47 /** 48 * {@hide} 49 */ 50 public abstract class IccRecords extends Handler implements IccConstants { 51 protected static final boolean DBG = true; 52 protected static final boolean VDBG = false; // STOPSHIP if true 53 54 // Lookup table for carriers known to produce SIMs which incorrectly indicate MNC length. 55 private static final String[] MCCMNC_CODES_HAVING_3DIGITS_MNC = { 56 "302370", "302720", "310260", 57 "405025", "405026", "405027", "405028", "405029", "405030", "405031", "405032", 58 "405033", "405034", "405035", "405036", "405037", "405038", "405039", "405040", 59 "405041", "405042", "405043", "405044", "405045", "405046", "405047", "405750", 60 "405751", "405752", "405753", "405754", "405755", "405756", "405799", "405800", 61 "405801", "405802", "405803", "405804", "405805", "405806", "405807", "405808", 62 "405809", "405810", "405811", "405812", "405813", "405814", "405815", "405816", 63 "405817", "405818", "405819", "405820", "405821", "405822", "405823", "405824", 64 "405825", "405826", "405827", "405828", "405829", "405830", "405831", "405832", 65 "405833", "405834", "405835", "405836", "405837", "405838", "405839", "405840", 66 "405841", "405842", "405843", "405844", "405845", "405846", "405847", "405848", 67 "405849", "405850", "405851", "405852", "405853", "405854", "405855", "405856", 68 "405857", "405858", "405859", "405860", "405861", "405862", "405863", "405864", 69 "405865", "405866", "405867", "405868", "405869", "405870", "405871", "405872", 70 "405873", "405874", "405875", "405876", "405877", "405878", "405879", "405880", 71 "405881", "405882", "405883", "405884", "405885", "405886", "405908", "405909", 72 "405910", "405911", "405912", "405913", "405914", "405915", "405916", "405917", 73 "405918", "405919", "405920", "405921", "405922", "405923", "405924", "405925", 74 "405926", "405927", "405928", "405929", "405930", "405931", "405932", "502142", 75 "502143", "502145", "502146", "502147", "502148" 76 }; 77 78 // ***** Instance Variables 79 @UnsupportedAppUsage 80 protected AtomicBoolean mDestroyed = new AtomicBoolean(false); 81 protected AtomicBoolean mLoaded = new AtomicBoolean(false); 82 @UnsupportedAppUsage 83 protected Context mContext; 84 @UnsupportedAppUsage 85 protected CommandsInterface mCi; 86 @UnsupportedAppUsage 87 protected IccFileHandler mFh; 88 @UnsupportedAppUsage 89 protected UiccCardApplication mParentApp; 90 @UnsupportedAppUsage 91 protected TelephonyManager mTelephonyManager; 92 93 protected RegistrantList mRecordsLoadedRegistrants = new RegistrantList(); 94 protected RegistrantList mLockedRecordsLoadedRegistrants = new RegistrantList(); 95 protected RegistrantList mNetworkLockedRecordsLoadedRegistrants = new RegistrantList(); 96 protected RegistrantList mImsiReadyRegistrants = new RegistrantList(); 97 @UnsupportedAppUsage 98 protected RegistrantList mRecordsEventsRegistrants = new RegistrantList(); 99 protected RegistrantList mNewSmsRegistrants = new RegistrantList(); 100 protected RegistrantList mNetworkSelectionModeAutomaticRegistrants = new RegistrantList(); 101 protected RegistrantList mSpnUpdatedRegistrants = new RegistrantList(); 102 protected RegistrantList mRecordsOverrideRegistrants = new RegistrantList(); 103 104 @UnsupportedAppUsage 105 protected int mRecordsToLoad; // number of pending load requests 106 107 @UnsupportedAppUsage 108 protected AdnRecordCache mAdnCache; 109 110 // ***** Cached SIM State; cleared on channel close 111 112 // SIM is not locked 113 protected static final int LOCKED_RECORDS_REQ_REASON_NONE = 0; 114 // Records requested for PIN or PUK locked SIM 115 protected static final int LOCKED_RECORDS_REQ_REASON_LOCKED = 1; 116 // Records requested for network locked SIM 117 protected static final int LOCKED_RECORDS_REQ_REASON_NETWORK_LOCKED = 2; 118 119 protected boolean mRecordsRequested = false; // true if we've made requests for the sim records 120 protected int mLockedRecordsReqReason = LOCKED_RECORDS_REQ_REASON_NONE; 121 122 @UnsupportedAppUsage 123 protected String mIccId; // Includes only decimals (no hex) 124 125 protected String mFullIccId; // Includes hex characters in ICCID 126 protected String mMsisdn = null; // My mobile number 127 protected String mMsisdnTag = null; 128 protected String mNewMsisdn = null; 129 protected String mNewMsisdnTag = null; 130 @UnsupportedAppUsage 131 protected String mVoiceMailNum = null; 132 protected String mVoiceMailTag = null; 133 protected String mNewVoiceMailNum = null; 134 protected String mNewVoiceMailTag = null; 135 @UnsupportedAppUsage 136 protected boolean mIsVoiceMailFixed = false; 137 @UnsupportedAppUsage 138 protected String mImsi; // IMSI must be only valid numeric characters 0-9 without padding 'f's 139 @UnsupportedAppUsage 140 private IccIoResult auth_rsp; 141 142 @UnsupportedAppUsage 143 protected int mMncLength = UNINITIALIZED; 144 protected int mMailboxIndex = 0; // 0 is no mailbox dailing number associated 145 146 @UnsupportedAppUsage 147 private String mSpn; 148 149 @UnsupportedAppUsage 150 protected String mGid1; 151 protected String mGid2; 152 153 protected String mPnnHomeName; 154 155 protected String mPrefLang; 156 157 protected PlmnActRecord[] mHplmnActRecords; 158 protected PlmnActRecord[] mOplmnActRecords; 159 protected PlmnActRecord[] mPlmnActRecords; 160 161 // A list of PLMN in which the SPN shall be displayed. 162 // Reference: 3GPP TS 31.102 Section 4.2.66 163 protected String[] mSpdi; 164 165 166 // Carrier name display condition bitmask 167 // Reference: 3GPP TS 131.102 section 4.2.12 EF_SPN Display Condition 168 protected int mCarrierNameDisplayCondition; 169 170 protected String[] mEhplmns; 171 protected String[] mFplmns; 172 173 @UnsupportedAppUsage 174 private final Object mLock = new Object(); 175 176 CarrierTestOverride mCarrierTestOverride; 177 178 //Arbitrary offset for the Handler 179 protected static final int HANDLER_ACTION_BASE = 0x12E500; 180 protected static final int HANDLER_ACTION_NONE = HANDLER_ACTION_BASE + 0; 181 protected static final int HANDLER_ACTION_SEND_RESPONSE = HANDLER_ACTION_BASE + 1; 182 protected static AtomicInteger sNextRequestId = new AtomicInteger(1); 183 protected final HashMap<Integer, Message> mPendingResponses = new HashMap<>(); 184 185 // ***** Constants 186 187 // Markers for mncLength 188 protected static final int UNINITIALIZED = -1; 189 protected static final int UNKNOWN = 0; 190 191 // Bitmask for carrier name display condition. 192 @Retention(RetentionPolicy.SOURCE) 193 @IntDef(prefix = {"CARRIER_NAME_DISPLAY_CONDITION_BITMASK_"}, 194 value = {CARRIER_NAME_DISPLAY_CONDITION_BITMASK_PLMN, 195 CARRIER_NAME_DISPLAY_CONDITION_BITMASK_SPN}, 196 flag = true) 197 public @interface CarrierNameDisplayConditionBitmask {} 198 public static final int CARRIER_NAME_DISPLAY_CONDITION_BITMASK_PLMN = 1; 199 public static final int CARRIER_NAME_DISPLAY_CONDITION_BITMASK_SPN = 2; 200 201 202 // See {@link CarrierConfigManager#KEY_SPN_DISPLAY_CONDITION_OVERRIDE_INT}. 203 public static final int INVALID_CARRIER_NAME_DISPLAY_CONDITION_BITMASK = -1; 204 205 // Display SPN only and only if registered to Home PLMNs. 206 // Display PLMN only and only if registered to Non-Home PLMNs. 207 public static final int DEFAULT_CARRIER_NAME_DISPLAY_CONDITION = 0; 208 209 // ***** Event Constants 210 public static final int EVENT_MWI = 0; // Message Waiting indication 211 public static final int EVENT_CFI = 1; // Call Forwarding indication 212 public static final int EVENT_SPN = 2; // Service Provider Name 213 214 public static final int EVENT_GET_ICC_RECORD_DONE = 100; 215 public static final int EVENT_REFRESH = 31; // ICC refresh occurred 216 protected static final int EVENT_APP_READY = 1; 217 private static final int EVENT_AKA_AUTHENTICATE_DONE = 90; 218 219 public static final int CALL_FORWARDING_STATUS_DISABLED = 0; 220 public static final int CALL_FORWARDING_STATUS_ENABLED = 1; 221 public static final int CALL_FORWARDING_STATUS_UNKNOWN = -1; 222 223 public static final int DEFAULT_VOICE_MESSAGE_COUNT = -2; 224 public static final int UNKNOWN_VOICE_MESSAGE_COUNT = -1; 225 226 @Override toString()227 public String toString() { 228 String iccIdToPrint = SubscriptionInfo.givePrintableIccid(mFullIccId); 229 return "mDestroyed=" + mDestroyed 230 + " mContext=" + mContext 231 + " mCi=" + mCi 232 + " mFh=" + mFh 233 + " mParentApp=" + mParentApp 234 + " recordsToLoad=" + mRecordsToLoad 235 + " adnCache=" + mAdnCache 236 + " recordsRequested=" + mRecordsRequested 237 + " lockedRecordsReqReason=" + mLockedRecordsReqReason 238 + " iccid=" + iccIdToPrint 239 + (mCarrierTestOverride.isInTestMode() ? "mFakeIccid=" 240 + mCarrierTestOverride.getFakeIccid() : "") 241 + " msisdnTag=" + mMsisdnTag 242 + " voiceMailNum=" + Rlog.pii(VDBG, mVoiceMailNum) 243 + " voiceMailTag=" + mVoiceMailTag 244 + " voiceMailNum=" + Rlog.pii(VDBG, mNewVoiceMailNum) 245 + " newVoiceMailTag=" + mNewVoiceMailTag 246 + " isVoiceMailFixed=" + mIsVoiceMailFixed 247 + " mImsi=" + ((mImsi != null) ? 248 mImsi.substring(0, 6) + Rlog.pii(VDBG, mImsi.substring(6)) : "null") 249 + (mCarrierTestOverride.isInTestMode() ? " mFakeImsi=" 250 + mCarrierTestOverride.getFakeIMSI() : "") 251 + " mncLength=" + mMncLength 252 + " mailboxIndex=" + mMailboxIndex 253 + " spn=" + mSpn 254 + (mCarrierTestOverride.isInTestMode() ? " mFakeSpn=" 255 + mCarrierTestOverride.getFakeSpn() : ""); 256 } 257 258 /** 259 * Generic ICC record loaded callback. Subclasses can call EF load methods on 260 * {@link IccFileHandler} passing a Message for onLoaded with the what field set to 261 * {@link #EVENT_GET_ICC_RECORD_DONE} and the obj field set to an instance 262 * of this interface. The {@link #handleMessage} method in this class will print a 263 * log message using {@link #getEfName()} and decrement {@link #mRecordsToLoad}. 264 * 265 * If the record load was successful, {@link #onRecordLoaded} will be called with the result. 266 * Otherwise, an error log message will be output by {@link #handleMessage} and 267 * {@link #onRecordLoaded} will not be called. 268 */ 269 public interface IccRecordLoaded { getEfName()270 String getEfName(); onRecordLoaded(AsyncResult ar)271 void onRecordLoaded(AsyncResult ar); 272 } 273 274 // ***** Constructor IccRecords(UiccCardApplication app, Context c, CommandsInterface ci)275 public IccRecords(UiccCardApplication app, Context c, CommandsInterface ci) { 276 mContext = c; 277 mCi = ci; 278 mFh = app.getIccFileHandler(); 279 mParentApp = app; 280 mTelephonyManager = (TelephonyManager) mContext.getSystemService( 281 Context.TELEPHONY_SERVICE); 282 283 mCarrierTestOverride = new CarrierTestOverride(); 284 mCi.registerForIccRefresh(this, EVENT_REFRESH, null); 285 } 286 287 // Override IccRecords for testing setCarrierTestOverride(String mccmnc, String imsi, String iccid, String gid1, String gid2, String pnn, String spn)288 public void setCarrierTestOverride(String mccmnc, String imsi, String iccid, String gid1, 289 String gid2, String pnn, String spn) { 290 mCarrierTestOverride.override(mccmnc, imsi, iccid, gid1, gid2, pnn, spn); 291 mTelephonyManager.setSimOperatorNameForPhone(mParentApp.getPhoneId(), spn); 292 mTelephonyManager.setSimOperatorNumericForPhone(mParentApp.getPhoneId(), mccmnc); 293 mRecordsOverrideRegistrants.notifyRegistrants(); 294 } 295 296 /** 297 * Call when the IccRecords object is no longer going to be used. 298 */ dispose()299 public void dispose() { 300 mDestroyed.set(true); 301 302 // It is possible that there is another thread waiting for the response 303 // to requestIccSimAuthentication() in getIccSimChallengeResponse(). 304 auth_rsp = null; 305 synchronized (mLock) { 306 mLock.notifyAll(); 307 } 308 309 mCi.unregisterForIccRefresh(this); 310 mParentApp = null; 311 mFh = null; 312 mCi = null; 313 mContext = null; 314 if (mAdnCache != null) { 315 mAdnCache.reset(); 316 } 317 mLoaded.set(false); 318 } 319 onReady()320 public abstract void onReady(); 321 322 //***** Public Methods getAdnCache()323 public AdnRecordCache getAdnCache() { 324 return mAdnCache; 325 } 326 327 /** 328 * Adds a message to the pending requests list by generating a unique 329 * (integer) hash key and returning it. The message should never be null. 330 */ storePendingResponseMessage(Message msg)331 public int storePendingResponseMessage(Message msg) { 332 int key = sNextRequestId.getAndIncrement(); 333 synchronized (mPendingResponses) { 334 mPendingResponses.put(key, msg); 335 } 336 return key; 337 } 338 339 /** 340 * Returns the pending request, if any or null 341 */ retrievePendingResponseMessage(Integer key)342 public Message retrievePendingResponseMessage(Integer key) { 343 Message m; 344 synchronized (mPendingResponses) { 345 return mPendingResponses.remove(key); 346 } 347 } 348 349 /** 350 * Returns the ICC ID stripped at the first hex character. Some SIMs have ICC IDs 351 * containing hex digits; {@link #getFullIccId()} should be used to get the full ID including 352 * hex digits. 353 * @return ICC ID without hex digits 354 */ 355 @UnsupportedAppUsage getIccId()356 public String getIccId() { 357 if (mCarrierTestOverride.isInTestMode() && mCarrierTestOverride.getFakeIccid() != null) { 358 return mCarrierTestOverride.getFakeIccid(); 359 } else { 360 return mIccId; 361 } 362 } 363 364 /** 365 * Returns the full ICC ID including hex digits. 366 * @return full ICC ID including hex digits 367 */ getFullIccId()368 public String getFullIccId() { 369 return mFullIccId; 370 } 371 372 @UnsupportedAppUsage registerForRecordsLoaded(Handler h, int what, Object obj)373 public void registerForRecordsLoaded(Handler h, int what, Object obj) { 374 if (mDestroyed.get()) { 375 return; 376 } 377 378 Registrant r = new Registrant(h, what, obj); 379 mRecordsLoadedRegistrants.add(r); 380 381 if (getRecordsLoaded()) { 382 r.notifyRegistrant(new AsyncResult(null, null, null)); 383 } 384 } 385 @UnsupportedAppUsage unregisterForRecordsLoaded(Handler h)386 public void unregisterForRecordsLoaded(Handler h) { 387 mRecordsLoadedRegistrants.remove(h); 388 } 389 unregisterForRecordsOverride(Handler h)390 public void unregisterForRecordsOverride(Handler h) { 391 mRecordsOverrideRegistrants.remove(h); 392 } 393 registerForRecordsOverride(Handler h, int what, Object obj)394 public void registerForRecordsOverride(Handler h, int what, Object obj) { 395 if (mDestroyed.get()) { 396 return; 397 } 398 399 Registrant r = new Registrant(h, what, obj); 400 mRecordsOverrideRegistrants.add(r); 401 402 if (getRecordsLoaded()) { 403 r.notifyRegistrant(new AsyncResult(null, null, null)); 404 } 405 } 406 407 /** 408 * Register to be notified when records are loaded for a PIN or PUK locked SIM 409 */ registerForLockedRecordsLoaded(Handler h, int what, Object obj)410 public void registerForLockedRecordsLoaded(Handler h, int what, Object obj) { 411 if (mDestroyed.get()) { 412 return; 413 } 414 415 Registrant r = new Registrant(h, what, obj); 416 mLockedRecordsLoadedRegistrants.add(r); 417 418 if (getLockedRecordsLoaded()) { 419 r.notifyRegistrant(new AsyncResult(null, null, null)); 420 } 421 } 422 423 /** 424 * Unregister corresponding to registerForLockedRecordsLoaded() 425 */ unregisterForLockedRecordsLoaded(Handler h)426 public void unregisterForLockedRecordsLoaded(Handler h) { 427 mLockedRecordsLoadedRegistrants.remove(h); 428 } 429 430 /** 431 * Register to be notified when records are loaded for a network locked SIM 432 */ registerForNetworkLockedRecordsLoaded(Handler h, int what, Object obj)433 public void registerForNetworkLockedRecordsLoaded(Handler h, int what, Object obj) { 434 if (mDestroyed.get()) { 435 return; 436 } 437 438 Registrant r = new Registrant(h, what, obj); 439 mNetworkLockedRecordsLoadedRegistrants.add(r); 440 441 if (getNetworkLockedRecordsLoaded()) { 442 r.notifyRegistrant(new AsyncResult(null, null, null)); 443 } 444 } 445 446 /** 447 * Unregister corresponding to registerForLockedRecordsLoaded() 448 */ unregisterForNetworkLockedRecordsLoaded(Handler h)449 public void unregisterForNetworkLockedRecordsLoaded(Handler h) { 450 mNetworkLockedRecordsLoadedRegistrants.remove(h); 451 } 452 registerForImsiReady(Handler h, int what, Object obj)453 public void registerForImsiReady(Handler h, int what, Object obj) { 454 if (mDestroyed.get()) { 455 return; 456 } 457 458 Registrant r = new Registrant(h, what, obj); 459 mImsiReadyRegistrants.add(r); 460 461 if (getIMSI() != null) { 462 r.notifyRegistrant(new AsyncResult(null, null, null)); 463 } 464 } unregisterForImsiReady(Handler h)465 public void unregisterForImsiReady(Handler h) { 466 mImsiReadyRegistrants.remove(h); 467 } 468 registerForSpnUpdate(Handler h, int what, Object obj)469 public void registerForSpnUpdate(Handler h, int what, Object obj) { 470 if (mDestroyed.get()) { 471 return; 472 } 473 474 Registrant r = new Registrant(h, what, obj); 475 mSpnUpdatedRegistrants.add(r); 476 477 if (!TextUtils.isEmpty(mSpn)) { 478 r.notifyRegistrant(new AsyncResult(null, null, null)); 479 } 480 } unregisterForSpnUpdate(Handler h)481 public void unregisterForSpnUpdate(Handler h) { 482 mSpnUpdatedRegistrants.remove(h); 483 } 484 485 @UnsupportedAppUsage registerForRecordsEvents(Handler h, int what, Object obj)486 public void registerForRecordsEvents(Handler h, int what, Object obj) { 487 Registrant r = new Registrant (h, what, obj); 488 mRecordsEventsRegistrants.add(r); 489 490 /* Notify registrant of all the possible events. This is to make sure registrant is 491 notified even if event occurred in the past. */ 492 r.notifyResult(EVENT_MWI); 493 r.notifyResult(EVENT_CFI); 494 } 495 @UnsupportedAppUsage unregisterForRecordsEvents(Handler h)496 public void unregisterForRecordsEvents(Handler h) { 497 mRecordsEventsRegistrants.remove(h); 498 } 499 500 @UnsupportedAppUsage registerForNewSms(Handler h, int what, Object obj)501 public void registerForNewSms(Handler h, int what, Object obj) { 502 Registrant r = new Registrant (h, what, obj); 503 mNewSmsRegistrants.add(r); 504 } 505 @UnsupportedAppUsage unregisterForNewSms(Handler h)506 public void unregisterForNewSms(Handler h) { 507 mNewSmsRegistrants.remove(h); 508 } 509 510 @UnsupportedAppUsage registerForNetworkSelectionModeAutomatic( Handler h, int what, Object obj)511 public void registerForNetworkSelectionModeAutomatic( 512 Handler h, int what, Object obj) { 513 Registrant r = new Registrant (h, what, obj); 514 mNetworkSelectionModeAutomaticRegistrants.add(r); 515 } 516 @UnsupportedAppUsage unregisterForNetworkSelectionModeAutomatic(Handler h)517 public void unregisterForNetworkSelectionModeAutomatic(Handler h) { 518 mNetworkSelectionModeAutomaticRegistrants.remove(h); 519 } 520 521 /** 522 * Get the International Mobile Subscriber ID (IMSI) on a SIM 523 * for GSM, UMTS and like networks. Default is null if IMSI is 524 * not supported or unavailable. 525 * 526 * @return null if SIM is not yet ready or unavailable 527 */ 528 @UnsupportedAppUsage getIMSI()529 public String getIMSI() { 530 if (mCarrierTestOverride.isInTestMode() && mCarrierTestOverride.getFakeIMSI() != null) { 531 return mCarrierTestOverride.getFakeIMSI(); 532 } else { 533 return mImsi; 534 } 535 } 536 537 /** 538 * Update IMSI record and try to extract the PLMN information and notify registrants. 539 * @param inImsi the IMSI value 540 */ setImsi(String inImsi)541 public void setImsi(String inImsi) { 542 // Remove trailing F's if present in IMSI. 543 mImsi = IccUtils.stripTrailingFs(inImsi); 544 if (!Objects.equals(mImsi, inImsi)) { 545 loge("Invalid IMSI padding digits received."); 546 } 547 548 if (TextUtils.isEmpty(mImsi)) mImsi = null; 549 550 if (mImsi != null && !mImsi.matches("[0-9]+")) { 551 loge("Invalid non-numeric IMSI digits received."); 552 mImsi = null; 553 } 554 555 // IMSI (MCC+MNC+MSIN) is at least 6 digits, but not more 556 // than 15 (and usually 15). 557 // This will also handle un-set IMSI records (all Fs) 558 if (mImsi != null && (mImsi.length() < 6 || mImsi.length() > 15)) { 559 loge("invalid IMSI " + mImsi); 560 mImsi = null; 561 } 562 563 log("IMSI: mMncLength=" + mMncLength); 564 565 if (mImsi != null && mImsi.length() >= 6) { 566 log("IMSI: " + mImsi.substring(0, 6) + Rlog.pii(VDBG, mImsi.substring(6))); 567 } 568 569 // IMSI has changed so the PLMN might have changed as well 570 updateOperatorPlmn(); 571 572 mImsiReadyRegistrants.notifyRegistrants(); 573 } 574 updateOperatorPlmn()575 protected void updateOperatorPlmn() { 576 // In case of a test override, use the test IMSI 577 String imsi = getIMSI(); 578 579 if (imsi != null) { 580 // First try to guess the length based on a table of known 3-digit MNCs. 581 if (((mMncLength == UNKNOWN) || (mMncLength == 2)) && imsi.length() >= 6) { 582 String mccmncCode = imsi.substring(0, 6); 583 for (String mccmnc : MCCMNC_CODES_HAVING_3DIGITS_MNC) { 584 if (mccmnc.equals(mccmncCode)) { 585 mMncLength = 3; 586 log("IMSI: setting1 mMncLength=" + mMncLength); 587 break; 588 } 589 } 590 } 591 592 // If still unknown, guess using the MCC. 593 if (mMncLength == UNKNOWN) { 594 try { 595 int mcc = Integer.parseInt(imsi.substring(0, 3)); 596 mMncLength = MccTable.smallestDigitsMccForMnc(mcc); 597 log("setting2 mMncLength=" + mMncLength); 598 } catch (NumberFormatException e) { 599 loge("Corrupt IMSI! setting3 mMncLength=" + mMncLength); 600 } 601 } 602 603 if (mMncLength != UNKNOWN && mMncLength != UNINITIALIZED 604 && imsi.length() >= 3 + mMncLength) { 605 log("update mccmnc=" + imsi.substring(0, 3 + mMncLength)); 606 // finally have both the imsi and the mncLength and 607 // can parse the imsi properly 608 MccTable.updateMccMncConfiguration(mContext, imsi.substring(0, 3 + mMncLength)); 609 } 610 } 611 } 612 613 /** 614 * Get the Network Access ID (NAI) on a CSIM for CDMA like networks. Default is null if IMSI is 615 * not supported or unavailable. 616 * 617 * @return null if NAI is not yet ready or unavailable 618 */ getNAI()619 public String getNAI() { 620 return null; 621 } 622 623 @UnsupportedAppUsage getMsisdnNumber()624 public String getMsisdnNumber() { 625 return mMsisdn; 626 } 627 628 /** 629 * Get the Group Identifier Level 1 (GID1) on a SIM for GSM. 630 * @return null if SIM is not yet ready 631 */ 632 @UnsupportedAppUsage getGid1()633 public String getGid1() { 634 if (mCarrierTestOverride.isInTestMode() && mCarrierTestOverride.getFakeGid1() != null) { 635 return mCarrierTestOverride.getFakeGid1(); 636 } else { 637 return mGid1; 638 } 639 } 640 641 /** 642 * Get the Group Identifier Level 2 (GID2) on a SIM. 643 * @return null if SIM is not yet ready 644 */ getGid2()645 public String getGid2() { 646 if (mCarrierTestOverride.isInTestMode() && mCarrierTestOverride.getFakeGid2() != null) { 647 return mCarrierTestOverride.getFakeGid2(); 648 } else { 649 return mGid2; 650 } 651 } 652 653 /** 654 * Get the PLMN network name on a SIM. 655 * @return null if SIM is not yet ready 656 */ getPnnHomeName()657 public String getPnnHomeName() { 658 if (mCarrierTestOverride.isInTestMode() 659 && mCarrierTestOverride.getFakePnnHomeName() != null) { 660 return mCarrierTestOverride.getFakePnnHomeName(); 661 } else { 662 return mPnnHomeName; 663 } 664 } 665 666 @UnsupportedAppUsage setMsisdnNumber(String alphaTag, String number, Message onComplete)667 public void setMsisdnNumber(String alphaTag, String number, 668 Message onComplete) { 669 loge("setMsisdn() should not be invoked on base IccRecords"); 670 // synthesize a "File Not Found" exception and return it 671 AsyncResult.forMessage(onComplete).exception = 672 (new IccIoResult(0x6A, 0x82, (byte[]) null)).getException(); 673 onComplete.sendToTarget(); 674 } 675 getMsisdnAlphaTag()676 public String getMsisdnAlphaTag() { 677 return mMsisdnTag; 678 } 679 getVoiceMailNumber()680 public String getVoiceMailNumber() { 681 return mVoiceMailNum; 682 } 683 684 /** 685 * Return Service Provider Name stored in SIM (EF_SPN=0x6F46) or in RUIM (EF_RUIM_SPN=0x6F41). 686 * 687 * @return null if SIM is not yet ready or no RUIM entry 688 */ 689 @UnsupportedAppUsage getServiceProviderName()690 public String getServiceProviderName() { 691 if (mCarrierTestOverride.isInTestMode() && mCarrierTestOverride.getFakeSpn() != null) { 692 return mCarrierTestOverride.getFakeSpn(); 693 } 694 return mSpn; 695 } 696 setServiceProviderName(String spn)697 protected void setServiceProviderName(String spn) { 698 if (!TextUtils.equals(mSpn, spn)) { 699 mSpn = spn != null ? spn.trim() : null; 700 mSpnUpdatedRegistrants.notifyRegistrants(); 701 } 702 } 703 704 /** 705 * Set voice mail number to SIM record 706 * 707 * The voice mail number can be stored either in EF_MBDN (TS 51.011) or 708 * EF_MAILBOX_CPHS (CPHS 4.2) 709 * 710 * If EF_MBDN is available, store the voice mail number to EF_MBDN 711 * 712 * If EF_MAILBOX_CPHS is enabled, store the voice mail number to EF_CHPS 713 * 714 * So the voice mail number will be stored in both EFs if both are available 715 * 716 * Return error only if both EF_MBDN and EF_MAILBOX_CPHS fail. 717 * 718 * When the operation is complete, onComplete will be sent to its handler 719 * 720 * @param alphaTag alpha-tagging of the dailing nubmer (upto 10 characters) 721 * @param voiceNumber dailing nubmer (upto 20 digits) 722 * if the number is start with '+', then set to international TOA 723 * @param onComplete 724 * onComplete.obj will be an AsyncResult 725 * ((AsyncResult)onComplete.obj).exception == null on success 726 * ((AsyncResult)onComplete.obj).exception != null on fail 727 */ setVoiceMailNumber(String alphaTag, String voiceNumber, Message onComplete)728 public abstract void setVoiceMailNumber(String alphaTag, String voiceNumber, 729 Message onComplete); 730 getVoiceMailAlphaTag()731 public String getVoiceMailAlphaTag() { 732 return mVoiceMailTag; 733 } 734 735 /** 736 * Sets the SIM voice message waiting indicator records 737 * @param line GSM Subscriber Profile Number, one-based. Only '1' is supported 738 * @param countWaiting The number of messages waiting, if known. Use 739 * -1 to indicate that an unknown number of 740 * messages are waiting 741 */ setVoiceMessageWaiting(int line, int countWaiting)742 public abstract void setVoiceMessageWaiting(int line, int countWaiting); 743 744 /** 745 * Called by GsmCdmaPhone to update VoiceMail count 746 */ getVoiceMessageCount()747 public abstract int getVoiceMessageCount(); 748 749 /** 750 * Called by STK Service when REFRESH is received. 751 * @param fileChanged indicates whether any files changed 752 * @param fileList if non-null, a list of EF files that changed 753 */ onRefresh(boolean fileChanged, int[] fileList)754 public abstract void onRefresh(boolean fileChanged, int[] fileList); 755 756 @UnsupportedAppUsage getRecordsLoaded()757 public boolean getRecordsLoaded() { 758 return mRecordsToLoad == 0 && mRecordsRequested; 759 } 760 getLockedRecordsLoaded()761 protected boolean getLockedRecordsLoaded() { 762 return mRecordsToLoad == 0 763 && mLockedRecordsReqReason == LOCKED_RECORDS_REQ_REASON_LOCKED; 764 } 765 getNetworkLockedRecordsLoaded()766 protected boolean getNetworkLockedRecordsLoaded() { 767 return mRecordsToLoad == 0 768 && mLockedRecordsReqReason == LOCKED_RECORDS_REQ_REASON_NETWORK_LOCKED; 769 } 770 771 //***** Overridden from Handler 772 @Override handleMessage(Message msg)773 public void handleMessage(Message msg) { 774 AsyncResult ar; 775 776 switch (msg.what) { 777 case EVENT_GET_ICC_RECORD_DONE: 778 try { 779 ar = (AsyncResult) msg.obj; 780 IccRecordLoaded recordLoaded = (IccRecordLoaded) ar.userObj; 781 if (DBG) log(recordLoaded.getEfName() + " LOADED"); 782 783 if (ar.exception != null) { 784 loge("Record Load Exception: " + ar.exception); 785 } else { 786 recordLoaded.onRecordLoaded(ar); 787 } 788 }catch (RuntimeException exc) { 789 // I don't want these exceptions to be fatal 790 loge("Exception parsing SIM record: " + exc); 791 } finally { 792 // Count up record load responses even if they are fails 793 onRecordLoaded(); 794 } 795 break; 796 797 case EVENT_REFRESH: 798 ar = (AsyncResult)msg.obj; 799 if (DBG) log("Card REFRESH occurred: "); 800 if (ar.exception == null) { 801 handleRefresh((IccRefreshResponse)ar.result); 802 } else { 803 loge("Icc refresh Exception: " + ar.exception); 804 } 805 break; 806 807 case EVENT_AKA_AUTHENTICATE_DONE: 808 ar = (AsyncResult)msg.obj; 809 auth_rsp = null; 810 if (DBG) log("EVENT_AKA_AUTHENTICATE_DONE"); 811 if (ar.exception != null) { 812 loge("Exception ICC SIM AKA: " + ar.exception); 813 } else { 814 try { 815 auth_rsp = (IccIoResult)ar.result; 816 if (DBG) log("ICC SIM AKA: auth_rsp = " + auth_rsp); 817 } catch (Exception e) { 818 loge("Failed to parse ICC SIM AKA contents: " + e); 819 } 820 } 821 synchronized (mLock) { 822 mLock.notifyAll(); 823 } 824 825 break; 826 827 default: 828 super.handleMessage(msg); 829 } 830 } 831 832 /** 833 * Returns the SIM language derived from the EF-LI and EF-PL sim records. 834 */ getSimLanguage()835 public String getSimLanguage() { 836 return mPrefLang; 837 } 838 setSimLanguage(byte[] efLi, byte[] efPl)839 protected void setSimLanguage(byte[] efLi, byte[] efPl) { 840 String[] locales = mContext.getAssets().getLocales(); 841 try { 842 mPrefLang = findBestLanguage(efLi, locales); 843 } catch (UnsupportedEncodingException uee) { 844 log("Unable to parse EF-LI: " + Arrays.toString(efLi)); 845 } 846 847 if (mPrefLang == null) { 848 try { 849 mPrefLang = findBestLanguage(efPl, locales); 850 } catch (UnsupportedEncodingException uee) { 851 log("Unable to parse EF-PL: " + Arrays.toString(efLi)); 852 } 853 } 854 } 855 findBestLanguage(byte[] languages, String[] locales)856 protected static String findBestLanguage(byte[] languages, String[] locales) 857 throws UnsupportedEncodingException { 858 if ((languages == null) || (locales == null)) return null; 859 860 // Each 2-bytes consists of one language 861 for (int i = 0; (i + 1) < languages.length; i += 2) { 862 String lang = new String(languages, i, 2, "ISO-8859-1"); 863 for (int j = 0; j < locales.length; j++) { 864 if (locales[j] != null && locales[j].length() >= 2 && 865 locales[j].substring(0, 2).equalsIgnoreCase(lang)) { 866 return lang; 867 } 868 } 869 } 870 871 // no match found. return null 872 return null; 873 } 874 handleFileUpdate(int efid)875 protected abstract void handleFileUpdate(int efid); 876 877 @UnsupportedAppUsage handleRefresh(IccRefreshResponse refreshResponse)878 protected void handleRefresh(IccRefreshResponse refreshResponse){ 879 if (refreshResponse == null) { 880 if (DBG) log("handleRefresh received without input"); 881 return; 882 } 883 884 if (!TextUtils.isEmpty(refreshResponse.aid) && 885 !refreshResponse.aid.equals(mParentApp.getAid())) { 886 // This is for different app. Ignore. 887 return; 888 } 889 890 switch (refreshResponse.refreshResult) { 891 case IccRefreshResponse.REFRESH_RESULT_FILE_UPDATE: 892 if (DBG) log("handleRefresh with SIM_FILE_UPDATED"); 893 handleFileUpdate(refreshResponse.efId); 894 break; 895 default: 896 // unknown refresh operation 897 if (DBG) log("handleRefresh with unknown operation"); 898 break; 899 } 900 } 901 onRecordLoaded()902 protected abstract void onRecordLoaded(); 903 onAllRecordsLoaded()904 protected abstract void onAllRecordsLoaded(); 905 906 /** 907 * Retrieves the SPN/PLMN display condition from UICC. 908 * 909 * Display of service provider name is required when registered PLMN is neither HPLMN nor a PLMN 910 * in the service provider PLMN list(EF_SPDI). 911 * 912 * Display of PLMN network name is required when registered PLMN is either HPLMN or a PLMN in 913 * the service provider PLMN list(EF_SPDI). 914 * 915 * Reference: 3GPP TS 131.102 section 4.2.12 EF_SPN Display Condition 916 * 917 * @return a bitmask represent the carrier name display condition. 918 */ 919 @CarrierNameDisplayConditionBitmask getCarrierNameDisplayCondition()920 public int getCarrierNameDisplayCondition() { 921 return mCarrierNameDisplayCondition; 922 } 923 924 /** 925 * Retrieves the service provider display information. This is a list of PLMNs in which the 926 * service provider name shall be displayed. 927 * 928 * Reference: 3GPP TS 131.102 section 4.2.66 EF_SPDI 929 * 930 * @return a list of PLMN(mcc+mnc) if EF_SPDI is existed, otherwise return null. 931 */ getServiceProviderDisplayInformation()932 public String[] getServiceProviderDisplayInformation() { 933 return mSpdi; 934 } 935 936 /** 937 * Get home PLMN list. 938 * 939 * @see #getEhplmns() 940 * @see #getServiceProviderDisplayInformation() 941 * 942 * @return a list of HPLMN if existed, otherwise return null. 943 */ getHomePlmns()944 public String[] getHomePlmns() { 945 // hplmn from imsi. 946 String hplmn = getOperatorNumeric(); 947 948 // hplmn from ehplmn list. 949 String[] hplmns = getEhplmns(); 950 951 // plmn from ef_spdi. 952 String[] spdi = getServiceProviderDisplayInformation(); 953 954 // Use the plmn from imsi as the hplmn if Ehplmn not present. 955 if (ArrayUtils.isEmpty(hplmns)) { 956 hplmns = new String[] {hplmn}; 957 } 958 959 if (!ArrayUtils.isEmpty(spdi)) { 960 hplmns = ArrayUtils.concatElements(String.class, hplmns, spdi); 961 } 962 return hplmns; 963 } 964 965 /** 966 * Return true if "Restriction of menu options for manual PLMN selection" 967 * bit is set or EF_CSP data is unavailable, return false otherwise. 968 * Generally used for GSM/UMTS and the like SIMs. 969 */ isCspPlmnEnabled()970 public boolean isCspPlmnEnabled() { 971 return false; 972 } 973 974 /** 975 * Returns the 5 or 6 digit MCC/MNC of the operator that 976 * provided the SIM card. Returns null of SIM is not yet ready 977 * or is not valid for the type of IccCard. Generally used for 978 * GSM/UMTS and the like SIMS 979 */ 980 @UnsupportedAppUsage getOperatorNumeric()981 public String getOperatorNumeric() { 982 return null; 983 } 984 985 /** 986 * Get the current Voice call forwarding flag for GSM/UMTS and the like SIMs 987 * 988 * @return CALL_FORWARDING_STATUS_XXX (DISABLED/ENABLED/UNKNOWN) 989 */ getVoiceCallForwardingFlag()990 public int getVoiceCallForwardingFlag() { 991 return CALL_FORWARDING_STATUS_UNKNOWN; 992 } 993 994 /** 995 * Set the voice call forwarding flag for GSM/UMTS and the like SIMs 996 * 997 * @param line to enable/disable 998 * @param enable 999 * @param number to which CFU is enabled 1000 */ 1001 @UnsupportedAppUsage setVoiceCallForwardingFlag(int line, boolean enable, String number)1002 public void setVoiceCallForwardingFlag(int line, boolean enable, String number) { 1003 } 1004 1005 /** 1006 * Indicates wether the ICC records have been loaded or not 1007 * 1008 * @return true if the records have been loaded, false otherwise. 1009 */ isLoaded()1010 public boolean isLoaded() { 1011 return mLoaded.get(); 1012 } 1013 1014 /** 1015 * Indicates wether SIM is in provisioned state or not. 1016 * Overridden only if SIM can be dynamically provisioned via OTA. 1017 * 1018 * @return true if provisioned 1019 */ isProvisioned()1020 public boolean isProvisioned () { 1021 return true; 1022 } 1023 1024 /** 1025 * Write string to log file 1026 * 1027 * @param s is the string to write 1028 */ 1029 @UnsupportedAppUsage log(String s)1030 protected abstract void log(String s); 1031 1032 /** 1033 * Write error string to log file. 1034 * 1035 * @param s is the string to write 1036 */ loge(String s)1037 protected abstract void loge(String s); 1038 1039 /** 1040 * @return String array containing EHPLMNs associated with the card. 1041 */ getEhplmns()1042 public String[] getEhplmns() { 1043 return mEhplmns; 1044 } 1045 1046 /** 1047 * @return String array containing PLMN from HplmnActRecord. 1048 */ getPlmnsFromHplmnActRecord()1049 public String[] getPlmnsFromHplmnActRecord() { 1050 if (mHplmnActRecords == null) return null; 1051 String[] hplmns = new String[mHplmnActRecords.length]; 1052 for (int i = 0; i < mHplmnActRecords.length; i++) { 1053 hplmns[i] = mHplmnActRecords[i].plmn; 1054 } 1055 return hplmns; 1056 } 1057 1058 /** 1059 * Return an interface to retrieve the ISIM records for IMS, if available. 1060 * @return the interface to retrieve the ISIM records, or null if not supported 1061 */ getIsimRecords()1062 public IsimRecords getIsimRecords() { 1063 return null; 1064 } 1065 1066 @UnsupportedAppUsage getUsimServiceTable()1067 public UsimServiceTable getUsimServiceTable() { 1068 return null; 1069 } 1070 setSystemProperty(String key, String val)1071 protected void setSystemProperty(String key, String val) { 1072 TelephonyManager.getDefault().setTelephonyProperty(mParentApp.getPhoneId(), key, val); 1073 1074 log("[key, value]=" + key + ", " + val); 1075 } 1076 1077 /** 1078 * Returns the response of the SIM application on the UICC to authentication 1079 * challenge/response algorithm. The data string and challenge response are 1080 * Base64 encoded Strings. 1081 * Can support EAP-SIM, EAP-AKA with results encoded per 3GPP TS 31.102. 1082 * 1083 * @param authContext parameter P2 that specifies the authentication context per 3GPP TS 31.102 (Section 7.1.2) 1084 * @param data authentication challenge data 1085 * @return challenge response 1086 */ 1087 @UnsupportedAppUsage getIccSimChallengeResponse(int authContext, String data)1088 public String getIccSimChallengeResponse(int authContext, String data) { 1089 if (DBG) log("getIccSimChallengeResponse:"); 1090 1091 try { 1092 synchronized(mLock) { 1093 CommandsInterface ci = mCi; 1094 UiccCardApplication parentApp = mParentApp; 1095 if (ci != null && parentApp != null) { 1096 ci.requestIccSimAuthentication(authContext, data, 1097 parentApp.getAid(), 1098 obtainMessage(EVENT_AKA_AUTHENTICATE_DONE)); 1099 try { 1100 mLock.wait(); 1101 } catch (InterruptedException e) { 1102 loge("getIccSimChallengeResponse: Fail, interrupted" 1103 + " while trying to request Icc Sim Auth"); 1104 return null; 1105 } 1106 } else { 1107 loge( "getIccSimChallengeResponse: " 1108 + "Fail, ci or parentApp is null"); 1109 return null; 1110 } 1111 } 1112 } catch(Exception e) { 1113 loge( "getIccSimChallengeResponse: " 1114 + "Fail while trying to request Icc Sim Auth"); 1115 return null; 1116 } 1117 1118 if (auth_rsp == null) { 1119 loge("getIccSimChallengeResponse: No authentication response"); 1120 return null; 1121 } 1122 1123 if (DBG) log("getIccSimChallengeResponse: return auth_rsp"); 1124 1125 return android.util.Base64.encodeToString(auth_rsp.payload, android.util.Base64.NO_WRAP); 1126 } 1127 1128 /** 1129 * Convert the spn display condition to a bitmask 1130 * {@link com.android.internal.telephony.uicc.IccRecords.CarrierNameDisplayConditionBitmask}. 1131 * 1132 * b1 is the last bit of the display condition which is used to determine whether display of 1133 * PLMN network name is required when registered PLMN is **either** HPLMN or a PLMN in the 1134 * service provider PLMN list. 1135 * 1136 * b2 is the second last bit of the display condtion which is used to determine 1137 * whether display of Service Provider Name is required when registered PLMN is 1138 * **neither** HPLMN nor PLMN in the service provider PLMN list. 1139 * 1140 * Reference: 3GPP TS 31.102 section 4.2.12 EF_SPN 1141 * 1142 * @return a carrier name display condtion bitmask. 1143 */ 1144 @CarrierNameDisplayConditionBitmask convertSpnDisplayConditionToBitmask(int condition)1145 public static int convertSpnDisplayConditionToBitmask(int condition) { 1146 int carrierNameDisplayCondition = 0; 1147 // b1 = 0: display of registered PLMN name not required when registered PLMN is 1148 // either HPLMN or a PLMN in the service provider PLMN list. 1149 // b1 = 1: display of registered PLMN name required when registered PLMN is 1150 // either HPLMN or a PLMN in the service provider PLMN list. 1151 if ((condition & 0x1) == 0x1) { 1152 carrierNameDisplayCondition |= CARRIER_NAME_DISPLAY_CONDITION_BITMASK_PLMN; 1153 } 1154 1155 // b2 = 0: display of the service provider name is **required** when registered 1156 // PLMN is neither HPLMN nor a PLMN in the service provider PLMN list. 1157 // b2 = 1: display of the servier provider name is **not required** when 1158 // registered PLMN is neither HPLMN nor PLMN in the service provider PLMN list. 1159 if ((condition & 0x2) == 0) { 1160 carrierNameDisplayCondition |= CARRIER_NAME_DISPLAY_CONDITION_BITMASK_SPN; 1161 } 1162 1163 return carrierNameDisplayCondition; 1164 } 1165 dump(FileDescriptor fd, PrintWriter pw, String[] args)1166 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1167 pw.println("IccRecords: " + this); 1168 pw.println(" mDestroyed=" + mDestroyed); 1169 pw.println(" mCi=" + mCi); 1170 pw.println(" mFh=" + mFh); 1171 pw.println(" mParentApp=" + mParentApp); 1172 pw.println(" recordsLoadedRegistrants: size=" + mRecordsLoadedRegistrants.size()); 1173 for (int i = 0; i < mRecordsLoadedRegistrants.size(); i++) { 1174 pw.println(" recordsLoadedRegistrants[" + i + "]=" 1175 + ((Registrant)mRecordsLoadedRegistrants.get(i)).getHandler()); 1176 } 1177 pw.println(" mLockedRecordsLoadedRegistrants: size=" 1178 + mLockedRecordsLoadedRegistrants.size()); 1179 for (int i = 0; i < mLockedRecordsLoadedRegistrants.size(); i++) { 1180 pw.println(" mLockedRecordsLoadedRegistrants[" + i + "]=" 1181 + ((Registrant) mLockedRecordsLoadedRegistrants.get(i)).getHandler()); 1182 } 1183 pw.println(" mNetworkLockedRecordsLoadedRegistrants: size=" 1184 + mNetworkLockedRecordsLoadedRegistrants.size()); 1185 for (int i = 0; i < mNetworkLockedRecordsLoadedRegistrants.size(); i++) { 1186 pw.println(" mLockedRecordsLoadedRegistrants[" + i + "]=" 1187 + ((Registrant) mNetworkLockedRecordsLoadedRegistrants.get(i)).getHandler()); 1188 } 1189 pw.println(" mImsiReadyRegistrants: size=" + mImsiReadyRegistrants.size()); 1190 for (int i = 0; i < mImsiReadyRegistrants.size(); i++) { 1191 pw.println(" mImsiReadyRegistrants[" + i + "]=" 1192 + ((Registrant)mImsiReadyRegistrants.get(i)).getHandler()); 1193 } 1194 pw.println(" mRecordsEventsRegistrants: size=" + mRecordsEventsRegistrants.size()); 1195 for (int i = 0; i < mRecordsEventsRegistrants.size(); i++) { 1196 pw.println(" mRecordsEventsRegistrants[" + i + "]=" 1197 + ((Registrant)mRecordsEventsRegistrants.get(i)).getHandler()); 1198 } 1199 pw.println(" mNewSmsRegistrants: size=" + mNewSmsRegistrants.size()); 1200 for (int i = 0; i < mNewSmsRegistrants.size(); i++) { 1201 pw.println(" mNewSmsRegistrants[" + i + "]=" 1202 + ((Registrant)mNewSmsRegistrants.get(i)).getHandler()); 1203 } 1204 pw.println(" mNetworkSelectionModeAutomaticRegistrants: size=" 1205 + mNetworkSelectionModeAutomaticRegistrants.size()); 1206 for (int i = 0; i < mNetworkSelectionModeAutomaticRegistrants.size(); i++) { 1207 pw.println(" mNetworkSelectionModeAutomaticRegistrants[" + i + "]=" 1208 + ((Registrant)mNetworkSelectionModeAutomaticRegistrants.get(i)).getHandler()); 1209 } 1210 pw.println(" mRecordsRequested=" + mRecordsRequested); 1211 pw.println(" mLockedRecordsReqReason=" + mLockedRecordsReqReason); 1212 pw.println(" mRecordsToLoad=" + mRecordsToLoad); 1213 pw.println(" mRdnCache=" + mAdnCache); 1214 1215 String iccIdToPrint = SubscriptionInfo.givePrintableIccid(mFullIccId); 1216 pw.println(" iccid=" + iccIdToPrint); 1217 pw.println(" mMsisdn=" + Rlog.pii(VDBG, mMsisdn)); 1218 pw.println(" mMsisdnTag=" + mMsisdnTag); 1219 pw.println(" mVoiceMailNum=" + Rlog.pii(VDBG, mVoiceMailNum)); 1220 pw.println(" mVoiceMailTag=" + mVoiceMailTag); 1221 pw.println(" mNewVoiceMailNum=" + Rlog.pii(VDBG, mNewVoiceMailNum)); 1222 pw.println(" mNewVoiceMailTag=" + mNewVoiceMailTag); 1223 pw.println(" mIsVoiceMailFixed=" + mIsVoiceMailFixed); 1224 pw.println(" mImsi=" + ((mImsi != null) ? 1225 mImsi.substring(0, 6) + Rlog.pii(VDBG, mImsi.substring(6)) : "null")); 1226 if (mCarrierTestOverride.isInTestMode()) { 1227 pw.println(" mFakeImsi=" + mCarrierTestOverride.getFakeIMSI()); 1228 } 1229 pw.println(" mMncLength=" + mMncLength); 1230 pw.println(" mMailboxIndex=" + mMailboxIndex); 1231 pw.println(" mSpn=" + mSpn); 1232 if (mCarrierTestOverride.isInTestMode()) { 1233 pw.println(" mFakeSpn=" + mCarrierTestOverride.getFakeSpn()); 1234 } 1235 pw.flush(); 1236 } 1237 1238 /** 1239 * Operator PLMN information. This contains the location area information or tracking area 1240 * that are used to associate a specific name contained in EF_PNN. 1241 * 1242 * Reference: 3GPP TS 31.102 section 4.2.59 EF_OPL 1243 */ 1244 public static final class OperatorPlmnInfo { 1245 // PLMN numeric that may contains wildcard character ".". 1246 // For example, the pattern "123..." could match all PLMN which mcc is 123. 1247 public final String plmnNumericPattern; 1248 1249 public final int lacTacStart; 1250 public final int lacTacEnd; 1251 1252 public final int plmnNetworkNameIndex; OperatorPlmnInfo(String plmnNumericPattern, int lacTacStart, int lacTacEnd, int plmnNetworkNameIndex)1253 public OperatorPlmnInfo(String plmnNumericPattern, int lacTacStart, int lacTacEnd, 1254 int plmnNetworkNameIndex) { 1255 this.plmnNumericPattern = plmnNumericPattern; 1256 this.lacTacStart = lacTacStart; 1257 this.lacTacEnd = lacTacEnd; 1258 this.plmnNetworkNameIndex = plmnNetworkNameIndex; 1259 } 1260 1261 @Override toString()1262 public String toString() { 1263 return "{ plmnNumericPattern = " + plmnNumericPattern 1264 + "lacTacStart = " + lacTacStart 1265 + "lacTacEnd = " + lacTacEnd 1266 + "plmnNetworkNameIndex = " + plmnNetworkNameIndex 1267 + " }"; 1268 } 1269 } 1270 1271 /** 1272 * Full and short version of PLMN network name. 1273 */ 1274 public static final class PlmnNetworkName { 1275 public final String fullName; 1276 public final String shortName; 1277 PlmnNetworkName(String fullName, String shortName)1278 public PlmnNetworkName(String fullName, String shortName) { 1279 this.fullName = fullName; 1280 this.shortName = shortName; 1281 } 1282 1283 @Override toString()1284 public String toString() { 1285 return "{ fullName = " + fullName + " shortName = " + shortName + " }"; 1286 } 1287 } 1288 } 1289