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