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