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
17package com.android.internal.telephony.uicc;
18
19import android.content.Context;
20import android.os.AsyncResult;
21import android.os.Handler;
22import android.os.Message;
23import android.os.Registrant;
24import android.os.RegistrantList;
25import android.telephony.Rlog;
26import android.telephony.SubscriptionInfo;
27import android.telephony.TelephonyManager;
28
29import com.android.internal.telephony.CommandsInterface;
30import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppState;
31
32import java.io.FileDescriptor;
33import java.io.PrintWriter;
34import java.io.UnsupportedEncodingException;
35import java.util.Arrays;
36import java.util.HashMap;
37import java.util.concurrent.atomic.AtomicBoolean;
38import java.util.concurrent.atomic.AtomicInteger;
39
40/**
41 * {@hide}
42 */
43public 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
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 {
178        String getEfName();
179        void onRecordLoaded(AsyncResult ar);
180    }
181
182    // ***** Constructor
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     */
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
211    public abstract void onReady();
212
213    //***** Public Methods
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     */
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     */
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     */
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     */
254    public String getFullIccId() {
255        return mFullIccId;
256    }
257
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    }
270    public void unregisterForRecordsLoaded(Handler h) {
271        mRecordsLoadedRegistrants.remove(h);
272    }
273
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    }
286    public void unregisterForImsiReady(Handler h) {
287        mImsiReadyRegistrants.remove(h);
288    }
289
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    }
299    public void unregisterForRecordsEvents(Handler h) {
300        mRecordsEventsRegistrants.remove(h);
301    }
302
303    public void registerForNewSms(Handler h, int what, Object obj) {
304        Registrant r = new Registrant (h, what, obj);
305        mNewSmsRegistrants.add(r);
306    }
307    public void unregisterForNewSms(Handler h) {
308        mNewSmsRegistrants.remove(h);
309    }
310
311    public void registerForNetworkSelectionModeAutomatic(
312            Handler h, int what, Object obj) {
313        Registrant r = new Registrant (h, what, obj);
314        mNetworkSelectionModeAutomaticRegistrants.add(r);
315    }
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     */
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     */
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     */
346    public String getNAI() {
347        return null;
348    }
349
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     */
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     */
366    public String getGid2() {
367        return null;
368    }
369
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
379    public String getMsisdnAlphaTag() {
380        return mMsisdnTag;
381    }
382
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     */
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
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     */
445    public abstract void setVoiceMailNumber(String alphaTag, String voiceNumber,
446            Message onComplete);
447
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     */
459    public abstract void setVoiceMessageWaiting(int line, int countWaiting);
460
461    /**
462     * Called by GsmCdmaPhone to update VoiceMail count
463     */
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     */
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     */
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
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
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     */
549    public String getSimLanguage() {
550        return mPrefLang;
551    }
552
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
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
589    protected abstract void onRecordLoaded();
590
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
669    public IsimRecords getIsimRecords() {
670        return null;
671    }
672
673    public UsimServiceTable getUsimServiceTable() {
674        return null;
675    }
676
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     */
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
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