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