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.annotation.IntDef;
20 import android.annotation.Nullable;
21 import android.content.Context;
22 import android.os.AsyncResult;
23 import android.os.Handler;
24 import android.os.Message;
25 import android.os.Registrant;
26 import android.os.RegistrantList;
27 import android.os.SystemClock;
28 import android.telephony.SubscriptionInfo;
29 import android.telephony.TelephonyManager;
30 import android.text.TextUtils;
31 import android.util.Pair;
32 
33 import com.android.internal.annotations.VisibleForTesting;
34 import com.android.internal.telephony.CommandsInterface;
35 import com.android.internal.telephony.MccTable;
36 import com.android.internal.telephony.util.ArrayUtils;
37 import com.android.telephony.Rlog;
38 
39 import java.io.FileDescriptor;
40 import java.io.PrintWriter;
41 import java.io.UnsupportedEncodingException;
42 import java.lang.annotation.Retention;
43 import java.lang.annotation.RetentionPolicy;
44 import java.util.Arrays;
45 import java.util.HashMap;
46 import java.util.Objects;
47 import java.util.concurrent.atomic.AtomicBoolean;
48 import java.util.concurrent.atomic.AtomicInteger;
49 
50 /**
51  * {@hide}
52  */
53 public abstract class IccRecords extends Handler implements IccConstants {
54     protected static final boolean DBG = true;
55     protected static final boolean VDBG = false; // STOPSHIP if true
56 
57     // Lookup table for carriers known to produce SIMs which incorrectly indicate MNC length.
58     private static final String[] MCCMNC_CODES_HAVING_3DIGITS_MNC = {
59         "302370", "302720", "310260",
60         "405025", "405026", "405027", "405028", "405029", "405030", "405031", "405032",
61         "405033", "405034", "405035", "405036", "405037", "405038", "405039", "405040",
62         "405041", "405042", "405043", "405044", "405045", "405046", "405047", "405750",
63         "405751", "405752", "405753", "405754", "405755", "405756", "405799", "405800",
64         "405801", "405802", "405803", "405804", "405805", "405806", "405807", "405808",
65         "405809", "405810", "405811", "405812", "405813", "405814", "405815", "405816",
66         "405817", "405818", "405819", "405820", "405821", "405822", "405823", "405824",
67         "405825", "405826", "405827", "405828", "405829", "405830", "405831", "405832",
68         "405833", "405834", "405835", "405836", "405837", "405838", "405839", "405840",
69         "405841", "405842", "405843", "405844", "405845", "405846", "405847", "405848",
70         "405849", "405850", "405851", "405852", "405853", "405854", "405855", "405856",
71         "405857", "405858", "405859", "405860", "405861", "405862", "405863", "405864",
72         "405865", "405866", "405867", "405868", "405869", "405870", "405871", "405872",
73         "405873", "405874", "405875", "405876", "405877", "405878", "405879", "405880",
74         "405881", "405882", "405883", "405884", "405885", "405886", "405908", "405909",
75         "405910", "405911", "405912", "405913", "405914", "405915", "405916", "405917",
76         "405918", "405919", "405920", "405921", "405922", "405923", "405924", "405925",
77         "405926", "405927", "405928", "405929", "405930", "405931", "405932", "502142",
78         "502143", "502145", "502146", "502147", "502148"
79     };
80 
81     // ***** Instance Variables
82     protected AtomicBoolean mDestroyed = new AtomicBoolean(false);
83     protected AtomicBoolean mLoaded = new AtomicBoolean(false);
84     protected Context mContext;
85     protected CommandsInterface mCi;
86     protected IccFileHandler mFh;
87     protected UiccCardApplication mParentApp;
88     protected TelephonyManager mTelephonyManager;
89 
90     protected RegistrantList mRecordsLoadedRegistrants = new RegistrantList();
91     protected RegistrantList mLockedRecordsLoadedRegistrants = new RegistrantList();
92     protected RegistrantList mNetworkLockedRecordsLoadedRegistrants = new RegistrantList();
93     protected RegistrantList mImsiReadyRegistrants = new RegistrantList();
94     protected RegistrantList mRecordsEventsRegistrants = new RegistrantList();
95     protected RegistrantList mNewSmsRegistrants = new RegistrantList();
96     protected RegistrantList mNetworkSelectionModeAutomaticRegistrants = new RegistrantList();
97     protected RegistrantList mSpnUpdatedRegistrants = new RegistrantList();
98     protected RegistrantList mRecordsOverrideRegistrants = new RegistrantList();
99 
100     protected int mRecordsToLoad;  // number of pending load requests
101 
102     protected AdnRecordCache mAdnCache;
103 
104     // ***** Cached SIM State; cleared on channel close
105 
106     // SIM is not locked
107     protected static final int LOCKED_RECORDS_REQ_REASON_NONE = 0;
108     // Records requested for PIN or PUK locked SIM
109     protected static final int LOCKED_RECORDS_REQ_REASON_LOCKED = 1;
110     // Records requested for network locked SIM
111     protected static final int LOCKED_RECORDS_REQ_REASON_NETWORK_LOCKED = 2;
112 
113     protected boolean mRecordsRequested = false; // true if we've made requests for the sim records
114     protected int mLockedRecordsReqReason = LOCKED_RECORDS_REQ_REASON_NONE;
115 
116     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED)
117     public String mIccId;  // Includes only decimals (no hex)
118 
119     protected String mFullIccId;  // Includes hex characters in ICCID
120     protected String mMsisdn = null;  // My mobile number
121     protected String mMsisdnTag = null;
122     protected String mNewMsisdn = null;
123     protected String mNewMsisdnTag = null;
124     protected String mVoiceMailNum = null;
125     protected String mVoiceMailTag = null;
126     protected String mNewVoiceMailNum = null;
127     protected String mNewVoiceMailTag = null;
128     protected boolean mIsVoiceMailFixed = false;
129     protected String mImsi; // IMSI must be only valid numeric characters 0-9 without padding 'f's
130 
131     protected int mMncLength = UNINITIALIZED;
132     protected int mMailboxIndex = 0; // 0 is no mailbox dailing number associated
133 
134     protected int mSmsCountOnIcc = 0;
135 
136     private String mSpn;
137 
138     protected String mGid1;
139     protected String mGid2;
140 
141     protected String mPnnHomeName;
142 
143     protected String mPrefLang;
144 
145     protected PlmnActRecord[] mHplmnActRecords;
146     protected PlmnActRecord[] mOplmnActRecords;
147     protected PlmnActRecord[] mPlmnActRecords;
148 
149     // A list of PLMN in which the SPN shall be displayed.
150     // Reference: 3GPP TS 31.102 Section 4.2.66
151     protected String[] mSpdi;
152 
153 
154     // Carrier name display condition bitmask
155     // Reference: 3GPP TS 131.102 section 4.2.12 EF_SPN Display Condition
156     protected int mCarrierNameDisplayCondition;
157 
158     protected String[] mEhplmns;
159     protected String[] mFplmns;
160 
161     CarrierTestOverride mCarrierTestOverride;
162 
163     //Arbitrary offset for the Handler
164     protected static final int HANDLER_ACTION_BASE = 0x12E500;
165     protected static final int HANDLER_ACTION_NONE = HANDLER_ACTION_BASE + 0;
166     protected static final int HANDLER_ACTION_SEND_RESPONSE = HANDLER_ACTION_BASE + 1;
167     protected static AtomicInteger sNextRequestId = new AtomicInteger(1);
168     protected final HashMap<Integer, Pair<Message, Object>> mPendingTransactions = new HashMap<>();
169     // ***** Constants
170 
171     // Markers for mncLength
172     protected static final int UNINITIALIZED = -1;
173     protected static final int UNKNOWN = 0;
174 
175     // Bitmask for carrier name display condition.
176     @Retention(RetentionPolicy.SOURCE)
177     @IntDef(prefix = {"CARRIER_NAME_DISPLAY_CONDITION_BITMASK_"},
178             value = {CARRIER_NAME_DISPLAY_CONDITION_BITMASK_PLMN,
179                     CARRIER_NAME_DISPLAY_CONDITION_BITMASK_SPN},
180             flag = true)
181     public @interface CarrierNameDisplayConditionBitmask {}
182     public static final int CARRIER_NAME_DISPLAY_CONDITION_BITMASK_PLMN = 1;
183     public static final int CARRIER_NAME_DISPLAY_CONDITION_BITMASK_SPN = 2;
184 
185 
186     // See {@link CarrierConfigManager#KEY_SPN_DISPLAY_CONDITION_OVERRIDE_INT}.
187     public static final int INVALID_CARRIER_NAME_DISPLAY_CONDITION_BITMASK = -1;
188 
189     // Display SPN only and only if registered to Home PLMNs.
190     // Display PLMN only and only if registered to Non-Home PLMNs.
191     public static final int DEFAULT_CARRIER_NAME_DISPLAY_CONDITION = 0;
192 
193     // ***** Event Constants
194     public static final int EVENT_MWI = 0; // Message Waiting indication
195     public static final int EVENT_CFI = 1; // Call Forwarding indication
196     public static final int EVENT_SPN = 2; // Service Provider Name
197 
198     public static final int EVENT_GET_ICC_RECORD_DONE = 100;
199     public static final int EVENT_REFRESH = 31; // ICC refresh occurred
200     private static final int EVENT_AKA_AUTHENTICATE_DONE = 90;
201     protected static final int EVENT_GET_SMS_RECORD_SIZE_DONE = 28;
202 
203     protected static final int SYSTEM_EVENT_BASE = 0x100;
204     protected static final int EVENT_APP_READY = 1 + SYSTEM_EVENT_BASE;
205     protected static final int EVENT_APP_LOCKED = 2 + SYSTEM_EVENT_BASE;
206     protected static final int EVENT_APP_NETWORK_LOCKED = 3 + SYSTEM_EVENT_BASE;
207     protected static final int EVENT_APP_DETECTED = 4 + SYSTEM_EVENT_BASE;
208 
209     public static final int CALL_FORWARDING_STATUS_DISABLED = 0;
210     public static final int CALL_FORWARDING_STATUS_ENABLED = 1;
211     public static final int CALL_FORWARDING_STATUS_UNKNOWN = -1;
212 
213     public static final int DEFAULT_VOICE_MESSAGE_COUNT = -2;
214     public static final int UNKNOWN_VOICE_MESSAGE_COUNT = -1;
215 
216     // Maximum time in millisecond to wait for a IccSim Challenge before assuming it will not
217     // arrive and returning null to the callers.
218     private static final long ICC_SIM_CHALLENGE_TIMEOUT_MILLIS = 2500;
219 
220     /**
221      * There are two purposes for this class. First, each instance of AuthAsyncResponse acts as a
222      * lock to for calling thead to wait in getIccSimChallengeResponse(). Second, pass the IMS
223      * authentication response to the getIccSimChallengeResponse().
224      */
225     private static class AuthAsyncResponse {
226         public IccIoResult authRsp;
227         public Throwable exception;
228     }
229 
230     @Override
toString()231     public String toString() {
232         String iccIdToPrint = SubscriptionInfo.givePrintableIccid(mFullIccId);
233         return "mDestroyed=" + mDestroyed
234                 + " mContext=" + mContext
235                 + " mCi=" + mCi
236                 + " mFh=" + mFh
237                 + " mParentApp=" + mParentApp
238                 + " recordsToLoad=" + mRecordsToLoad
239                 + " adnCache=" + mAdnCache
240                 + " recordsRequested=" + mRecordsRequested
241                 + " lockedRecordsReqReason=" + mLockedRecordsReqReason
242                 + " iccid=" + iccIdToPrint
243                 + (mCarrierTestOverride.isInTestMode() ? "mFakeIccid="
244                 + mCarrierTestOverride.getFakeIccid() : "")
245                 + " msisdnTag=" + mMsisdnTag
246                 + " voiceMailNum=" + Rlog.pii(VDBG, mVoiceMailNum)
247                 + " voiceMailTag=" + mVoiceMailTag
248                 + " voiceMailNum=" + Rlog.pii(VDBG, mNewVoiceMailNum)
249                 + " newVoiceMailTag=" + mNewVoiceMailTag
250                 + " isVoiceMailFixed=" + mIsVoiceMailFixed
251                 + " mImsi=" + ((mImsi != null) ?
252                 mImsi.substring(0, 6) + Rlog.pii(VDBG, mImsi.substring(6)) : "null")
253                 + (mCarrierTestOverride.isInTestMode() ? " mFakeImsi="
254                 + mCarrierTestOverride.getFakeIMSI() : "")
255                 + " mncLength=" + mMncLength
256                 + " mailboxIndex=" + mMailboxIndex
257                 + " spn=" + mSpn
258                 + (mCarrierTestOverride.isInTestMode() ? " mFakeSpn="
259                 + mCarrierTestOverride.getFakeSpn() : "");
260     }
261 
262     /**
263      * Generic ICC record loaded callback. Subclasses can call EF load methods on
264      * {@link IccFileHandler} passing a Message for onLoaded with the what field set to
265      * {@link #EVENT_GET_ICC_RECORD_DONE} and the obj field set to an instance
266      * of this interface. The {@link #handleMessage} method in this class will print a
267      * log message using {@link #getEfName()} and decrement {@link #mRecordsToLoad}.
268      *
269      * If the record load was successful, {@link #onRecordLoaded} will be called with the result.
270      * Otherwise, an error log message will be output by {@link #handleMessage} and
271      * {@link #onRecordLoaded} will not be called.
272      */
273     public interface IccRecordLoaded {
getEfName()274         String getEfName();
onRecordLoaded(AsyncResult ar)275         void onRecordLoaded(AsyncResult ar);
276     }
277 
278     // ***** Constructor
IccRecords(UiccCardApplication app, Context c, CommandsInterface ci)279     public IccRecords(UiccCardApplication app, Context c, CommandsInterface ci) {
280         mContext = c;
281         mCi = ci;
282         mFh = app.getIccFileHandler();
283         mParentApp = app;
284         mTelephonyManager = (TelephonyManager) mContext.getSystemService(
285                 Context.TELEPHONY_SERVICE);
286 
287         mCarrierTestOverride = new CarrierTestOverride();
288         mCi.registerForIccRefresh(this, EVENT_REFRESH, null);
289 
290         mParentApp.registerForReady(this, EVENT_APP_READY, null);
291         mParentApp.registerForDetected(this, EVENT_APP_DETECTED, null);
292         mParentApp.registerForLocked(this, EVENT_APP_LOCKED, null);
293         mParentApp.registerForNetworkLocked(this, EVENT_APP_NETWORK_LOCKED, null);
294     }
295 
296     // Override IccRecords for testing
setCarrierTestOverride(String mccmnc, String imsi, String iccid, String gid1, String gid2, String pnn, String spn)297     public void setCarrierTestOverride(String mccmnc, String imsi, String iccid, String gid1,
298             String gid2, String pnn, String spn)  {
299         mCarrierTestOverride.override(mccmnc, imsi, iccid, gid1, gid2, pnn, spn);
300         mTelephonyManager.setSimOperatorNameForPhone(mParentApp.getPhoneId(), spn);
301         mTelephonyManager.setSimOperatorNumericForPhone(mParentApp.getPhoneId(), mccmnc);
302         mRecordsOverrideRegistrants.notifyRegistrants();
303     }
304 
305     /**
306      * Call when the IccRecords object is no longer going to be used.
307      */
dispose()308     public void dispose() {
309         mDestroyed.set(true);
310 
311         mCi.unregisterForIccRefresh(this);
312         mParentApp.unregisterForReady(this);
313         mParentApp.unregisterForDetected(this);
314         mParentApp.unregisterForLocked(this);
315         mParentApp.unregisterForNetworkLocked(this);
316 
317         mParentApp = null;
318         mFh = null;
319         mCi = null;
320         mContext = null;
321         if (mAdnCache != null) {
322             mAdnCache.reset();
323         }
324         mLoaded.set(false);
325     }
326 
onReady()327     protected abstract void onReady();
328 
onDetected()329     protected void onDetected() {
330         mRecordsRequested = false;
331         mLoaded.set(false);
332     }
333 
onLocked()334     protected void onLocked() {
335         // The LOADED state should not be indicated while the lock is effective.
336         mRecordsRequested = false;
337         mLoaded.set(false);
338     }
339 
340     //***** Public Methods
getAdnCache()341     public AdnRecordCache getAdnCache() {
342         return mAdnCache;
343     }
344 
345     /**
346      * Adds a message to the pending requests list by generating a unique (integer)
347      * hash key and returning it. The message should never be null.
348      *
349      * @param msg Message of the transaction to be stored
350      * @return the unique (integer) hash key to retrieve the pending transaction
351      */
storePendingTransaction(Message msg)352     public int storePendingTransaction(Message msg) {
353         return storePendingTransaction(msg, null);
354     }
355 
356     /**
357      * Adds a message and obj pair to the pending requests list by generating a unique (integer)
358      * hash key and returning it. The message should never be null.
359      *
360      * @param msg Message of the transaction to be stored
361      * @param obj Object of the transaction to be stored
362      * @return the unique (integer) hash key to retrieve the pending transaction
363      */
storePendingTransaction(Message msg, Object obj)364     public int storePendingTransaction(Message msg, Object obj) {
365         int key = sNextRequestId.getAndIncrement();
366         Pair<Message, Object> pair = new Pair<Message, Object>(msg, obj);
367         synchronized (mPendingTransactions) {
368             mPendingTransactions.put(key, pair);
369         }
370         return key;
371     }
372 
373     /**
374      * Returns the pending transaction and free it from memory, if any or null
375      *
376      * @param key key of the entry to retrieve
377      * @return The pending transaction.
378      */
retrievePendingTransaction(Integer key)379     public Pair<Message, Object> retrievePendingTransaction(Integer key) {
380         synchronized (mPendingTransactions) {
381             return mPendingTransactions.remove(key);
382         }
383     }
384 
385     /**
386      * Returns the ICC ID stripped at the first hex character. Some SIMs have ICC IDs
387      * containing hex digits; {@link #getFullIccId()} should be used to get the full ID including
388      * hex digits.
389      * @return ICC ID without hex digits
390      */
getIccId()391     public String getIccId() {
392         if (mCarrierTestOverride.isInTestMode()) {
393             String fakeIccId = mCarrierTestOverride.getFakeIccid();
394             if (fakeIccId != null) {
395                 return fakeIccId;
396             }
397         }
398         return mIccId;
399     }
400 
401     /**
402      * Returns the full ICC ID including hex digits.
403      * @return full ICC ID including hex digits
404      */
getFullIccId()405     public String getFullIccId() {
406         return mFullIccId;
407     }
408 
registerForRecordsLoaded(Handler h, int what, Object obj)409     public void registerForRecordsLoaded(Handler h, int what, Object obj) {
410         if (mDestroyed.get()) {
411             return;
412         }
413 
414         Registrant r = new Registrant(h, what, obj);
415         mRecordsLoadedRegistrants.add(r);
416 
417         if (getRecordsLoaded()) {
418             r.notifyRegistrant(new AsyncResult(null, null, null));
419         }
420     }
421 
unregisterForRecordsLoaded(Handler h)422     public void unregisterForRecordsLoaded(Handler h) {
423         mRecordsLoadedRegistrants.remove(h);
424     }
425 
unregisterForRecordsOverride(Handler h)426     public void unregisterForRecordsOverride(Handler h) {
427         mRecordsOverrideRegistrants.remove(h);
428     }
429 
registerForRecordsOverride(Handler h, int what, Object obj)430     public void registerForRecordsOverride(Handler h, int what, Object obj) {
431         if (mDestroyed.get()) {
432             return;
433         }
434 
435         Registrant r = new Registrant(h, what, obj);
436         mRecordsOverrideRegistrants.add(r);
437 
438         if (getRecordsLoaded()) {
439             r.notifyRegistrant(new AsyncResult(null, null, null));
440         }
441     }
442 
443     /**
444      * Register to be notified when records are loaded for a PIN or PUK locked SIM
445      */
registerForLockedRecordsLoaded(Handler h, int what, Object obj)446     public void registerForLockedRecordsLoaded(Handler h, int what, Object obj) {
447         if (mDestroyed.get()) {
448             return;
449         }
450 
451         Registrant r = new Registrant(h, what, obj);
452         mLockedRecordsLoadedRegistrants.add(r);
453 
454         if (getLockedRecordsLoaded()) {
455             r.notifyRegistrant(new AsyncResult(null, null, null));
456         }
457     }
458 
459     /**
460      * Unregister corresponding to registerForLockedRecordsLoaded()
461      */
unregisterForLockedRecordsLoaded(Handler h)462     public void unregisterForLockedRecordsLoaded(Handler h) {
463         mLockedRecordsLoadedRegistrants.remove(h);
464     }
465 
466     /**
467      * Register to be notified when records are loaded for a network locked SIM
468      */
registerForNetworkLockedRecordsLoaded(Handler h, int what, Object obj)469     public void registerForNetworkLockedRecordsLoaded(Handler h, int what, Object obj) {
470         if (mDestroyed.get()) {
471             return;
472         }
473 
474         Registrant r = new Registrant(h, what, obj);
475         mNetworkLockedRecordsLoadedRegistrants.add(r);
476 
477         if (getNetworkLockedRecordsLoaded()) {
478             r.notifyRegistrant(new AsyncResult(null, null, null));
479         }
480     }
481 
482     /**
483      * Unregister corresponding to registerForLockedRecordsLoaded()
484      */
unregisterForNetworkLockedRecordsLoaded(Handler h)485     public void unregisterForNetworkLockedRecordsLoaded(Handler h) {
486         mNetworkLockedRecordsLoadedRegistrants.remove(h);
487     }
488 
registerForImsiReady(Handler h, int what, Object obj)489     public void registerForImsiReady(Handler h, int what, Object obj) {
490         if (mDestroyed.get()) {
491             return;
492         }
493 
494         Registrant r = new Registrant(h, what, obj);
495         mImsiReadyRegistrants.add(r);
496 
497         if (getIMSI() != null) {
498             r.notifyRegistrant(new AsyncResult(null, null, null));
499         }
500     }
unregisterForImsiReady(Handler h)501     public void unregisterForImsiReady(Handler h) {
502         mImsiReadyRegistrants.remove(h);
503     }
504 
registerForSpnUpdate(Handler h, int what, Object obj)505     public void registerForSpnUpdate(Handler h, int what, Object obj) {
506         if (mDestroyed.get()) {
507             return;
508         }
509 
510         Registrant r = new Registrant(h, what, obj);
511         mSpnUpdatedRegistrants.add(r);
512 
513         if (!TextUtils.isEmpty(mSpn)) {
514             r.notifyRegistrant(new AsyncResult(null, null, null));
515         }
516     }
unregisterForSpnUpdate(Handler h)517     public void unregisterForSpnUpdate(Handler h) {
518         mSpnUpdatedRegistrants.remove(h);
519     }
520 
registerForRecordsEvents(Handler h, int what, Object obj)521     public void registerForRecordsEvents(Handler h, int what, Object obj) {
522         Registrant r = new Registrant (h, what, obj);
523         mRecordsEventsRegistrants.add(r);
524 
525         /* Notify registrant of all the possible events. This is to make sure registrant is
526         notified even if event occurred in the past. */
527         r.notifyResult(EVENT_MWI);
528         r.notifyResult(EVENT_CFI);
529     }
530 
unregisterForRecordsEvents(Handler h)531     public void unregisterForRecordsEvents(Handler h) {
532         mRecordsEventsRegistrants.remove(h);
533     }
534 
registerForNewSms(Handler h, int what, Object obj)535     public void registerForNewSms(Handler h, int what, Object obj) {
536         Registrant r = new Registrant (h, what, obj);
537         mNewSmsRegistrants.add(r);
538     }
539 
unregisterForNewSms(Handler h)540     public void unregisterForNewSms(Handler h) {
541         mNewSmsRegistrants.remove(h);
542     }
543 
registerForNetworkSelectionModeAutomatic( Handler h, int what, Object obj)544     public void registerForNetworkSelectionModeAutomatic(
545             Handler h, int what, Object obj) {
546         Registrant r = new Registrant (h, what, obj);
547         mNetworkSelectionModeAutomaticRegistrants.add(r);
548     }
unregisterForNetworkSelectionModeAutomatic(Handler h)549     public void unregisterForNetworkSelectionModeAutomatic(Handler h) {
550         mNetworkSelectionModeAutomaticRegistrants.remove(h);
551     }
552 
553     /**
554      * Get the International Mobile Subscriber ID (IMSI) on a SIM
555      * for GSM, UMTS and like networks. Default is null if IMSI is
556      * not supported or unavailable.
557      *
558      * @return null if SIM is not yet ready or unavailable
559      */
getIMSI()560     public String getIMSI() {
561         if (mCarrierTestOverride.isInTestMode()) {
562             String fakeImsi = mCarrierTestOverride.getFakeIMSI();
563             if (fakeImsi != null) {
564                 return fakeImsi;
565             }
566         }
567         return mImsi;
568     }
569 
570     /**
571      * Update IMSI record and try to extract the PLMN information and notify registrants.
572      * @param inImsi the IMSI value
573      */
setImsi(String inImsi)574     public void setImsi(String inImsi) {
575         // Remove trailing F's if present in IMSI.
576         mImsi = IccUtils.stripTrailingFs(inImsi);
577         if (!Objects.equals(mImsi, inImsi)) {
578             loge("Invalid IMSI padding digits received.");
579         }
580 
581         if (TextUtils.isEmpty(mImsi)) mImsi = null;
582 
583         if (mImsi != null && !mImsi.matches("[0-9]+")) {
584             loge("Invalid non-numeric IMSI digits received.");
585             mImsi = null;
586         }
587 
588         // IMSI (MCC+MNC+MSIN) is at least 6 digits, but not more
589         // than 15 (and usually 15).
590         // This will also handle un-set IMSI records (all Fs)
591         if (mImsi != null && (mImsi.length() < 6 || mImsi.length() > 15)) {
592             loge("invalid IMSI " + mImsi);
593             mImsi = null;
594         }
595 
596         log("IMSI: mMncLength=" + mMncLength);
597 
598         if (mImsi != null && mImsi.length() >= 6) {
599             log("IMSI: " + mImsi.substring(0, 6) + Rlog.pii(VDBG, mImsi.substring(6)));
600         }
601 
602         // IMSI has changed so the PLMN might have changed as well
603         updateOperatorPlmn();
604 
605         mImsiReadyRegistrants.notifyRegistrants();
606     }
607 
updateOperatorPlmn()608     protected void updateOperatorPlmn() {
609         // In case of a test override, use the test IMSI
610         String imsi = getIMSI();
611 
612         if (imsi != null) {
613             // First try to guess the length based on a table of known 3-digit MNCs.
614             if (((mMncLength == UNKNOWN) || (mMncLength == 2)) && imsi.length() >= 6) {
615                 String mccmncCode = imsi.substring(0, 6);
616                 for (String mccmnc : MCCMNC_CODES_HAVING_3DIGITS_MNC) {
617                     if (mccmnc.equals(mccmncCode)) {
618                         mMncLength = 3;
619                         log("IMSI: setting1 mMncLength=" + mMncLength);
620                         break;
621                     }
622                 }
623             }
624 
625             // If still unknown, guess using the MCC.
626             if (mMncLength == UNKNOWN) {
627                 try {
628                     int mcc = Integer.parseInt(imsi.substring(0, 3));
629                     mMncLength = MccTable.smallestDigitsMccForMnc(mcc);
630                     log("setting2 mMncLength=" + mMncLength);
631                 } catch (NumberFormatException e) {
632                     loge("Corrupt IMSI! setting3 mMncLength=" + mMncLength);
633                 }
634             }
635 
636             if (mMncLength != UNKNOWN && mMncLength != UNINITIALIZED
637                     && imsi.length() >= 3 + mMncLength) {
638                 log("update mccmnc=" + imsi.substring(0, 3 + mMncLength));
639                 // finally have both the imsi and the mncLength and
640                 // can parse the imsi properly
641                 MccTable.updateMccMncConfiguration(mContext, imsi.substring(0, 3 + mMncLength));
642             }
643         }
644     }
645 
646     /**
647      * Get the Network Access ID (NAI) on a CSIM for CDMA like networks. Default is null if IMSI is
648      * not supported or unavailable.
649      *
650      * @return null if NAI is not yet ready or unavailable
651      */
getNAI()652     public String getNAI() {
653         return null;
654     }
655 
getMsisdnNumber()656     public String getMsisdnNumber() {
657         return mMsisdn;
658     }
659 
660     /**
661      * Get the Group Identifier Level 1 (GID1) on a SIM for GSM.
662      * @return null if SIM is not yet ready
663      */
getGid1()664     public String getGid1() {
665         if (mCarrierTestOverride.isInTestMode()) {
666             String fakeGid1 = mCarrierTestOverride.getFakeGid1();
667             if (fakeGid1 != null) {
668                 return fakeGid1;
669             }
670         }
671         return mGid1;
672     }
673 
674     /**
675      * Get the Group Identifier Level 2 (GID2) on a SIM.
676      * @return null if SIM is not yet ready
677      */
getGid2()678     public String getGid2() {
679         if (mCarrierTestOverride.isInTestMode()) {
680             String fakeGid2 = mCarrierTestOverride.getFakeGid2();
681             if (fakeGid2 != null) {
682                 return fakeGid2;
683             }
684         }
685         return mGid2;
686     }
687 
688     /**
689      * Get the PLMN network name on a SIM.
690      * @return null if SIM is not yet ready
691      */
getPnnHomeName()692     public String getPnnHomeName() {
693         if (mCarrierTestOverride.isInTestMode()) {
694             String fakePnnHomeName = mCarrierTestOverride.getFakePnnHomeName();
695             if (fakePnnHomeName != null) {
696                 return fakePnnHomeName;
697             }
698         }
699         return mPnnHomeName;
700     }
701 
setMsisdnNumber(String alphaTag, String number, Message onComplete)702     public void setMsisdnNumber(String alphaTag, String number,
703             Message onComplete) {
704         loge("setMsisdn() should not be invoked on base IccRecords");
705         // synthesize a "File Not Found" exception and return it
706         AsyncResult.forMessage(onComplete).exception =
707             (new IccIoResult(0x6A, 0x82, (byte[]) null)).getException();
708         onComplete.sendToTarget();
709     }
710 
getMsisdnAlphaTag()711     public String getMsisdnAlphaTag() {
712         return mMsisdnTag;
713     }
714 
getVoiceMailNumber()715     public String getVoiceMailNumber() {
716         return mVoiceMailNum;
717     }
718 
719     /**
720      * Return Service Provider Name stored in SIM (EF_SPN=0x6F46) or in RUIM (EF_RUIM_SPN=0x6F41).
721      *
722      * @return null if SIM is not yet ready or no RUIM entry
723      */
getServiceProviderName()724     public String getServiceProviderName() {
725         if (mCarrierTestOverride.isInTestMode()) {
726             String fakeSpn = mCarrierTestOverride.getFakeSpn();
727             if (fakeSpn != null) {
728                 return fakeSpn;
729             }
730         }
731         return mSpn;
732     }
733 
734     /**
735      * Return Service Provider Name stored in SIM (EF_SPN=0x6F46) or in RUIM (EF_RUIM_SPN=0x6F41) or
736      * the brand override. The brand override has higher priority than the SPN from SIM.
737      *
738      * @return service provider name.
739      */
740     @Nullable
getServiceProviderNameWithBrandOverride()741     public String getServiceProviderNameWithBrandOverride() {
742         if (mParentApp != null && mParentApp.getUiccProfile() != null) {
743             String brandOverride = mParentApp.getUiccProfile().getOperatorBrandOverride();
744             if (!TextUtils.isEmpty(brandOverride)) {
745                 return brandOverride;
746             }
747         }
748         return mSpn;
749     }
750 
setServiceProviderName(String spn)751     protected void setServiceProviderName(String spn) {
752         if (!TextUtils.equals(mSpn, spn)) {
753             mSpn = spn != null ? spn.trim() : null;
754             mSpnUpdatedRegistrants.notifyRegistrants();
755         }
756     }
757 
758     /**
759      * Set voice mail number to SIM record
760      *
761      * The voice mail number can be stored either in EF_MBDN (TS 51.011) or
762      * EF_MAILBOX_CPHS (CPHS 4.2)
763      *
764      * If EF_MBDN is available, store the voice mail number to EF_MBDN
765      *
766      * If EF_MAILBOX_CPHS is enabled, store the voice mail number to EF_CHPS
767      *
768      * So the voice mail number will be stored in both EFs if both are available
769      *
770      * Return error only if both EF_MBDN and EF_MAILBOX_CPHS fail.
771      *
772      * When the operation is complete, onComplete will be sent to its handler
773      *
774      * @param alphaTag alpha-tagging of the dailing nubmer (upto 10 characters)
775      * @param voiceNumber dailing nubmer (upto 20 digits)
776      *        if the number is start with '+', then set to international TOA
777      * @param onComplete
778      *        onComplete.obj will be an AsyncResult
779      *        ((AsyncResult)onComplete.obj).exception == null on success
780      *        ((AsyncResult)onComplete.obj).exception != null on fail
781      */
setVoiceMailNumber(String alphaTag, String voiceNumber, Message onComplete)782     public abstract void setVoiceMailNumber(String alphaTag, String voiceNumber,
783             Message onComplete);
784 
getVoiceMailAlphaTag()785     public String getVoiceMailAlphaTag() {
786         return mVoiceMailTag;
787     }
788 
789     /**
790      * Sets the SIM voice message waiting indicator records
791      * @param line GSM Subscriber Profile Number, one-based. Only '1' is supported
792      * @param countWaiting The number of messages waiting, if known. Use
793      *                     -1 to indicate that an unknown number of
794      *                      messages are waiting
795      */
setVoiceMessageWaiting(int line, int countWaiting)796     public abstract void setVoiceMessageWaiting(int line, int countWaiting);
797 
798     /**
799      * Called by GsmCdmaPhone to update VoiceMail count
800      */
getVoiceMessageCount()801     public abstract int getVoiceMessageCount();
802 
803     /**
804      * Called by STK Service when REFRESH is received.
805      * @param fileChanged indicates whether any files changed
806      * @param fileList if non-null, a list of EF files that changed
807      */
onRefresh(boolean fileChanged, int[] fileList)808     public abstract void onRefresh(boolean fileChanged, int[] fileList);
809 
getRecordsLoaded()810     public boolean getRecordsLoaded() {
811         return mRecordsToLoad == 0 && mRecordsRequested;
812     }
813 
getLockedRecordsLoaded()814     protected boolean getLockedRecordsLoaded() {
815         return mRecordsToLoad == 0
816                 && mLockedRecordsReqReason == LOCKED_RECORDS_REQ_REASON_LOCKED;
817     }
818 
getNetworkLockedRecordsLoaded()819     protected boolean getNetworkLockedRecordsLoaded() {
820         return mRecordsToLoad == 0
821                 && mLockedRecordsReqReason == LOCKED_RECORDS_REQ_REASON_NETWORK_LOCKED;
822     }
823 
824     //***** Overridden from Handler
825     @Override
handleMessage(Message msg)826     public void handleMessage(Message msg) {
827         AsyncResult ar;
828 
829         switch (msg.what) {
830             case EVENT_APP_READY:
831                 mLockedRecordsReqReason = LOCKED_RECORDS_REQ_REASON_NONE;
832                 onReady();
833                 break;
834 
835             case EVENT_APP_DETECTED:
836                 mLockedRecordsReqReason = LOCKED_RECORDS_REQ_REASON_NONE;
837                 onDetected();
838                 break;
839 
840             case EVENT_APP_LOCKED:
841                 mLockedRecordsReqReason = LOCKED_RECORDS_REQ_REASON_LOCKED;
842                 onLocked();
843                 break;
844 
845             case EVENT_APP_NETWORK_LOCKED:
846                 mLockedRecordsReqReason = LOCKED_RECORDS_REQ_REASON_NETWORK_LOCKED;
847                 onLocked();
848                 break;
849 
850             case EVENT_GET_ICC_RECORD_DONE:
851                 try {
852                     ar = (AsyncResult) msg.obj;
853                     IccRecordLoaded recordLoaded = (IccRecordLoaded) ar.userObj;
854                     if (DBG) log(recordLoaded.getEfName() + " LOADED");
855 
856                     if (ar.exception != null) {
857                         loge("Record Load Exception: " + ar.exception);
858                     } else {
859                         recordLoaded.onRecordLoaded(ar);
860                     }
861                 }catch (RuntimeException exc) {
862                     // I don't want these exceptions to be fatal
863                     loge("Exception parsing SIM record: " + exc);
864                 } finally {
865                     // Count up record load responses even if they are fails
866                     onRecordLoaded();
867                 }
868                 break;
869 
870             case EVENT_REFRESH:
871                 ar = (AsyncResult)msg.obj;
872                 if (DBG) log("Card REFRESH occurred: ");
873                 if (ar.exception == null) {
874                     handleRefresh((IccRefreshResponse)ar.result);
875                 } else {
876                     loge("Icc refresh Exception: " + ar.exception);
877                 }
878                 break;
879 
880             case EVENT_AKA_AUTHENTICATE_DONE:
881                 ar = (AsyncResult) msg.obj;
882                 AuthAsyncResponse rsp = (AuthAsyncResponse) ar.userObj;
883                 if (DBG) log("EVENT_AKA_AUTHENTICATE_DONE");
884 
885                 synchronized (rsp) {
886                     if (ar.exception != null) {
887                         rsp.exception = ar.exception;
888                         loge("Exception ICC SIM AKA: " + ar.exception);
889                     } else if (ar.result == null) {
890                         rsp.exception = new NullPointerException(
891                                 "Null SIM authentication response");
892                         loge("EVENT_AKA_AUTHENTICATE_DONE: null response");
893                     } else {
894                         try {
895                             rsp.authRsp = (IccIoResult) ar.result;
896                             if (VDBG) log("ICC SIM AKA: authRsp = " + rsp.authRsp);
897                         } catch (ClassCastException e) {
898                             rsp.exception = e;
899                             loge("Failed to parse ICC SIM AKA contents: " + e);
900                         }
901                     }
902                     rsp.notifyAll();
903                 }
904 
905                 break;
906 
907             case EVENT_GET_SMS_RECORD_SIZE_DONE:
908                 ar = (AsyncResult) msg.obj;
909 
910                 if (ar.exception != null) {
911                     onRecordLoaded();
912                     loge("Exception in EVENT_GET_SMS_RECORD_SIZE_DONE " + ar.exception);
913                     break;
914                 }
915 
916                 int[] recordSize = (int[])ar.result;
917                 try {
918                     // recordSize[0]  is the record length
919                     // recordSize[1]  is the total length of the EF file
920                     // recordSize[2]  is the number of records in the EF file
921                     mSmsCountOnIcc = recordSize[2];
922                     log("EVENT_GET_SMS_RECORD_SIZE_DONE Size " + recordSize[0]
923                             + " total " + recordSize[1]
924                                     + " record " + recordSize[2]);
925                 } catch (ArrayIndexOutOfBoundsException exc) {
926                     mSmsCountOnIcc = -1;
927                     loge("ArrayIndexOutOfBoundsException in EVENT_GET_SMS_RECORD_SIZE_DONE: "
928                             + exc.toString());
929                 } finally {
930                     onRecordLoaded();
931                 }
932                 break;
933 
934             default:
935                 super.handleMessage(msg);
936         }
937     }
938 
939     /**
940      * Returns the SIM language derived from the EF-LI and EF-PL sim records.
941      */
getSimLanguage()942     public String getSimLanguage() {
943         return mPrefLang;
944     }
945 
setSimLanguage(byte[] efLi, byte[] efPl)946     protected void setSimLanguage(byte[] efLi, byte[] efPl) {
947         String[] locales = mContext.getAssets().getLocales();
948         try {
949             mPrefLang = findBestLanguage(efLi, locales);
950         } catch (UnsupportedEncodingException uee) {
951             log("Unable to parse EF-LI: " + Arrays.toString(efLi));
952         }
953 
954         if (mPrefLang == null) {
955             try {
956                 mPrefLang = findBestLanguage(efPl, locales);
957             } catch (UnsupportedEncodingException uee) {
958                 log("Unable to parse EF-PL: " + Arrays.toString(efLi));
959             }
960         }
961     }
962 
findBestLanguage(byte[] languages, String[] locales)963     protected static String findBestLanguage(byte[] languages, String[] locales)
964             throws UnsupportedEncodingException {
965         if ((languages == null) || (locales == null)) return null;
966 
967         // Each 2-bytes consists of one language
968         for (int i = 0; (i + 1) < languages.length; i += 2) {
969             String lang = new String(languages, i, 2, "ISO-8859-1");
970             for (int j = 0; j < locales.length; j++) {
971                 if (locales[j] != null && locales[j].length() >= 2 &&
972                         locales[j].substring(0, 2).equalsIgnoreCase(lang)) {
973                     return lang;
974                 }
975             }
976         }
977 
978         // no match found. return null
979         return null;
980     }
981 
handleFileUpdate(int efid)982     protected abstract void handleFileUpdate(int efid);
983 
handleRefresh(IccRefreshResponse refreshResponse)984     protected void handleRefresh(IccRefreshResponse refreshResponse){
985         if (refreshResponse == null) {
986             if (DBG) log("handleRefresh received without input");
987             return;
988         }
989 
990         if (!TextUtils.isEmpty(refreshResponse.aid) &&
991                 !refreshResponse.aid.equals(mParentApp.getAid())) {
992             // This is for different app. Ignore.
993             return;
994         }
995 
996         switch (refreshResponse.refreshResult) {
997             case IccRefreshResponse.REFRESH_RESULT_FILE_UPDATE:
998                 if (DBG) log("handleRefresh with SIM_FILE_UPDATED");
999                 handleFileUpdate(refreshResponse.efId);
1000                 break;
1001             default:
1002                 // unknown refresh operation
1003                 if (DBG) log("handleRefresh with unknown operation");
1004                 break;
1005         }
1006     }
1007 
onRecordLoaded()1008     protected abstract void onRecordLoaded();
1009 
onAllRecordsLoaded()1010     protected abstract void onAllRecordsLoaded();
1011 
1012     /**
1013      * Retrieves the SPN/PLMN display condition from UICC.
1014      *
1015      * Display of service provider name is required when registered PLMN is neither HPLMN nor a PLMN
1016      * in the service provider PLMN list(EF_SPDI).
1017      *
1018      * Display of PLMN network name is required when registered PLMN is either HPLMN or a PLMN in
1019      * the service provider PLMN list(EF_SPDI).
1020      *
1021      * Reference: 3GPP TS 131.102 section 4.2.12 EF_SPN Display Condition
1022      *
1023      * @return a bitmask represent the carrier name display condition.
1024      */
1025     @CarrierNameDisplayConditionBitmask
getCarrierNameDisplayCondition()1026     public int getCarrierNameDisplayCondition() {
1027         return mCarrierNameDisplayCondition;
1028     }
1029 
1030     /**
1031      * Retrieves the service provider display information. This is a list of PLMNs in which the
1032      * service provider name shall be displayed.
1033      *
1034      * Reference: 3GPP TS 131.102 section 4.2.66 EF_SPDI
1035      *
1036      * @return a list of PLMN(mcc+mnc) if EF_SPDI is existed, otherwise return null.
1037      */
getServiceProviderDisplayInformation()1038     public String[] getServiceProviderDisplayInformation() {
1039         return mSpdi;
1040     }
1041 
1042     /**
1043      * Get home PLMN list.
1044      *
1045      * @see #getEhplmns()
1046      * @see #getServiceProviderDisplayInformation()
1047      *
1048      * @return a list of HPLMN if existed, otherwise return null.
1049      */
getHomePlmns()1050     public String[] getHomePlmns() {
1051         // hplmn from imsi.
1052         String hplmn = getOperatorNumeric();
1053 
1054         // hplmn from ehplmn list.
1055         String[] hplmns = getEhplmns();
1056 
1057         // plmn from ef_spdi.
1058         String[] spdi = getServiceProviderDisplayInformation();
1059 
1060         // Use the plmn from imsi as the hplmn if Ehplmn not present.
1061         if (ArrayUtils.isEmpty(hplmns)) {
1062             hplmns = new String[] {hplmn};
1063         }
1064 
1065         if (!ArrayUtils.isEmpty(spdi)) {
1066             hplmns = ArrayUtils.concatElements(String.class, hplmns, spdi);
1067         }
1068         // If hplmns don't contain hplmn, we need to add hplmn to hplmns
1069         hplmns = ArrayUtils.appendElement(String.class, hplmns, hplmn);
1070         return hplmns;
1071     }
1072 
1073     /**
1074      * Return true if "Restriction of menu options for manual PLMN selection"
1075      * bit is set or EF_CSP data is unavailable, return false otherwise.
1076      * Generally used for GSM/UMTS and the like SIMs.
1077      */
isCspPlmnEnabled()1078     public boolean isCspPlmnEnabled() {
1079         return false;
1080     }
1081 
1082     /**
1083      * Returns the 5 or 6 digit MCC/MNC of the operator that
1084      * provided the SIM card. Returns null of SIM is not yet ready
1085      * or is not valid for the type of IccCard. Generally used for
1086      * GSM/UMTS and the like SIMS
1087      */
getOperatorNumeric()1088     public String getOperatorNumeric() {
1089         return null;
1090     }
1091 
1092     /**
1093      * Get the current Voice call forwarding flag for GSM/UMTS and the like SIMs
1094      *
1095      * @return CALL_FORWARDING_STATUS_XXX (DISABLED/ENABLED/UNKNOWN)
1096      */
getVoiceCallForwardingFlag()1097     public int getVoiceCallForwardingFlag() {
1098         return CALL_FORWARDING_STATUS_UNKNOWN;
1099     }
1100 
1101     /**
1102      * Set the voice call forwarding flag for GSM/UMTS and the like SIMs
1103      *
1104      * @param line to enable/disable
1105      * @param enable
1106      * @param number to which CFU is enabled
1107      */
setVoiceCallForwardingFlag(int line, boolean enable, String number)1108     public void setVoiceCallForwardingFlag(int line, boolean enable, String number) {
1109     }
1110 
1111     /**
1112      * Indicates wether the ICC records have been loaded or not
1113      *
1114      * @return true if the records have been loaded, false otherwise.
1115      */
isLoaded()1116     public boolean isLoaded() {
1117         return mLoaded.get();
1118     }
1119 
1120     /**
1121      * Indicates wether SIM is in provisioned state or not.
1122      * Overridden only if SIM can be dynamically provisioned via OTA.
1123      *
1124      * @return true if provisioned
1125      */
isProvisioned()1126     public boolean isProvisioned () {
1127         return true;
1128     }
1129 
1130     /**
1131      * Write string to log file
1132      *
1133      * @param s is the string to write
1134      */
log(String s)1135     protected abstract void log(String s);
1136 
1137     /**
1138      * Write error string to log file.
1139      *
1140      * @param s is the string to write
1141      */
loge(String s)1142     protected abstract void loge(String s);
1143 
1144     /**
1145      * @return String array containing EHPLMNs associated with the card.
1146      */
getEhplmns()1147     public String[] getEhplmns() {
1148         return mEhplmns;
1149     }
1150 
1151     /**
1152      * @return String array containing PLMN from HplmnActRecord.
1153      */
getPlmnsFromHplmnActRecord()1154     public String[] getPlmnsFromHplmnActRecord() {
1155         if (mHplmnActRecords == null) return null;
1156         String[] hplmns = new String[mHplmnActRecords.length];
1157         for (int i = 0; i < mHplmnActRecords.length; i++) {
1158             hplmns[i] = mHplmnActRecords[i].plmn;
1159         }
1160         return hplmns;
1161     }
1162 
1163     /**
1164      * Return an interface to retrieve the ISIM records for IMS, if available.
1165      * @return the interface to retrieve the ISIM records, or null if not supported
1166      */
getIsimRecords()1167     public IsimRecords getIsimRecords() {
1168         return null;
1169     }
1170 
getUsimServiceTable()1171     public UsimServiceTable getUsimServiceTable() {
1172         return null;
1173     }
1174 
1175     /**
1176      * Solve authentication leakage issue. See b/147463955.
1177      * Returns the response of the SIM application on the UICC to authentication
1178      * challenge/response algorithm. The data string and challenge response are
1179      * Base64 encoded Strings.
1180      * Can support EAP-SIM, EAP-AKA with results encoded per 3GPP TS 31.102.
1181      *
1182      * @param authContext parameter P2 that specifies the authentication context
1183      * per 3GPP TS 31.102 (Section 7.1.2)
1184      * @param data authentication challenge data
1185      * @return challenge response
1186      */
1187     @Nullable
getIccSimChallengeResponse(int authContext, String data)1188     public String getIccSimChallengeResponse(int authContext, String data) {
1189         if (VDBG) log("getIccSimChallengeResponse:");
1190 
1191         //final here is for defensive copy.
1192         final CommandsInterface ci = mCi;
1193         final UiccCardApplication parentApp = mParentApp;
1194         if (ci == null || parentApp == null) {
1195             loge("getIccSimChallengeResponse: Fail, ci or parentApp is null");
1196             return null;
1197         }
1198 
1199         AuthAsyncResponse rsp = new AuthAsyncResponse();
1200 
1201         synchronized (rsp) {
1202             ci.requestIccSimAuthentication(authContext, data, parentApp.getAid(),
1203                     obtainMessage(EVENT_AKA_AUTHENTICATE_DONE, 0, 0, rsp));
1204             //TODO: factor wait with timeout into a separate method
1205             final long startTime = SystemClock.elapsedRealtime();
1206             do {
1207                 try {
1208                     long sleepTime = startTime + ICC_SIM_CHALLENGE_TIMEOUT_MILLIS
1209                             - SystemClock.elapsedRealtime();
1210                     if (sleepTime > 0) rsp.wait(sleepTime);
1211                 } catch (InterruptedException e) {
1212                     Rlog.w("IccRecords", "getIccSimChallengeResponse: InterruptedException.");
1213                 }
1214             } while (SystemClock.elapsedRealtime() - startTime < ICC_SIM_CHALLENGE_TIMEOUT_MILLIS
1215                     && rsp.authRsp == null && rsp.exception == null);
1216 
1217             if (SystemClock.elapsedRealtime() - startTime >= ICC_SIM_CHALLENGE_TIMEOUT_MILLIS
1218                     && rsp.authRsp == null && rsp.exception == null) {
1219                 loge("getIccSimChallengeResponse timeout!");
1220                 return null;
1221             }
1222 
1223             if (rsp.exception != null) {
1224                 loge("getIccSimChallengeResponse exception: " + rsp.exception);
1225                 //TODO: propagate better exceptions up to the user now that we have them available
1226                 //in the call stack.
1227                 return null;
1228             }
1229 
1230             if (rsp.authRsp == null) {
1231                 loge("getIccSimChallengeResponse: No authentication response");
1232                 return null;
1233             }
1234         }
1235         if (VDBG) log("getIccSimChallengeResponse: return rsp.authRsp");
1236 
1237         return rsp.authRsp.payload != null ? new String(rsp.authRsp.payload) : null;
1238     }
1239 
1240     /**
1241      * Convert the spn display condition to a bitmask
1242      * {@link com.android.internal.telephony.uicc.IccRecords.CarrierNameDisplayConditionBitmask}.
1243      *
1244      * b1 is the last bit of the display condition which is used to determine whether display of
1245      * PLMN network name is required when registered PLMN is **either** HPLMN or a PLMN in the
1246      * service provider PLMN list.
1247      *
1248      * b2 is the second last bit of the display condtion which is used to determine
1249      * whether display of Service Provider Name is required when registered PLMN is
1250      * **neither** HPLMN nor PLMN in the service provider PLMN list.
1251      *
1252      * Reference: 3GPP TS 31.102 section 4.2.12 EF_SPN
1253      *
1254      * @return a carrier name display condtion bitmask.
1255      */
1256     @CarrierNameDisplayConditionBitmask
convertSpnDisplayConditionToBitmask(int condition)1257     public static int convertSpnDisplayConditionToBitmask(int condition) {
1258         int carrierNameDisplayCondition = 0;
1259         // b1 = 0: display of registered PLMN name not required when registered PLMN is
1260         // either HPLMN or a PLMN in the service provider PLMN list.
1261         // b1 = 1: display of registered PLMN name required when registered PLMN is
1262         // either HPLMN or a PLMN in the service provider PLMN list.
1263         if ((condition & 0x1) == 0x1) {
1264             carrierNameDisplayCondition |= CARRIER_NAME_DISPLAY_CONDITION_BITMASK_PLMN;
1265         }
1266 
1267         // b2 = 0: display of the service provider name is **required** when registered
1268         // PLMN is neither HPLMN nor a PLMN in the service provider PLMN list.
1269         // b2 = 1: display of the servier provider name is **not required** when
1270         // registered PLMN is neither HPLMN nor PLMN in the service provider PLMN list.
1271         if ((condition & 0x2) == 0) {
1272             carrierNameDisplayCondition |= CARRIER_NAME_DISPLAY_CONDITION_BITMASK_SPN;
1273         }
1274 
1275         return carrierNameDisplayCondition;
1276     }
1277 
1278     /**
1279      * Get SMS capacity count on ICC card.
1280      */
getSmsCapacityOnIcc()1281     public int getSmsCapacityOnIcc() {
1282         if (DBG) log("getSmsCapacityOnIcc: " + mSmsCountOnIcc);
1283         return mSmsCountOnIcc;
1284     }
1285 
dump(FileDescriptor fd, PrintWriter pw, String[] args)1286     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1287         pw.println("IccRecords: " + this);
1288         pw.println(" mDestroyed=" + mDestroyed);
1289         pw.println(" mCi=" + mCi);
1290         pw.println(" mFh=" + mFh);
1291         pw.println(" mParentApp=" + mParentApp);
1292         pw.println(" recordsLoadedRegistrants: size=" + mRecordsLoadedRegistrants.size());
1293         for (int i = 0; i < mRecordsLoadedRegistrants.size(); i++) {
1294             pw.println("  recordsLoadedRegistrants[" + i + "]="
1295                     + ((Registrant)mRecordsLoadedRegistrants.get(i)).getHandler());
1296         }
1297         pw.println(" mLockedRecordsLoadedRegistrants: size="
1298                 + mLockedRecordsLoadedRegistrants.size());
1299         for (int i = 0; i < mLockedRecordsLoadedRegistrants.size(); i++) {
1300             pw.println("  mLockedRecordsLoadedRegistrants[" + i + "]="
1301                     + ((Registrant) mLockedRecordsLoadedRegistrants.get(i)).getHandler());
1302         }
1303         pw.println(" mNetworkLockedRecordsLoadedRegistrants: size="
1304                 + mNetworkLockedRecordsLoadedRegistrants.size());
1305         for (int i = 0; i < mNetworkLockedRecordsLoadedRegistrants.size(); i++) {
1306             pw.println("  mLockedRecordsLoadedRegistrants[" + i + "]="
1307                     + ((Registrant) mNetworkLockedRecordsLoadedRegistrants.get(i)).getHandler());
1308         }
1309         pw.println(" mImsiReadyRegistrants: size=" + mImsiReadyRegistrants.size());
1310         for (int i = 0; i < mImsiReadyRegistrants.size(); i++) {
1311             pw.println("  mImsiReadyRegistrants[" + i + "]="
1312                     + ((Registrant)mImsiReadyRegistrants.get(i)).getHandler());
1313         }
1314         pw.println(" mRecordsEventsRegistrants: size=" + mRecordsEventsRegistrants.size());
1315         for (int i = 0; i < mRecordsEventsRegistrants.size(); i++) {
1316             pw.println("  mRecordsEventsRegistrants[" + i + "]="
1317                     + ((Registrant)mRecordsEventsRegistrants.get(i)).getHandler());
1318         }
1319         pw.println(" mNewSmsRegistrants: size=" + mNewSmsRegistrants.size());
1320         for (int i = 0; i < mNewSmsRegistrants.size(); i++) {
1321             pw.println("  mNewSmsRegistrants[" + i + "]="
1322                     + ((Registrant)mNewSmsRegistrants.get(i)).getHandler());
1323         }
1324         pw.println(" mNetworkSelectionModeAutomaticRegistrants: size="
1325                 + mNetworkSelectionModeAutomaticRegistrants.size());
1326         for (int i = 0; i < mNetworkSelectionModeAutomaticRegistrants.size(); i++) {
1327             pw.println("  mNetworkSelectionModeAutomaticRegistrants[" + i + "]="
1328                     + ((Registrant)mNetworkSelectionModeAutomaticRegistrants.get(i)).getHandler());
1329         }
1330         pw.println(" mRecordsRequested=" + mRecordsRequested);
1331         pw.println(" mLockedRecordsReqReason=" + mLockedRecordsReqReason);
1332         pw.println(" mRecordsToLoad=" + mRecordsToLoad);
1333         pw.println(" mRdnCache=" + mAdnCache);
1334 
1335         String iccIdToPrint = SubscriptionInfo.givePrintableIccid(mFullIccId);
1336         pw.println(" iccid=" + iccIdToPrint);
1337         pw.println(" mMsisdn=" + Rlog.pii(VDBG, mMsisdn));
1338         pw.println(" mMsisdnTag=" + mMsisdnTag);
1339         pw.println(" mVoiceMailNum=" + Rlog.pii(VDBG, mVoiceMailNum));
1340         pw.println(" mVoiceMailTag=" + mVoiceMailTag);
1341         pw.println(" mNewVoiceMailNum=" + Rlog.pii(VDBG, mNewVoiceMailNum));
1342         pw.println(" mNewVoiceMailTag=" + mNewVoiceMailTag);
1343         pw.println(" mIsVoiceMailFixed=" + mIsVoiceMailFixed);
1344         pw.println(" mImsi=" + ((mImsi != null) ?
1345                 mImsi.substring(0, 6) + Rlog.pii(VDBG, mImsi.substring(6)) : "null"));
1346         if (mCarrierTestOverride.isInTestMode()) {
1347             pw.println(" mFakeImsi=" + mCarrierTestOverride.getFakeIMSI());
1348         }
1349         pw.println(" mMncLength=" + mMncLength);
1350         pw.println(" mMailboxIndex=" + mMailboxIndex);
1351         pw.println(" mSpn=" + mSpn);
1352         if (mCarrierTestOverride.isInTestMode()) {
1353             pw.println(" mFakeSpn=" + mCarrierTestOverride.getFakeSpn());
1354         }
1355         pw.flush();
1356     }
1357 
1358     /**
1359      * Operator PLMN information. This contains the location area information or tracking area
1360      * that are used to associate a specific name contained in EF_PNN.
1361      *
1362      * Reference: 3GPP TS 31.102 section 4.2.59 EF_OPL
1363      */
1364     public static final class OperatorPlmnInfo {
1365         // PLMN numeric that may contains wildcard character ".".
1366         // For example, the pattern "123..." could match all PLMN which mcc is 123.
1367         public final String plmnNumericPattern;
1368 
1369         public final int lacTacStart;
1370         public final int lacTacEnd;
1371 
1372         public final int plmnNetworkNameIndex;
OperatorPlmnInfo(String plmnNumericPattern, int lacTacStart, int lacTacEnd, int plmnNetworkNameIndex)1373         public OperatorPlmnInfo(String plmnNumericPattern, int lacTacStart, int lacTacEnd,
1374                                 int plmnNetworkNameIndex) {
1375             this.plmnNumericPattern = plmnNumericPattern;
1376             this.lacTacStart = lacTacStart;
1377             this.lacTacEnd = lacTacEnd;
1378             this.plmnNetworkNameIndex = plmnNetworkNameIndex;
1379         }
1380 
1381         @Override
toString()1382         public String toString() {
1383             return "{ plmnNumericPattern = " + plmnNumericPattern
1384                     + "lacTacStart = " + lacTacStart
1385                     + "lacTacEnd = " + lacTacEnd
1386                     + "plmnNetworkNameIndex = " + plmnNetworkNameIndex
1387                     + " }";
1388         }
1389     }
1390 
1391     /**
1392      * Full and short version of PLMN network name.
1393      */
1394     public static final class PlmnNetworkName {
1395         public final String fullName;
1396         public final String shortName;
1397 
PlmnNetworkName(String fullName, String shortName)1398         public PlmnNetworkName(String fullName, String shortName) {
1399             this.fullName = fullName;
1400             this.shortName = shortName;
1401         }
1402 
1403         @Override
toString()1404         public String toString() {
1405             return "{ fullName = " + fullName + " shortName = " + shortName + " }";
1406         }
1407     }
1408 }
1409