1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.telephony.uicc; 18 19 import android.content.Context; 20 import android.os.AsyncResult; 21 import android.os.Handler; 22 import android.os.Message; 23 import android.os.Registrant; 24 import android.os.RegistrantList; 25 import android.telephony.Rlog; 26 import android.telephony.SubscriptionInfo; 27 import android.telephony.TelephonyManager; 28 29 import com.android.internal.telephony.CommandsInterface; 30 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppState; 31 32 import java.io.FileDescriptor; 33 import java.io.PrintWriter; 34 import java.io.UnsupportedEncodingException; 35 import java.util.Arrays; 36 import java.util.HashMap; 37 import java.util.concurrent.atomic.AtomicBoolean; 38 import java.util.concurrent.atomic.AtomicInteger; 39 40 /** 41 * {@hide} 42 */ 43 public abstract class IccRecords extends Handler implements IccConstants { 44 protected static final boolean DBG = true; 45 protected static final boolean VDBG = false; // STOPSHIP if true 46 47 // ***** Instance Variables 48 protected AtomicBoolean mDestroyed = new AtomicBoolean(false); 49 protected Context mContext; 50 protected CommandsInterface mCi; 51 protected IccFileHandler mFh; 52 protected UiccCardApplication mParentApp; 53 protected TelephonyManager mTelephonyManager; 54 55 protected RegistrantList mRecordsLoadedRegistrants = new RegistrantList(); 56 protected RegistrantList mImsiReadyRegistrants = new RegistrantList(); 57 protected RegistrantList mRecordsEventsRegistrants = new RegistrantList(); 58 protected RegistrantList mNewSmsRegistrants = new RegistrantList(); 59 protected RegistrantList mNetworkSelectionModeAutomaticRegistrants = new RegistrantList(); 60 61 protected int mRecordsToLoad; // number of pending load requests 62 63 protected AdnRecordCache mAdnCache; 64 65 // ***** Cached SIM State; cleared on channel close 66 67 protected boolean mRecordsRequested = false; // true if we've made requests for the sim records 68 69 protected String mIccId; // Includes only decimals (no hex) 70 protected String mFullIccId; // Includes hex characters in ICCID 71 protected String mMsisdn = null; // My mobile number 72 protected String mMsisdnTag = null; 73 protected String mNewMsisdn = null; 74 protected String mNewMsisdnTag = null; 75 protected String mVoiceMailNum = null; 76 protected String mVoiceMailTag = null; 77 protected String mNewVoiceMailNum = null; 78 protected String mNewVoiceMailTag = null; 79 protected boolean mIsVoiceMailFixed = false; 80 protected String mImsi; 81 protected String mFakeImsi; 82 private IccIoResult auth_rsp; 83 84 protected int mMncLength = UNINITIALIZED; 85 protected int mMailboxIndex = 0; // 0 is no mailbox dailing number associated 86 87 private String mSpn; 88 private String mFakeSpn; 89 90 protected String mGid1; 91 protected String mFakeGid1; 92 protected String mGid2; 93 protected String mFakeGid2; 94 95 protected String mPrefLang; 96 97 protected PlmnActRecord[] mHplmnActRecords; 98 protected PlmnActRecord[] mOplmnActRecords; 99 protected PlmnActRecord[] mPlmnActRecords; 100 101 protected String[] mEhplmns; 102 protected String[] mFplmns; 103 104 private final Object mLock = new Object(); 105 106 CarrierTestOverride mCarrierTestOverride; 107 108 //Arbitrary offset for the Handler 109 protected static final int HANDLER_ACTION_BASE = 0x12E500; 110 protected static final int HANDLER_ACTION_NONE = HANDLER_ACTION_BASE + 0; 111 protected static final int HANDLER_ACTION_SEND_RESPONSE = HANDLER_ACTION_BASE + 1; 112 protected static AtomicInteger sNextRequestId = new AtomicInteger(1); 113 protected final HashMap<Integer, Message> mPendingResponses = new HashMap<>(); 114 115 // ***** Constants 116 117 // Markers for mncLength 118 protected static final int UNINITIALIZED = -1; 119 protected static final int UNKNOWN = 0; 120 121 // Bitmasks for SPN display rules. 122 public static final int SPN_RULE_SHOW_SPN = 0x01; 123 public static final int SPN_RULE_SHOW_PLMN = 0x02; 124 125 // ***** Event Constants 126 public static final int EVENT_MWI = 0; // Message Waiting indication 127 public static final int EVENT_CFI = 1; // Call Forwarding indication 128 public static final int EVENT_SPN = 2; // Service Provider Name 129 130 public static final int EVENT_GET_ICC_RECORD_DONE = 100; 131 protected static final int EVENT_APP_READY = 1; 132 private static final int EVENT_AKA_AUTHENTICATE_DONE = 90; 133 134 public static final int CALL_FORWARDING_STATUS_DISABLED = 0; 135 public static final int CALL_FORWARDING_STATUS_ENABLED = 1; 136 public static final int CALL_FORWARDING_STATUS_UNKNOWN = -1; 137 138 public static final int DEFAULT_VOICE_MESSAGE_COUNT = -2; 139 public static final int UNKNOWN_VOICE_MESSAGE_COUNT = -1; 140 141 @Override toString()142 public String toString() { 143 String iccIdToPrint = SubscriptionInfo.givePrintableIccid(mFullIccId); 144 return "mDestroyed=" + mDestroyed 145 + " mContext=" + mContext 146 + " mCi=" + mCi 147 + " mFh=" + mFh 148 + " mParentApp=" + mParentApp 149 + " recordsLoadedRegistrants=" + mRecordsLoadedRegistrants 150 + " mImsiReadyRegistrants=" + mImsiReadyRegistrants 151 + " mRecordsEventsRegistrants=" + mRecordsEventsRegistrants 152 + " mNewSmsRegistrants=" + mNewSmsRegistrants 153 + " mNetworkSelectionModeAutomaticRegistrants=" 154 + mNetworkSelectionModeAutomaticRegistrants 155 + " recordsToLoad=" + mRecordsToLoad 156 + " adnCache=" + mAdnCache 157 + " recordsRequested=" + mRecordsRequested 158 + " iccid=" + iccIdToPrint 159 + " msisdnTag=" + mMsisdnTag 160 + " voiceMailNum=" + Rlog.pii(VDBG, mVoiceMailNum) 161 + " voiceMailTag=" + mVoiceMailTag 162 + " voiceMailNum=" + Rlog.pii(VDBG, mNewVoiceMailNum) 163 + " newVoiceMailTag=" + mNewVoiceMailTag 164 + " isVoiceMailFixed=" + mIsVoiceMailFixed 165 + " mImsi=" + ((mImsi != null) ? 166 mImsi.substring(0, 6) + Rlog.pii(VDBG, mImsi.substring(6)) : "null") 167 + (mCarrierTestOverride.isInTestMode() 168 ? (" mFakeImsi=" + ((mFakeImsi != null) ? mFakeImsi : "null")) : "") 169 + " mncLength=" + mMncLength 170 + " mailboxIndex=" + mMailboxIndex 171 + " spn=" + mSpn 172 + (mCarrierTestOverride.isInTestMode() 173 ? (" mFakeSpn=" + ((mFakeSpn != null) ? mFakeSpn : "null")) : ""); 174 175 } 176 177 /** 178 * Generic ICC record loaded callback. Subclasses can call EF load methods on 179 * {@link IccFileHandler} passing a Message for onLoaded with the what field set to 180 * {@link #EVENT_GET_ICC_RECORD_DONE} and the obj field set to an instance 181 * of this interface. The {@link #handleMessage} method in this class will print a 182 * log message using {@link #getEfName()} and decrement {@link #mRecordsToLoad}. 183 * 184 * If the record load was successful, {@link #onRecordLoaded} will be called with the result. 185 * Otherwise, an error log message will be output by {@link #handleMessage} and 186 * {@link #onRecordLoaded} will not be called. 187 */ 188 public interface IccRecordLoaded { getEfName()189 String getEfName(); onRecordLoaded(AsyncResult ar)190 void onRecordLoaded(AsyncResult ar); 191 } 192 193 // ***** Constructor IccRecords(UiccCardApplication app, Context c, CommandsInterface ci)194 public IccRecords(UiccCardApplication app, Context c, CommandsInterface ci) { 195 mContext = c; 196 mCi = ci; 197 mFh = app.getIccFileHandler(); 198 mParentApp = app; 199 mTelephonyManager = (TelephonyManager) mContext.getSystemService( 200 Context.TELEPHONY_SERVICE); 201 202 mCarrierTestOverride = new CarrierTestOverride(); 203 204 if (mCarrierTestOverride.isInTestMode()) { 205 mFakeImsi = mCarrierTestOverride.getFakeIMSI(); 206 log("load mFakeImsi: " + mFakeImsi); 207 208 mFakeGid1 = mCarrierTestOverride.getFakeGid1(); 209 log("load mFakeGid1: " + mFakeGid1); 210 211 mFakeGid2 = mCarrierTestOverride.getFakeGid2(); 212 log("load mFakeGid2: " + mFakeGid2); 213 214 mFakeSpn = mCarrierTestOverride.getFakeSpn(); 215 log("load mFakeSpn: " + mFakeSpn); 216 } 217 } 218 219 /** 220 * Call when the IccRecords object is no longer going to be used. 221 */ dispose()222 public void dispose() { 223 mDestroyed.set(true); 224 225 // It is possible that there is another thread waiting for the response 226 // to requestIccSimAuthentication() in getIccSimChallengeResponse(). 227 auth_rsp = null; 228 synchronized (mLock) { 229 mLock.notifyAll(); 230 } 231 232 mParentApp = null; 233 mFh = null; 234 mCi = null; 235 mContext = null; 236 } 237 onReady()238 public abstract void onReady(); 239 240 //***** Public Methods getAdnCache()241 public AdnRecordCache getAdnCache() { 242 return mAdnCache; 243 } 244 245 /** 246 * Adds a message to the pending requests list by generating a unique 247 * (integer) hash key and returning it. The message should never be null. 248 */ storePendingResponseMessage(Message msg)249 public int storePendingResponseMessage(Message msg) { 250 int key = sNextRequestId.getAndIncrement(); 251 synchronized (mPendingResponses) { 252 mPendingResponses.put(key, msg); 253 } 254 return key; 255 } 256 257 /** 258 * Returns the pending request, if any or null 259 */ retrievePendingResponseMessage(Integer key)260 public Message retrievePendingResponseMessage(Integer key) { 261 Message m; 262 synchronized (mPendingResponses) { 263 return mPendingResponses.remove(key); 264 } 265 } 266 267 /** 268 * Returns the ICC ID stripped at the first hex character. Some SIMs have ICC IDs 269 * containing hex digits; {@link #getFullIccId()} should be used to get the full ID including 270 * hex digits. 271 * @return ICC ID without hex digits 272 */ getIccId()273 public String getIccId() { 274 return mIccId; 275 } 276 277 /** 278 * Returns the full ICC ID including hex digits. 279 * @return full ICC ID including hex digits 280 */ getFullIccId()281 public String getFullIccId() { 282 return mFullIccId; 283 } 284 registerForRecordsLoaded(Handler h, int what, Object obj)285 public void registerForRecordsLoaded(Handler h, int what, Object obj) { 286 if (mDestroyed.get()) { 287 return; 288 } 289 290 Registrant r = new Registrant(h, what, obj); 291 mRecordsLoadedRegistrants.add(r); 292 293 if (mRecordsToLoad == 0 && mRecordsRequested == true) { 294 r.notifyRegistrant(new AsyncResult(null, null, null)); 295 } 296 } unregisterForRecordsLoaded(Handler h)297 public void unregisterForRecordsLoaded(Handler h) { 298 mRecordsLoadedRegistrants.remove(h); 299 } 300 registerForImsiReady(Handler h, int what, Object obj)301 public void registerForImsiReady(Handler h, int what, Object obj) { 302 if (mDestroyed.get()) { 303 return; 304 } 305 306 Registrant r = new Registrant(h, what, obj); 307 mImsiReadyRegistrants.add(r); 308 309 if (getIMSI() != null) { 310 r.notifyRegistrant(new AsyncResult(null, null, null)); 311 } 312 } unregisterForImsiReady(Handler h)313 public void unregisterForImsiReady(Handler h) { 314 mImsiReadyRegistrants.remove(h); 315 } 316 registerForRecordsEvents(Handler h, int what, Object obj)317 public void registerForRecordsEvents(Handler h, int what, Object obj) { 318 Registrant r = new Registrant (h, what, obj); 319 mRecordsEventsRegistrants.add(r); 320 321 /* Notify registrant of all the possible events. This is to make sure registrant is 322 notified even if event occurred in the past. */ 323 r.notifyResult(EVENT_MWI); 324 r.notifyResult(EVENT_CFI); 325 } unregisterForRecordsEvents(Handler h)326 public void unregisterForRecordsEvents(Handler h) { 327 mRecordsEventsRegistrants.remove(h); 328 } 329 registerForNewSms(Handler h, int what, Object obj)330 public void registerForNewSms(Handler h, int what, Object obj) { 331 Registrant r = new Registrant (h, what, obj); 332 mNewSmsRegistrants.add(r); 333 } unregisterForNewSms(Handler h)334 public void unregisterForNewSms(Handler h) { 335 mNewSmsRegistrants.remove(h); 336 } 337 registerForNetworkSelectionModeAutomatic( Handler h, int what, Object obj)338 public void registerForNetworkSelectionModeAutomatic( 339 Handler h, int what, Object obj) { 340 Registrant r = new Registrant (h, what, obj); 341 mNetworkSelectionModeAutomaticRegistrants.add(r); 342 } unregisterForNetworkSelectionModeAutomatic(Handler h)343 public void unregisterForNetworkSelectionModeAutomatic(Handler h) { 344 mNetworkSelectionModeAutomaticRegistrants.remove(h); 345 } 346 347 /** 348 * Get the International Mobile Subscriber ID (IMSI) on a SIM 349 * for GSM, UMTS and like networks. Default is null if IMSI is 350 * not supported or unavailable. 351 * 352 * @return null if SIM is not yet ready or unavailable 353 */ getIMSI()354 public String getIMSI() { 355 if (mCarrierTestOverride.isInTestMode() && mFakeImsi != null) { 356 return mFakeImsi; 357 } else { 358 return mImsi; 359 } 360 } 361 362 /** 363 * Imsi could be set by ServiceStateTrackers in case of cdma 364 * @param imsi 365 */ setImsi(String imsi)366 public void setImsi(String imsi) { 367 mImsi = imsi; 368 mImsiReadyRegistrants.notifyRegistrants(); 369 } 370 371 /** 372 * Get the Network Access ID (NAI) on a CSIM for CDMA like networks. Default is null if IMSI is 373 * not supported or unavailable. 374 * 375 * @return null if NAI is not yet ready or unavailable 376 */ getNAI()377 public String getNAI() { 378 return null; 379 } 380 getMsisdnNumber()381 public String getMsisdnNumber() { 382 return mMsisdn; 383 } 384 385 /** 386 * Get the Group Identifier Level 1 (GID1) on a SIM for GSM. 387 * @return null if SIM is not yet ready 388 */ getGid1()389 public String getGid1() { 390 if (mCarrierTestOverride.isInTestMode() && mFakeGid1 != null) { 391 return mFakeGid1; 392 } else { 393 return mGid1; 394 } 395 } 396 397 /** 398 * Get the Group Identifier Level 2 (GID2) on a SIM. 399 * @return null if SIM is not yet ready 400 */ getGid2()401 public String getGid2() { 402 if (mCarrierTestOverride.isInTestMode() && mFakeGid2 != null) { 403 return mFakeGid2; 404 } else { 405 return mGid2; 406 } 407 } 408 setMsisdnNumber(String alphaTag, String number, Message onComplete)409 public void setMsisdnNumber(String alphaTag, String number, 410 Message onComplete) { 411 loge("setMsisdn() should not be invoked on base IccRecords"); 412 // synthesize a "File Not Found" exception and return it 413 AsyncResult.forMessage(onComplete).exception = 414 (new IccIoResult(0x6A, 0x82, (byte[]) null)).getException(); 415 onComplete.sendToTarget(); 416 } 417 getMsisdnAlphaTag()418 public String getMsisdnAlphaTag() { 419 return mMsisdnTag; 420 } 421 getVoiceMailNumber()422 public String getVoiceMailNumber() { 423 return mVoiceMailNum; 424 } 425 426 /** 427 * Return Service Provider Name stored in SIM (EF_SPN=0x6F46) or in RUIM (EF_RUIM_SPN=0x6F41). 428 * 429 * @return null if SIM is not yet ready or no RUIM entry 430 */ getServiceProviderName()431 public String getServiceProviderName() { 432 if (mCarrierTestOverride.isInTestMode() && mFakeSpn != null) { 433 return mFakeSpn; 434 } 435 String providerName = mSpn; 436 437 // Check for null pointers, mParentApp can be null after dispose, 438 // which did occur after removing a SIM. 439 UiccCardApplication parentApp = mParentApp; 440 if (parentApp != null) { 441 UiccCard card = parentApp.getUiccCard(); 442 if (card != null) { 443 String brandOverride = card.getOperatorBrandOverride(); 444 if (brandOverride != null) { 445 log("getServiceProviderName: override, providerName=" + providerName); 446 providerName = brandOverride; 447 } else { 448 log("getServiceProviderName: no brandOverride, providerName=" + providerName); 449 } 450 } else { 451 log("getServiceProviderName: card is null, providerName=" + providerName); 452 } 453 } else { 454 log("getServiceProviderName: mParentApp is null, providerName=" + providerName); 455 } 456 return providerName; 457 } 458 setServiceProviderName(String spn)459 protected void setServiceProviderName(String spn) { 460 mSpn = spn; 461 } 462 463 /** 464 * Set voice mail number to SIM record 465 * 466 * The voice mail number can be stored either in EF_MBDN (TS 51.011) or 467 * EF_MAILBOX_CPHS (CPHS 4.2) 468 * 469 * If EF_MBDN is available, store the voice mail number to EF_MBDN 470 * 471 * If EF_MAILBOX_CPHS is enabled, store the voice mail number to EF_CHPS 472 * 473 * So the voice mail number will be stored in both EFs if both are available 474 * 475 * Return error only if both EF_MBDN and EF_MAILBOX_CPHS fail. 476 * 477 * When the operation is complete, onComplete will be sent to its handler 478 * 479 * @param alphaTag alpha-tagging of the dailing nubmer (upto 10 characters) 480 * @param voiceNumber dailing nubmer (upto 20 digits) 481 * if the number is start with '+', then set to international TOA 482 * @param onComplete 483 * onComplete.obj will be an AsyncResult 484 * ((AsyncResult)onComplete.obj).exception == null on success 485 * ((AsyncResult)onComplete.obj).exception != null on fail 486 */ setVoiceMailNumber(String alphaTag, String voiceNumber, Message onComplete)487 public abstract void setVoiceMailNumber(String alphaTag, String voiceNumber, 488 Message onComplete); 489 getVoiceMailAlphaTag()490 public String getVoiceMailAlphaTag() { 491 return mVoiceMailTag; 492 } 493 494 /** 495 * Sets the SIM voice message waiting indicator records 496 * @param line GSM Subscriber Profile Number, one-based. Only '1' is supported 497 * @param countWaiting The number of messages waiting, if known. Use 498 * -1 to indicate that an unknown number of 499 * messages are waiting 500 */ setVoiceMessageWaiting(int line, int countWaiting)501 public abstract void setVoiceMessageWaiting(int line, int countWaiting); 502 503 /** 504 * Called by GsmCdmaPhone to update VoiceMail count 505 */ getVoiceMessageCount()506 public abstract int getVoiceMessageCount(); 507 508 /** 509 * Called by STK Service when REFRESH is received. 510 * @param fileChanged indicates whether any files changed 511 * @param fileList if non-null, a list of EF files that changed 512 */ onRefresh(boolean fileChanged, int[] fileList)513 public abstract void onRefresh(boolean fileChanged, int[] fileList); 514 515 /** 516 * Called by subclasses (SimRecords and RuimRecords) whenever 517 * IccRefreshResponse.REFRESH_RESULT_INIT event received 518 */ onIccRefreshInit()519 protected void onIccRefreshInit() { 520 mAdnCache.reset(); 521 mMncLength = UNINITIALIZED; 522 UiccCardApplication parentApp = mParentApp; 523 if ((parentApp != null) && 524 (parentApp.getState() == AppState.APPSTATE_READY)) { 525 // This will cause files to be reread 526 sendMessage(obtainMessage(EVENT_APP_READY)); 527 } 528 } 529 getRecordsLoaded()530 public boolean getRecordsLoaded() { 531 if (mRecordsToLoad == 0 && mRecordsRequested == true) { 532 return true; 533 } else { 534 return false; 535 } 536 } 537 538 //***** Overridden from Handler 539 @Override handleMessage(Message msg)540 public void handleMessage(Message msg) { 541 AsyncResult ar; 542 543 switch (msg.what) { 544 case EVENT_GET_ICC_RECORD_DONE: 545 try { 546 ar = (AsyncResult) msg.obj; 547 IccRecordLoaded recordLoaded = (IccRecordLoaded) ar.userObj; 548 if (DBG) log(recordLoaded.getEfName() + " LOADED"); 549 550 if (ar.exception != null) { 551 loge("Record Load Exception: " + ar.exception); 552 } else { 553 recordLoaded.onRecordLoaded(ar); 554 } 555 }catch (RuntimeException exc) { 556 // I don't want these exceptions to be fatal 557 loge("Exception parsing SIM record: " + exc); 558 } finally { 559 // Count up record load responses even if they are fails 560 onRecordLoaded(); 561 } 562 break; 563 564 case EVENT_AKA_AUTHENTICATE_DONE: 565 ar = (AsyncResult)msg.obj; 566 auth_rsp = null; 567 if (DBG) log("EVENT_AKA_AUTHENTICATE_DONE"); 568 if (ar.exception != null) { 569 loge("Exception ICC SIM AKA: " + ar.exception); 570 } else { 571 try { 572 auth_rsp = (IccIoResult)ar.result; 573 if (DBG) log("ICC SIM AKA: auth_rsp = " + auth_rsp); 574 } catch (Exception e) { 575 loge("Failed to parse ICC SIM AKA contents: " + e); 576 } 577 } 578 synchronized (mLock) { 579 mLock.notifyAll(); 580 } 581 582 break; 583 584 default: 585 super.handleMessage(msg); 586 } 587 } 588 589 /** 590 * Returns the SIM language derived from the EF-LI and EF-PL sim records. 591 */ getSimLanguage()592 public String getSimLanguage() { 593 return mPrefLang; 594 } 595 setSimLanguage(byte[] efLi, byte[] efPl)596 protected void setSimLanguage(byte[] efLi, byte[] efPl) { 597 String[] locales = mContext.getAssets().getLocales(); 598 try { 599 mPrefLang = findBestLanguage(efLi, locales); 600 } catch (UnsupportedEncodingException uee) { 601 log("Unable to parse EF-LI: " + Arrays.toString(efLi)); 602 } 603 604 if (mPrefLang == null) { 605 try { 606 mPrefLang = findBestLanguage(efPl, locales); 607 } catch (UnsupportedEncodingException uee) { 608 log("Unable to parse EF-PL: " + Arrays.toString(efLi)); 609 } 610 } 611 } 612 findBestLanguage(byte[] languages, String[] locales)613 protected static String findBestLanguage(byte[] languages, String[] locales) 614 throws UnsupportedEncodingException { 615 if ((languages == null) || (locales == null)) return null; 616 617 // Each 2-bytes consists of one language 618 for (int i = 0; (i + 1) < languages.length; i += 2) { 619 String lang = new String(languages, i, 2, "ISO-8859-1"); 620 for (int j = 0; j < locales.length; j++) { 621 if (locales[j] != null && locales[j].length() >= 2 && 622 locales[j].substring(0, 2).equalsIgnoreCase(lang)) { 623 return lang; 624 } 625 } 626 } 627 628 // no match found. return null 629 return null; 630 } 631 onRecordLoaded()632 protected abstract void onRecordLoaded(); 633 onAllRecordsLoaded()634 protected abstract void onAllRecordsLoaded(); 635 636 /** 637 * Returns the SpnDisplayRule based on settings on the SIM and the 638 * specified plmn (currently-registered PLMN). See TS 22.101 Annex A 639 * and TS 51.011 10.3.11 for details. 640 * 641 * If the SPN is not found on the SIM, the rule is always PLMN_ONLY. 642 * Generally used for GSM/UMTS and the like SIMs. 643 */ getDisplayRule(String plmn)644 public abstract int getDisplayRule(String plmn); 645 646 /** 647 * Return true if "Restriction of menu options for manual PLMN selection" 648 * bit is set or EF_CSP data is unavailable, return false otherwise. 649 * Generally used for GSM/UMTS and the like SIMs. 650 */ isCspPlmnEnabled()651 public boolean isCspPlmnEnabled() { 652 return false; 653 } 654 655 /** 656 * Returns the 5 or 6 digit MCC/MNC of the operator that 657 * provided the SIM card. Returns null of SIM is not yet ready 658 * or is not valid for the type of IccCard. Generally used for 659 * GSM/UMTS and the like SIMS 660 */ getOperatorNumeric()661 public String getOperatorNumeric() { 662 return null; 663 } 664 665 /** 666 * Get the current Voice call forwarding flag for GSM/UMTS and the like SIMs 667 * 668 * @return CALL_FORWARDING_STATUS_XXX (DISABLED/ENABLED/UNKNOWN) 669 */ getVoiceCallForwardingFlag()670 public int getVoiceCallForwardingFlag() { 671 return CALL_FORWARDING_STATUS_UNKNOWN; 672 } 673 674 /** 675 * Set the voice call forwarding flag for GSM/UMTS and the like SIMs 676 * 677 * @param line to enable/disable 678 * @param enable 679 * @param number to which CFU is enabled 680 */ setVoiceCallForwardingFlag(int line, boolean enable, String number)681 public void setVoiceCallForwardingFlag(int line, boolean enable, String number) { 682 } 683 684 /** 685 * Indicates wether SIM is in provisioned state or not. 686 * Overridden only if SIM can be dynamically provisioned via OTA. 687 * 688 * @return true if provisioned 689 */ isProvisioned()690 public boolean isProvisioned () { 691 return true; 692 } 693 694 /** 695 * Write string to log file 696 * 697 * @param s is the string to write 698 */ log(String s)699 protected abstract void log(String s); 700 701 /** 702 * Write error string to log file. 703 * 704 * @param s is the string to write 705 */ loge(String s)706 protected abstract void loge(String s); 707 708 /** 709 * Return an interface to retrieve the ISIM records for IMS, if available. 710 * @return the interface to retrieve the ISIM records, or null if not supported 711 */ getIsimRecords()712 public IsimRecords getIsimRecords() { 713 return null; 714 } 715 getUsimServiceTable()716 public UsimServiceTable getUsimServiceTable() { 717 return null; 718 } 719 setSystemProperty(String key, String val)720 protected void setSystemProperty(String key, String val) { 721 TelephonyManager.getDefault().setTelephonyProperty(mParentApp.getPhoneId(), key, val); 722 723 log("[key, value]=" + key + ", " + val); 724 } 725 726 /** 727 * Returns the response of the SIM application on the UICC to authentication 728 * challenge/response algorithm. The data string and challenge response are 729 * Base64 encoded Strings. 730 * Can support EAP-SIM, EAP-AKA with results encoded per 3GPP TS 31.102. 731 * 732 * @param authContext parameter P2 that specifies the authentication context per 3GPP TS 31.102 (Section 7.1.2) 733 * @param data authentication challenge data 734 * @return challenge response 735 */ getIccSimChallengeResponse(int authContext, String data)736 public String getIccSimChallengeResponse(int authContext, String data) { 737 if (DBG) log("getIccSimChallengeResponse:"); 738 739 try { 740 synchronized(mLock) { 741 CommandsInterface ci = mCi; 742 UiccCardApplication parentApp = mParentApp; 743 if (ci != null && parentApp != null) { 744 ci.requestIccSimAuthentication(authContext, data, 745 parentApp.getAid(), 746 obtainMessage(EVENT_AKA_AUTHENTICATE_DONE)); 747 try { 748 mLock.wait(); 749 } catch (InterruptedException e) { 750 loge("getIccSimChallengeResponse: Fail, interrupted" 751 + " while trying to request Icc Sim Auth"); 752 return null; 753 } 754 } else { 755 loge( "getIccSimChallengeResponse: " 756 + "Fail, ci or parentApp is null"); 757 return null; 758 } 759 } 760 } catch(Exception e) { 761 loge( "getIccSimChallengeResponse: " 762 + "Fail while trying to request Icc Sim Auth"); 763 return null; 764 } 765 766 if (auth_rsp == null) { 767 loge("getIccSimChallengeResponse: No authentication response"); 768 return null; 769 } 770 771 if (DBG) log("getIccSimChallengeResponse: return auth_rsp"); 772 773 return android.util.Base64.encodeToString(auth_rsp.payload, android.util.Base64.NO_WRAP); 774 } 775 dump(FileDescriptor fd, PrintWriter pw, String[] args)776 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 777 pw.println("IccRecords: " + this); 778 pw.println(" mDestroyed=" + mDestroyed); 779 pw.println(" mCi=" + mCi); 780 pw.println(" mFh=" + mFh); 781 pw.println(" mParentApp=" + mParentApp); 782 pw.println(" recordsLoadedRegistrants: size=" + mRecordsLoadedRegistrants.size()); 783 for (int i = 0; i < mRecordsLoadedRegistrants.size(); i++) { 784 pw.println(" recordsLoadedRegistrants[" + i + "]=" 785 + ((Registrant)mRecordsLoadedRegistrants.get(i)).getHandler()); 786 } 787 pw.println(" mImsiReadyRegistrants: size=" + mImsiReadyRegistrants.size()); 788 for (int i = 0; i < mImsiReadyRegistrants.size(); i++) { 789 pw.println(" mImsiReadyRegistrants[" + i + "]=" 790 + ((Registrant)mImsiReadyRegistrants.get(i)).getHandler()); 791 } 792 pw.println(" mRecordsEventsRegistrants: size=" + mRecordsEventsRegistrants.size()); 793 for (int i = 0; i < mRecordsEventsRegistrants.size(); i++) { 794 pw.println(" mRecordsEventsRegistrants[" + i + "]=" 795 + ((Registrant)mRecordsEventsRegistrants.get(i)).getHandler()); 796 } 797 pw.println(" mNewSmsRegistrants: size=" + mNewSmsRegistrants.size()); 798 for (int i = 0; i < mNewSmsRegistrants.size(); i++) { 799 pw.println(" mNewSmsRegistrants[" + i + "]=" 800 + ((Registrant)mNewSmsRegistrants.get(i)).getHandler()); 801 } 802 pw.println(" mNetworkSelectionModeAutomaticRegistrants: size=" 803 + mNetworkSelectionModeAutomaticRegistrants.size()); 804 for (int i = 0; i < mNetworkSelectionModeAutomaticRegistrants.size(); i++) { 805 pw.println(" mNetworkSelectionModeAutomaticRegistrants[" + i + "]=" 806 + ((Registrant)mNetworkSelectionModeAutomaticRegistrants.get(i)).getHandler()); 807 } 808 pw.println(" mRecordsRequested=" + mRecordsRequested); 809 pw.println(" mRecordsToLoad=" + mRecordsToLoad); 810 pw.println(" mRdnCache=" + mAdnCache); 811 812 String iccIdToPrint = SubscriptionInfo.givePrintableIccid(mFullIccId); 813 pw.println(" iccid=" + iccIdToPrint); 814 pw.println(" mMsisdn=" + Rlog.pii(VDBG, mMsisdn)); 815 pw.println(" mMsisdnTag=" + mMsisdnTag); 816 pw.println(" mVoiceMailNum=" + Rlog.pii(VDBG, mVoiceMailNum)); 817 pw.println(" mVoiceMailTag=" + mVoiceMailTag); 818 pw.println(" mNewVoiceMailNum=" + Rlog.pii(VDBG, mNewVoiceMailNum)); 819 pw.println(" mNewVoiceMailTag=" + mNewVoiceMailTag); 820 pw.println(" mIsVoiceMailFixed=" + mIsVoiceMailFixed); 821 pw.println(" mImsi=" + ((mImsi != null) ? 822 mImsi.substring(0, 6) + Rlog.pii(VDBG, mImsi.substring(6)) : "null")); 823 if (mCarrierTestOverride.isInTestMode()) { 824 pw.println(" mFakeImsi=" + ((mFakeImsi != null) ? mFakeImsi : "null")); 825 } 826 pw.println(" mMncLength=" + mMncLength); 827 pw.println(" mMailboxIndex=" + mMailboxIndex); 828 pw.println(" mSpn=" + mSpn); 829 if (mCarrierTestOverride.isInTestMode()) { 830 pw.println(" mFakeSpn=" + ((mFakeSpn != null) ? mFakeSpn : "null")); 831 } 832 pw.flush(); 833 } 834 } 835