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