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