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