• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 android.telephony.mockmodem;
18 
19 import android.content.Context;
20 import android.hardware.radio.sim.AppStatus;
21 import android.hardware.radio.sim.PinState;
22 import android.text.TextUtils;
23 import android.util.Log;
24 import android.util.Xml;
25 
26 import org.xmlpull.v1.XmlPullParser;
27 
28 import java.io.InputStream;
29 import java.util.ArrayList;
30 import java.util.Collections;
31 import java.util.HashMap;
32 import java.util.List;
33 import java.util.Locale;
34 import java.util.Map;
35 
36 public class MockSimService {
37     /* Support SIM card identify */
38     public static final int MOCK_SIM_PROFILE_ID_DEFAULT = 0; // SIM Absent
39     public static final int MOCK_SIM_PROFILE_ID_TWN_CHT = 1;
40     public static final int MOCK_SIM_PROFILE_ID_TWN_FET = 2;
41     public static final int MOCK_SIM_PROFILE_ID_US_FI = 3;
42     public static final int MOCK_SIM_PROFILE_ID_MAX = 4;
43 
44     /* Type of SIM IO command */
45     public static final int COMMAND_READ_BINARY = 0xb0;
46     public static final int COMMAND_GET_RESPONSE = 0xc0;
47     public static final int COMMAND_SELECT = 0xa4;
48 
49     /* EF Id definition */
50     public static final int EF_ICCID = 0x2FE2;
51     public static final int EF_IMSI = 0x6F07;
52     public static final int EF_GID1 = 0x6F3E;
53 
54     /* SIM profile XML TAG definition */
55     private static final String MOCK_SIM_TAG = "MockSim";
56     private static final String MOCK_SIM_PROFILE_TAG = "MockSimProfile";
57     private static final String MOCK_PIN_PROFILE_TAG = "PinProfile";
58     private static final String MOCK_PIN1_STATE_TAG = "Pin1State";
59     private static final String MOCK_PIN2_STATE_TAG = "Pin2State";
60     private static final String MOCK_FACILITY_LOCK_TAG = "FacilityLock";
61     private static final String MOCK_FACILITY_LOCK_FD_TAG = "FD";
62     private static final String MOCK_FACILITY_LOCK_SC_TAG = "SC";
63     private static final String MOCK_MF_TAG = "MF";
64     private static final String MOCK_EF_TAG = "EF";
65     private static final String MOCK_EF_DIR_TAG = "EFDIR";
66     private static final String MOCK_ADF_TAG = "ADF";
67     // ADF used for SIM-IO through logical channel (iccOpenLogicalChannel) instead of iccIoForApp
68     // with which MOCK_ADF_TAG is used
69     private static final String MOCK_ADFLC_TAG = "ADF-LC";
70     // Each tag represent a command-respond APDU IO
71     private static final String MOCK_IO_TAG = "IO";
72 
73     /* Support SIM slot */
74     private static final int MOCK_SIM_SLOT_1 = 0;
75     private static final int MOCK_SIM_SLOT_2 = 1;
76     private static final int MOCK_SIM_SLOT_3 = 2;
77     public static final int MOCK_SIM_SLOT_MIN = 1;
78     public static final int MOCK_SIM_SLOT_MAX = 3;
79 
80     /* Default value definition */
81     private static final int MOCK_SIM_DEFAULT_SLOTID = MOCK_SIM_SLOT_1;
82     private static final int DEFAULT_NUM_OF_SIM_APP = 0;
83     private static final int DEFAULT_GSM_APP_IDX = -1;
84     private static final int DEFAULT_CDMA_APP_IDX = -1;
85     private static final int DEFAULT_IMS_APP_IDX = -1;
86     private static final int DEFAULT_NUM_OF_SIM_PORT_INFO = 1;
87     // SIM1 slot status - physical SIM
88     private static final int DEFAULT_SIM1_PROFILE_ID = MOCK_SIM_PROFILE_ID_DEFAULT;
89     private static final boolean DEFAULT_SIM1_CARD_PRESENT = false;
90     private static final String DEFAULT_SIM1_ATR = "";
91     private static final String DEFAULT_SIM1_EID = "";
92     private static final boolean DEFAULT_SIM1_PORT_ACTIVE = true;
93     private static final int DEFAULT_SIM1_PORT_ID = 0;
94     private static final int DEFAULT_SIM1_LOGICAL_SLOT_ID = 0;
95     private static final int DEFAULT_SIM1_UNIVERSAL_PIN_STATE = PinState.UNKNOWN;
96     // SIM2 slot status - eSIM
97     private static final int DEFAULT_SIM2_PROFILE_ID = MOCK_SIM_PROFILE_ID_DEFAULT;
98     private static final boolean DEFAULT_SIM2_CARD_PRESENT = true;
99     private static final String DEFAULT_SIM2_ATR =
100             "3B9F97C00A3FC6828031E073FE211F65D002341512810F51";
101     private static final String DEFAULT_SIM2_EID = "89033023426200000000005430099507";
102     private static final boolean DEFAULT_SIM2_PORT_ACTIVE = true;
103     private static final int DEFAULT_SIM2_PORT_ID = 0;
104     private static final int DEFAULT_SIM2_LOGICAL_SLOT_ID = 1;
105     private static final int DEFAULT_SIM2_UNIVERSAL_PIN_STATE = PinState.DISABLED;
106     // SIM3 slot status - eSIM
107     private static final int DEFAULT_SIM3_PROFILE_ID = MOCK_SIM_PROFILE_ID_DEFAULT;
108     private static final boolean DEFAULT_SIM3_CARD_PRESENT = true;
109     private static final String DEFAULT_SIM3_ATR =
110             "3B9F97C00AB1FE453FC6838031E073FE211F65D002341569810F21";
111     private static final String DEFAULT_SIM3_EID = "89033023427100000000007980324395";
112     private static final boolean DEFAULT_SIM3_PORT_ACTIVE = false;
113     private static final int DEFAULT_SIM3_PORT_ID = 0;
114     private static final int DEFAULT_SIM3_LOGICAL_SLOT_ID = -1;
115     private static final int DEFAULT_SIM3_UNIVERSAL_PIN_STATE = PinState.DISABLED;
116 
117     private String mTag = "MockSimService";
118     private Context mContext;
119 
120     // SIM Slot status
121     private int mPhysicalSlotId;
122     private int mLogicalSlotId;
123     private int mSlotPortId;
124     private boolean mIsSlotPortActive;
125     private boolean mIsCardPresent;
126 
127     /* SIM profile info */
128     private SimProfileInfo[] mSimProfileInfoList;
129 
130     // SIM card data
131     private int mSimProfileId;
132     private String mEID;
133     private String mATR;
134     private int mUniversalPinState;
135 
136     private AppStatus[] mSimApp;
137     private ArrayList<SimAppData> mSimAppList;
138 
139     // Key: AID Value: list of SIM IO (command-respond) data
140     private final Map<String, List<SimIoData>> mSimIoDataMap = new HashMap<>();
141 
142     // TODO: switch to @AutoValue?
143     public static final class SimIoData {
144         public final String mFileId;
145         public final String mCommand;
146         public final String mSw1;
147         public final String mSw2;
148         public final String mResponse;
149 
SimIoData(String fileid, String command, String sw1, String sw2, String response)150         public SimIoData(String fileid, String command, String sw1, String sw2, String response) {
151             mFileId = fileid;
152             mCommand = command;
153             mSw1 = sw1;
154             mSw2 = sw2;
155             mResponse = response;
156         }
157 
toString()158         public String toString() {
159             return "SimIoData: "
160                     + "fileid=" + mFileId
161                     + ", cmd=" + mCommand
162                     + ", sw1=" + mSw1
163                     + ", sw2=" + mSw2
164                     + ", response=" + mResponse;
165         }
166     }
167 
168     public class SimAppData {
169         private static final int EF_INFO_DATA = 0;
170         private static final int EF_BINARY_DATA = 1;
171 
172         private int mSimAppId;
173         private String mAid;
174         private boolean mIsCurrentActive;
175         private String mPath;
176         private int mFdnStatus;
177         private int mPin1State;
178         private String mImsi;
179         private String mMcc;
180         private String mMnc;
181         private String mMsin;
182         private String[] mIccid;
183         private String[] mGid1;
184 
initSimAppData(int simappid, String aid, String path, boolean status)185         private void initSimAppData(int simappid, String aid, String path, boolean status) {
186             mSimAppId = simappid;
187             mAid = aid;
188             mIsCurrentActive = status;
189             mPath = path;
190             mIccid = new String[2];
191             mGid1 = new String[2];
192         }
193 
SimAppData(int simappid, String aid, String path)194         public SimAppData(int simappid, String aid, String path) {
195             initSimAppData(simappid, aid, path, false);
196         }
197 
SimAppData(int simappid, String aid, String path, boolean status)198         public SimAppData(int simappid, String aid, String path, boolean status) {
199             initSimAppData(simappid, aid, path, status);
200         }
201 
getSimAppId()202         public int getSimAppId() {
203             return mSimAppId;
204         }
205 
getAid()206         public String getAid() {
207             return mAid;
208         }
209 
isCurrentActive()210         public boolean isCurrentActive() {
211             return mIsCurrentActive;
212         }
213 
getPath()214         public String getPath() {
215             return mPath;
216         }
217 
getFdnStatus()218         public int getFdnStatus() {
219             return mFdnStatus;
220         }
221 
setFdnStatus(int status)222         public void setFdnStatus(int status) {
223             mFdnStatus = status;
224         }
225 
getPin1State()226         public int getPin1State() {
227             return mPin1State;
228         }
229 
setPin1State(int state)230         public void setPin1State(int state) {
231             mPin1State = state;
232         }
233 
getImsi()234         public String getImsi() {
235             return mMcc + mMnc + mMsin;
236         }
237 
setImsi(String mcc, String mnc, String msin)238         public void setImsi(String mcc, String mnc, String msin) {
239             setMcc(mcc);
240             setMnc(mnc);
241             setMsin(msin);
242         }
243 
getMcc()244         public String getMcc() {
245             return mMcc;
246         }
247 
setMcc(String mcc)248         public void setMcc(String mcc) {
249             mMcc = mcc;
250         }
251 
getMnc()252         public String getMnc() {
253             return mMnc;
254         }
255 
setMnc(String mnc)256         public void setMnc(String mnc) {
257             mMnc = mnc;
258         }
259 
getMsin()260         public String getMsin() {
261             return mMsin;
262         }
263 
setMsin(String msin)264         public void setMsin(String msin) {
265             mMsin = msin;
266         }
267 
getIccidInfo()268         public String getIccidInfo() {
269             return mIccid[EF_INFO_DATA];
270         }
271 
setIccidInfo(String info)272         public void setIccidInfo(String info) {
273             mIccid[EF_INFO_DATA] = info;
274         }
275 
getIccid()276         public String getIccid() {
277             return mIccid[EF_BINARY_DATA];
278         }
279 
setIccid(String iccid)280         public void setIccid(String iccid) {
281             mIccid[EF_BINARY_DATA] = iccid;
282         }
283 
getGid1Info()284         public String getGid1Info() {
285             return mGid1[EF_INFO_DATA];
286         }
287 
setGid1Info(String info)288         public void setGid1Info(String info) {
289             mGid1[EF_INFO_DATA] = info;
290         }
291 
getGid1()292         public String getGid1() {
293             return mGid1[EF_BINARY_DATA];
294         }
295 
setGid1(String gid1)296         public void setGid1(String gid1) {
297             mGid1[EF_BINARY_DATA] = gid1;
298         }
299     }
300 
301     public class SimProfileInfo {
302         private int mSimProfileId;
303         private int mNumOfSimApp;
304         private int mGsmAppIndex;
305         private int mCdmaAppIndex;
306         private int mImsAppIndex;
307         private String mXmlFile;
308 
SimProfileInfo(int profileid)309         public SimProfileInfo(int profileid) {
310             mSimProfileId = profileid;
311             mNumOfSimApp = DEFAULT_NUM_OF_SIM_APP;
312             mGsmAppIndex = DEFAULT_GSM_APP_IDX;
313             mCdmaAppIndex = DEFAULT_CDMA_APP_IDX;
314             mImsAppIndex = DEFAULT_IMS_APP_IDX;
315             mXmlFile = "";
316         }
317 
getNumOfSimApp()318         public int getNumOfSimApp() {
319             return mNumOfSimApp;
320         }
321 
getGsmAppIndex()322         public int getGsmAppIndex() {
323             return mGsmAppIndex;
324         }
325 
getCdmaAppIndex()326         public int getCdmaAppIndex() {
327             return mCdmaAppIndex;
328         }
329 
getImsAppIndex()330         public int getImsAppIndex() {
331             return mImsAppIndex;
332         }
333 
getXmlFile()334         public String getXmlFile() {
335             return mXmlFile;
336         }
337 
setNumOfSimApp(int number)338         public void setNumOfSimApp(int number) {
339             mNumOfSimApp = number;
340         }
341 
setGsmAppIndex(int index)342         public void setGsmAppIndex(int index) {
343             mGsmAppIndex = index;
344         }
345 
setCdmaAppIndex(int index)346         public void setCdmaAppIndex(int index) {
347             mCdmaAppIndex = index;
348         }
349 
setImsAppIndex(int index)350         public void setImsAppIndex(int index) {
351             mImsAppIndex = index;
352         }
353 
setXmlFile(String file)354         public void setXmlFile(String file) {
355             mXmlFile = file;
356         }
357     }
358 
MockSimService(Context context, int slotId)359     public MockSimService(Context context, int slotId) {
360         mContext = context;
361         int simprofile = DEFAULT_SIM1_PROFILE_ID;
362 
363         if (slotId >= MOCK_SIM_SLOT_MAX) {
364             Log.e(
365                     mTag,
366                     "Invalid slot id("
367                             + slotId
368                             + "). Using default slot id("
369                             + MOCK_SIM_DEFAULT_SLOTID
370                             + ").");
371             slotId = MOCK_SIM_DEFAULT_SLOTID;
372         }
373 
374         // Init default SIM profile id
375         mTag = mTag + "-" + slotId;
376         switch (slotId) {
377             case MOCK_SIM_SLOT_1:
378                 simprofile = DEFAULT_SIM1_PROFILE_ID;
379                 break;
380             case MOCK_SIM_SLOT_2:
381                 simprofile = DEFAULT_SIM2_PROFILE_ID;
382                 break;
383             case MOCK_SIM_SLOT_3:
384                 simprofile = DEFAULT_SIM3_PROFILE_ID;
385                 break;
386         }
387 
388         // Initial support SIM profile list
389         mSimProfileInfoList = new SimProfileInfo[MOCK_SIM_PROFILE_ID_MAX];
390         for (int idx = 0; idx < MOCK_SIM_PROFILE_ID_MAX; idx++) {
391             Log.d(mTag, "Create sim profile id = " + idx);
392             mSimProfileInfoList[idx] = new SimProfileInfo(idx);
393             switch (idx) {
394                 case MOCK_SIM_PROFILE_ID_TWN_CHT:
395                     mSimProfileInfoList[idx].setXmlFile("mock_sim_tw_cht.xml");
396                     break;
397                 case MOCK_SIM_PROFILE_ID_TWN_FET:
398                     mSimProfileInfoList[idx].setXmlFile("mock_sim_tw_fet.xml");
399                     break;
400                 case MOCK_SIM_PROFILE_ID_US_FI:
401                     mSimProfileInfoList[idx].setXmlFile("mock_sim_us_fi.xml");
402                     break;
403                 default:
404                     break;
405             }
406         }
407 
408         // Initiate SIM card with default profile
409         initMockSimCard(slotId, simprofile);
410     }
411 
initMockSimCard(int slotId, int simProfileId)412     private void initMockSimCard(int slotId, int simProfileId) {
413         if (slotId > MockModemConfigInterface.MAX_NUM_OF_SIM_SLOT) {
414             Log.e(
415                     mTag,
416                     "Physical slot id("
417                             + slotId
418                             + ") is invalid. Using default slot id("
419                             + MOCK_SIM_DEFAULT_SLOTID
420                             + ").");
421             mPhysicalSlotId = MOCK_SIM_DEFAULT_SLOTID;
422         } else {
423             mPhysicalSlotId = slotId;
424         }
425         if (simProfileId >= 0 && simProfileId < MOCK_SIM_PROFILE_ID_MAX) {
426             mSimProfileId = simProfileId;
427             Log.i(
428                     mTag,
429                     "Load SIM profile ID: "
430                             + mSimProfileId
431                             + " into physical slot["
432                             + mPhysicalSlotId
433                             + "]");
434         } else {
435             mSimProfileId = MOCK_SIM_PROFILE_ID_DEFAULT;
436             Log.e(
437                     mTag,
438                     "SIM Absent on physical slot["
439                             + mPhysicalSlotId
440                             + "]. Not support SIM card ID: "
441                             + mSimProfileId);
442         }
443 
444         // Initiate slot status
445         initMockSimSlot();
446 
447         // Load SIM profile data
448         loadMockSimCard();
449     }
450 
initMockSimSlot()451     private void initMockSimSlot() {
452         switch (mPhysicalSlotId) {
453             case MOCK_SIM_SLOT_1:
454                 mLogicalSlotId = DEFAULT_SIM1_LOGICAL_SLOT_ID;
455                 mSlotPortId = DEFAULT_SIM1_PORT_ID;
456                 mIsSlotPortActive = DEFAULT_SIM1_PORT_ACTIVE;
457                 mIsCardPresent = DEFAULT_SIM1_CARD_PRESENT;
458                 break;
459             case MOCK_SIM_SLOT_2:
460                 mLogicalSlotId = DEFAULT_SIM2_LOGICAL_SLOT_ID;
461                 mSlotPortId = DEFAULT_SIM2_PORT_ID;
462                 mIsSlotPortActive = DEFAULT_SIM2_PORT_ACTIVE;
463                 mIsCardPresent = DEFAULT_SIM2_CARD_PRESENT;
464                 break;
465             case MOCK_SIM_SLOT_3:
466                 mLogicalSlotId = DEFAULT_SIM3_LOGICAL_SLOT_ID;
467                 mSlotPortId = DEFAULT_SIM3_PORT_ID;
468                 mIsSlotPortActive = DEFAULT_SIM3_PORT_ACTIVE;
469                 mIsCardPresent = DEFAULT_SIM3_CARD_PRESENT;
470                 break;
471         }
472     }
473 
convertMockSimPinState(String pinstate)474     private int convertMockSimPinState(String pinstate) {
475         int mocksim_pinstate = PinState.UNKNOWN;
476         switch (pinstate) {
477             case "PINSTATE_UNKNOWN":
478                 mocksim_pinstate = PinState.UNKNOWN;
479                 break;
480             case "PINSTATE_ENABLED_NOT_VERIFIED":
481                 mocksim_pinstate = PinState.ENABLED_NOT_VERIFIED;
482                 break;
483             case "PINSTATE_ENABLED_VERIFIED":
484                 mocksim_pinstate = PinState.ENABLED_VERIFIED;
485                 break;
486             case "PINSTATE_DISABLED":
487                 mocksim_pinstate = PinState.DISABLED;
488                 break;
489             case "PINSTATE_ENABLED_BLOCKED":
490                 mocksim_pinstate = PinState.ENABLED_BLOCKED;
491                 break;
492             case "PINSTATE_ENABLED_PERM_BLOCKED":
493                 mocksim_pinstate = PinState.ENABLED_PERM_BLOCKED;
494                 break;
495         }
496 
497         return mocksim_pinstate;
498     }
499 
convertMockSimAppType(String apptype)500     private int convertMockSimAppType(String apptype) {
501         int mocksim_apptype = AppStatus.APP_TYPE_UNKNOWN;
502         switch (apptype) {
503             case "APPTYPE_UNKNOWN":
504                 mocksim_apptype = AppStatus.APP_TYPE_UNKNOWN;
505                 break;
506             case "APPTYPE_SIM":
507                 mocksim_apptype = AppStatus.APP_TYPE_SIM;
508                 break;
509             case "APPTYPE_USIM":
510                 mocksim_apptype = AppStatus.APP_TYPE_USIM;
511                 break;
512             case "APPTYPE_RUIM":
513                 mocksim_apptype = AppStatus.APP_TYPE_RUIM;
514                 break;
515             case "APPTYPE_CSIM":
516                 mocksim_apptype = AppStatus.APP_TYPE_CSIM;
517                 break;
518             case "APPTYPE_ISIM":
519                 mocksim_apptype = AppStatus.APP_TYPE_ISIM;
520                 break;
521         }
522 
523         return mocksim_apptype;
524     }
525 
convertMockSimAppState(String appstate)526     private int convertMockSimAppState(String appstate) {
527         int mocksim_appstate = AppStatus.APP_STATE_UNKNOWN;
528         switch (appstate) {
529             case "APPSTATE_UNKNOWN":
530                 mocksim_appstate = AppStatus.APP_STATE_UNKNOWN;
531                 break;
532             case "APPSTATE_DETECTED":
533                 mocksim_appstate = AppStatus.APP_STATE_DETECTED;
534                 break;
535             case "APPSTATE_PIN":
536                 mocksim_appstate = AppStatus.APP_STATE_PIN;
537                 break;
538             case "APPSTATE_PUK":
539                 mocksim_appstate = AppStatus.APP_STATE_PUK;
540                 break;
541             case "APPSTATE_SUBSCRIPTION_PERSO":
542                 mocksim_appstate = AppStatus.APP_STATE_SUBSCRIPTION_PERSO;
543                 break;
544             case "APPSTATE_READY":
545                 mocksim_appstate = AppStatus.APP_STATE_READY;
546                 break;
547         }
548         return mocksim_appstate;
549     }
550 
convertMockSimFacilityLock(String lock)551     private int convertMockSimFacilityLock(String lock) {
552         int facilitylock = 0;
553         switch (lock) {
554             case "LOCK_ENABLED":
555                 facilitylock = 1;
556                 break;
557             case "LOCK_DISABLED":
558                 facilitylock = 0;
559                 break;
560         }
561         return facilitylock;
562     }
563 
getSimAppDataIndexByAid(String aid)564     private int getSimAppDataIndexByAid(String aid) {
565         int idx;
566         for (idx = 0; idx < mSimAppList.size(); idx++) {
567             if (aid.equals(mSimAppList.get(idx).getAid())) {
568                 break;
569             }
570         }
571         return idx;
572     }
573 
extractImsi(String imsi, int mncDigit)574     private String[] extractImsi(String imsi, int mncDigit) {
575         String[] result = null;
576 
577         Log.d(mTag, "IMSI = " + imsi + ", mnc-digit = " + mncDigit);
578 
579         if (imsi.length() > 15 && imsi.length() < 5) {
580             Log.d(mTag, "Invalid IMSI length.");
581             return result;
582         }
583 
584         if (mncDigit != 2 && mncDigit != 3) {
585             Log.d(mTag, "Invalid mnc length.");
586             return result;
587         }
588 
589         result = new String[3];
590         result[0] = imsi.substring(0, 3); // MCC
591         result[1] = imsi.substring(3, 3 + mncDigit); // MNC
592         result[2] = imsi.substring(3 + mncDigit, imsi.length()); // MSIN
593 
594         Log.d(mTag, "MCC = " + result[0] + " MNC = " + result[1] + " MSIN = " + result[2]);
595 
596         return result;
597     }
598 
storeEfData( String aid, String name, String id, String command, String[] value)599     private boolean storeEfData(
600             String aid, String name, String id, String command, String[] value) {
601         boolean result = true;
602 
603         if (value == null) {
604             Log.e(mTag, "Invalid value of EF field - " + name + "(" + id + ")");
605             return false;
606         }
607 
608         switch (name) {
609             case "EF_IMSI":
610                 if (value.length == 3
611                         && value[0] != null
612                         && value[0].length() == 3
613                         && value[1] != null
614                         && (value[1].length() == 2 || value[1].length() == 3)
615                         && value[2] != null
616                         && value[2].length() > 0
617                         && (value[0].length() + value[1].length() + value[2].length() <= 15)) {
618                     mSimAppList
619                             .get(getSimAppDataIndexByAid(aid))
620                             .setImsi(value[0], value[1], value[2]);
621                 } else {
622                     result = false;
623                     Log.e(mTag, "Invalid value for EF field - " + name + "(" + id + ")");
624                 }
625                 break;
626             case "EF_ICCID":
627                 if (command.length() > 2
628                         && Integer.parseInt(command.substring(2), 16) == COMMAND_READ_BINARY) {
629                     mSimAppList.get(getSimAppDataIndexByAid(aid)).setIccid(value[0]);
630                 } else if (command.length() > 2
631                         && Integer.parseInt(command.substring(2), 16) == COMMAND_GET_RESPONSE) {
632                     mSimAppList.get(getSimAppDataIndexByAid(aid)).setIccidInfo(value[0]);
633                 } else {
634                     Log.e(mTag, "No valid Iccid data found");
635                     result = false;
636                 }
637                 break;
638             case "EF_GID1":
639                 if (command.length() > 2
640                         && Integer.parseInt(command.substring(2), 16) == COMMAND_READ_BINARY) {
641                     mSimAppList.get(getSimAppDataIndexByAid(aid)).setGid1(value[0]);
642                 } else if (command.length() > 2
643                         && Integer.parseInt(command.substring(2), 16) == COMMAND_GET_RESPONSE) {
644                     mSimAppList.get(getSimAppDataIndexByAid(aid)).setGid1Info(value[0]);
645                 } else {
646                     Log.e(mTag, "No valid GID1 found");
647                     result = false;
648                 }
649                 break;
650             default:
651                 result = false;
652                 Log.w(mTag, "Not support EF field - " + name + "(" + id + ")");
653                 break;
654         }
655         return result;
656     }
657 
loadSimProfileFromXml()658     private boolean loadSimProfileFromXml() {
659         boolean result = true;
660 
661         if (mSimProfileInfoList == null) {
662             Log.e(mTag, "No support SIM profile list.");
663             return false;
664         }
665 
666         try {
667             String file = mSimProfileInfoList[mSimProfileId].getXmlFile();
668             int event;
669             XmlPullParser parser = Xml.newPullParser();
670             InputStream input;
671             boolean mocksim_validation = false;
672             boolean mocksim_pf_validatiion = false;
673             boolean mocksim_mf_validation = false;
674             boolean mocksim_adflc_validation = false;
675             int appidx = 0;
676             int fd_lock = 0;
677             int sc_lock = 0;
678             String adf_aid = "";
679             String adflc_aid = "";
680 
681             input = mContext.getAssets().open(file);
682             parser.setInput(input, null);
683             while (result && (event = parser.next()) != XmlPullParser.END_DOCUMENT) {
684                 switch (event) {
685                     case XmlPullParser.START_TAG:
686                         if (MOCK_SIM_TAG.equals(parser.getName())) {
687                             int numofapp = Integer.parseInt(parser.getAttributeValue(0));
688                             mATR = parser.getAttributeValue(1);
689                             Log.d(
690                                     mTag,
691                                     "Found "
692                                             + MOCK_SIM_TAG
693                                             + ": numofapp = "
694                                             + numofapp
695                                             + " atr = "
696                                             + mATR);
697                             mSimApp = new AppStatus[numofapp];
698                             if (mSimApp == null) {
699                                 Log.e(mTag, "Create SIM app failed!");
700                                 result = false;
701                                 break;
702                             }
703                             mocksim_validation = true;
704                         } else if (mocksim_validation
705                                 && MOCK_SIM_PROFILE_TAG.equals(parser.getName())
706                                 && appidx < mSimApp.length) {
707                             int id = Integer.parseInt(parser.getAttributeValue(0));
708                             int type = convertMockSimAppType(parser.getAttributeValue(1));
709                             mSimApp[appidx] = new AppStatus();
710                             mSimApp[appidx].appType = type;
711                             switch (type) {
712                                 case AppStatus.APP_TYPE_SIM:
713                                 case AppStatus.APP_TYPE_USIM:
714                                     mSimProfileInfoList[mSimProfileId].setGsmAppIndex(id);
715                                     break;
716                                 case AppStatus.APP_TYPE_CSIM:
717                                 case AppStatus.APP_TYPE_RUIM:
718                                     mSimProfileInfoList[mSimProfileId].setCdmaAppIndex(id);
719                                     break;
720                                 case AppStatus.APP_TYPE_ISIM:
721                                     mSimProfileInfoList[mSimProfileId].setImsAppIndex(id);
722                                     break;
723                             }
724                             Log.d(
725                                     mTag,
726                                     "Found ["
727                                             + MOCK_SIM_PROFILE_TAG
728                                             + "]: id = "
729                                             + id
730                                             + " type = "
731                                             + parser.getAttributeValue(1)
732                                             + " ("
733                                             + type
734                                             + ")========");
735                             mocksim_pf_validatiion = true;
736                         } else if (mocksim_validation
737                                 && mocksim_pf_validatiion
738                                 && MOCK_PIN_PROFILE_TAG.equals(parser.getName())) {
739                             int appstate = convertMockSimAppState(parser.getAttributeValue(0));
740                             mSimApp[appidx].appState = appstate;
741                             Log.d(
742                                     mTag,
743                                     "Found "
744                                             + MOCK_PIN_PROFILE_TAG
745                                             + ": appstate = "
746                                             + parser.getAttributeValue(0)
747                                             + " ("
748                                             + appstate
749                                             + ")");
750                         } else if (mocksim_validation
751                                 && mocksim_pf_validatiion
752                                 && MOCK_PIN1_STATE_TAG.equals(parser.getName())) {
753                             String state = parser.nextText();
754                             int pin1state = convertMockSimPinState(state);
755                             mSimApp[appidx].pin1 = pin1state;
756                             Log.d(
757                                     mTag,
758                                     "Found "
759                                             + MOCK_PIN1_STATE_TAG
760                                             + " = "
761                                             + state
762                                             + " ("
763                                             + pin1state
764                                             + ")");
765                         } else if (mocksim_validation
766                                 && mocksim_pf_validatiion
767                                 && MOCK_PIN2_STATE_TAG.equals(parser.getName())) {
768                             String state = parser.nextText();
769                             int pin2state = convertMockSimPinState(state);
770                             Log.d(
771                                     mTag,
772                                     "Found "
773                                             + MOCK_PIN2_STATE_TAG
774                                             + " = "
775                                             + state
776                                             + " ("
777                                             + pin2state
778                                             + ")");
779                             mSimApp[appidx].pin2 = pin2state;
780                         } else if (mocksim_validation
781                                 && mocksim_pf_validatiion
782                                 && MOCK_FACILITY_LOCK_FD_TAG.equals(parser.getName())) {
783                             fd_lock = convertMockSimFacilityLock(parser.nextText());
784                             Log.d(
785                                     mTag,
786                                     "Found "
787                                             + MOCK_FACILITY_LOCK_FD_TAG
788                                             + ": fd lock = "
789                                             + fd_lock);
790                         } else if (mocksim_validation
791                                 && mocksim_pf_validatiion
792                                 && MOCK_FACILITY_LOCK_SC_TAG.equals(parser.getName())) {
793                             sc_lock = convertMockSimFacilityLock(parser.nextText());
794                             Log.d(
795                                     mTag,
796                                     "Found "
797                                             + MOCK_FACILITY_LOCK_SC_TAG
798                                             + ": sc lock = "
799                                             + sc_lock);
800                         } else if (mocksim_validation
801                                 && mocksim_pf_validatiion
802                                 && MOCK_MF_TAG.equals(parser.getName())) {
803                             SimAppData simAppData;
804                             String name = parser.getAttributeValue(0);
805                             String path = parser.getAttributeValue(1);
806                             simAppData = new SimAppData(appidx, name, path);
807                             if (simAppData == null) {
808                                 Log.e(mTag, "Create SIM app data failed!");
809                                 result = false;
810                                 break;
811                             }
812                             mSimAppList.add(simAppData);
813                             Log.d(
814                                     mTag,
815                                     "Found "
816                                             + MOCK_MF_TAG
817                                             + ": name = "
818                                             + name
819                                             + " path = "
820                                             + path);
821                         } else if (mocksim_validation
822                                 && mocksim_pf_validatiion
823                                 && !mocksim_mf_validation
824                                 && MOCK_EF_DIR_TAG.equals(parser.getName())) {
825                             SimAppData simAppData;
826                             String name = parser.getAttributeValue(0);
827                             boolean curr_active = Boolean.parseBoolean(parser.getAttributeValue(1));
828                             String aid = parser.nextText();
829                             simAppData = new SimAppData(appidx, aid, name, curr_active);
830                             if (simAppData == null) {
831                                 Log.e(mTag, "Create SIM app data failed!");
832                                 result = false;
833                                 break;
834                             }
835                             simAppData.setFdnStatus(fd_lock);
836                             simAppData.setPin1State(sc_lock);
837                             mSimAppList.add(simAppData);
838                             if (curr_active) {
839                                 mSimApp[appidx].aidPtr = aid;
840                             }
841                             Log.d(
842                                     mTag,
843                                     "Found "
844                                             + MOCK_EF_DIR_TAG
845                                             + ": name = "
846                                             + name
847                                             + ": curr_active = "
848                                             + curr_active
849                                             + " aid = "
850                                             + aid);
851                             mocksim_mf_validation = true;
852                         } else if (mocksim_validation
853                                 && mocksim_pf_validatiion
854                                 && mocksim_mf_validation
855                                 && MOCK_ADF_TAG.equals(parser.getName())) {
856                             String aid = parser.getAttributeValue(0);
857                             Log.d(mTag, "Found " + MOCK_ADF_TAG + ": aid = " + aid);
858                             adf_aid = aid;
859                         } else if (mocksim_validation
860                                 && mocksim_pf_validatiion
861                                 && mocksim_mf_validation
862                                 && (adf_aid.length() > 0)
863                                 && MOCK_EF_TAG.equals(parser.getName())) {
864                             String name = parser.getAttributeValue(0);
865                             String id = parser.getAttributeValue(1);
866                             String command = parser.getAttributeValue(2);
867                             String[] value;
868                             switch (id) {
869                                 case "6F07": // EF_IMSI
870                                     int mncDigit = Integer.parseInt(parser.getAttributeValue(3));
871                                     String imsi = parser.nextText();
872                                     value = extractImsi(imsi, mncDigit);
873                                     if (value != null
874                                             && storeEfData(adf_aid, name, id, command, value)) {
875                                         Log.d(
876                                                 mTag,
877                                                 "Found "
878                                                         + MOCK_EF_TAG
879                                                         + ": name = "
880                                                         + name
881                                                         + " id = "
882                                                         + id
883                                                         + " command = "
884                                                         + command
885                                                         + " value = "
886                                                         + imsi
887                                                         + " with mnc-digit = "
888                                                         + mncDigit);
889                                     }
890                                     break;
891                                 default:
892                                     value = new String[1];
893                                     if (value != null) {
894                                         value[0] = parser.nextText();
895                                         if (storeEfData(adf_aid, name, id, command, value)) {
896                                             Log.d(
897                                                     mTag,
898                                                     "Found "
899                                                             + MOCK_EF_TAG
900                                                             + ": name = "
901                                                             + name
902                                                             + " id = "
903                                                             + id
904                                                             + " command = "
905                                                             + command
906                                                             + " value = "
907                                                             + value[0]);
908                                         }
909                                     }
910                                     break;
911                             }
912                         } else if (mocksim_validation && MOCK_ADFLC_TAG.equals(parser.getName())) {
913                             String aid = parser.getAttributeValue(0);
914                             String name = parser.getAttributeValue(1);
915                             Log.d(mTag,
916                                     "Found " + MOCK_ADFLC_TAG + ", aid=" + aid + ", name=" + name);
917                             if (!TextUtils.isEmpty(aid)) {
918                                 adflc_aid = aid;
919                                 synchronized (mSimIoDataMap) {
920                                     mSimIoDataMap.put(aid, new ArrayList<>());
921                                 }
922                             }
923                             mocksim_adflc_validation = true;
924                         } else if (mocksim_adflc_validation
925                                 && MOCK_IO_TAG.equals(parser.getName())) {
926                             String fileid = parser.getAttributeValue(0);
927                             String command = parser.getAttributeValue(1);
928                             String sw1 = parser.getAttributeValue(2);
929                             String sw2 = parser.getAttributeValue(3);
930                             String response = parser.nextText();
931                             synchronized (mSimIoDataMap) {
932                                 mSimIoDataMap.get(adflc_aid).add(
933                                         new SimIoData(fileid, command, sw1, sw2, response));
934                             }
935                             Log.d(mTag, "Found " + MOCK_IO_TAG + ": fileid=" + fileid + " command="
936                                     + command + " adflc_aid=" + adflc_aid);
937                         }
938                         break;
939                     case XmlPullParser.END_TAG:
940                         if (mocksim_validation && MOCK_SIM_PROFILE_TAG.equals(parser.getName())) {
941                             appidx++;
942                             mocksim_pf_validatiion = false;
943                             mocksim_mf_validation = false;
944                         } else if (mocksim_validation && MOCK_ADF_TAG.equals(parser.getName())) {
945                             adf_aid = "";
946                         } else if (mocksim_validation && MOCK_ADFLC_TAG.equals(parser.getName())) {
947                             mocksim_adflc_validation = false;
948                             adflc_aid = "";
949                         }
950                         break;
951                 }
952             }
953             Log.d(mTag, "Totally create " + Math.min(mSimApp.length, appidx) + " SIM profiles");
954             mSimProfileInfoList[mSimProfileId].setNumOfSimApp(appidx);
955             input.close();
956         } catch (Exception e) {
957             Log.e(mTag, "Exception error: " + e);
958             result = false;
959         }
960 
961         return result;
962     }
963 
loadSimApp()964     private boolean loadSimApp() {
965         boolean result = true;
966 
967         if (mSimAppList == null) {
968             mSimAppList = new ArrayList<SimAppData>();
969         } else {
970             mSimAppList.clear();
971         }
972 
973         if (mSimProfileId == MOCK_SIM_PROFILE_ID_DEFAULT
974                 || mSimProfileInfoList[mSimProfileId].getXmlFile().length() == 0) {
975             Log.d(mTag, "SIM absent case");
976             mSimApp = new AppStatus[0];
977             if (mSimApp == null) {
978                 Log.e(mTag, "Create SIM app failed!");
979                 result = false;
980             }
981         } else {
982             result = loadSimProfileFromXml();
983         }
984 
985         return result;
986     }
987 
loadMockSimCard()988     private boolean loadMockSimCard() {
989         if (mSimProfileId != MOCK_SIM_PROFILE_ID_DEFAULT) {
990             switch (mPhysicalSlotId) {
991                 case MOCK_SIM_SLOT_1: // pSIM
992                     mEID = DEFAULT_SIM1_EID;
993                     break;
994                 case MOCK_SIM_SLOT_2: // eSIM
995                     mATR = DEFAULT_SIM2_ATR;
996                     mEID = DEFAULT_SIM2_EID;
997                     break;
998                 case MOCK_SIM_SLOT_3: // eSIM
999                     mATR = DEFAULT_SIM3_ATR;
1000                     mEID = DEFAULT_SIM3_EID;
1001                     break;
1002             }
1003             mUniversalPinState = PinState.DISABLED;
1004             mIsCardPresent = true;
1005         } else {
1006             switch (mPhysicalSlotId) {
1007                 case MOCK_SIM_SLOT_1:
1008                     mATR = DEFAULT_SIM1_ATR;
1009                     mEID = DEFAULT_SIM1_EID;
1010                     mUniversalPinState = DEFAULT_SIM1_UNIVERSAL_PIN_STATE;
1011                     mIsCardPresent = DEFAULT_SIM1_CARD_PRESENT;
1012                     break;
1013                 case MOCK_SIM_SLOT_2:
1014                     mATR = DEFAULT_SIM2_ATR;
1015                     mEID = DEFAULT_SIM2_EID;
1016                     mUniversalPinState = DEFAULT_SIM2_UNIVERSAL_PIN_STATE;
1017                     mIsCardPresent = DEFAULT_SIM2_CARD_PRESENT;
1018                     break;
1019                 case MOCK_SIM_SLOT_3:
1020                     mATR = DEFAULT_SIM3_ATR;
1021                     mEID = DEFAULT_SIM3_EID;
1022                     mUniversalPinState = DEFAULT_SIM3_UNIVERSAL_PIN_STATE;
1023                     mIsCardPresent = DEFAULT_SIM3_CARD_PRESENT;
1024                     break;
1025             }
1026         }
1027         return loadSimApp();
1028     }
1029 
loadSimCard(int simprofileid)1030     public boolean loadSimCard(int simprofileid) {
1031         boolean result = true;
1032         if (mSimProfileId >= MOCK_SIM_PROFILE_ID_DEFAULT
1033                 && mSimProfileId < MOCK_SIM_PROFILE_ID_MAX) {
1034             mSimProfileId = simprofileid;
1035             result = loadMockSimCard();
1036         } else {
1037             result = false;
1038         }
1039         return result;
1040     }
1041 
isSlotPortActive()1042     public boolean isSlotPortActive() {
1043         return mIsSlotPortActive;
1044     }
1045 
isCardPresent()1046     public boolean isCardPresent() {
1047         return mIsCardPresent;
1048     }
1049 
getNumOfSimPortInfo()1050     public int getNumOfSimPortInfo() {
1051         // TODO: support multiple sim port
1052         return DEFAULT_NUM_OF_SIM_PORT_INFO;
1053     }
1054 
getPhysicalSlotId()1055     public int getPhysicalSlotId() {
1056         return mPhysicalSlotId;
1057     }
1058 
getLogicalSlotId()1059     public int getLogicalSlotId() {
1060         return mLogicalSlotId;
1061     }
1062 
getSlotPortId()1063     public int getSlotPortId() {
1064         return mSlotPortId;
1065     }
1066 
getEID()1067     public String getEID() {
1068         return mEID;
1069     }
1070 
setATR(String atr)1071     public boolean setATR(String atr) {
1072         // TODO: add any ATR format check
1073         mATR = atr;
1074         return true;
1075     }
1076 
getATR()1077     public String getATR() {
1078         return mATR;
1079     }
1080 
setICCID(String iccid)1081     public boolean setICCID(String iccid) {
1082         boolean result = false;
1083         SimAppData activeSimAppData = getActiveSimAppData();
1084 
1085         // TODO: add iccid format check
1086         if (activeSimAppData != null) {
1087             String iccidInfo = activeSimAppData.getIccidInfo();
1088             int dataFileSize = iccid.length() / 2;
1089             String dataFileSizeStr = Integer.toString(dataFileSize, 16);
1090 
1091             Log.d(mTag, "Data file size = " + dataFileSizeStr);
1092             if (dataFileSizeStr.length() <= 4) {
1093                 dataFileSizeStr = String.format("%04x", dataFileSize).toUpperCase(Locale.ROOT);
1094                 // Data file size index is 2 and 3 in byte array of iccid info data.
1095                 iccidInfo = iccidInfo.substring(0, 4) + dataFileSizeStr + iccidInfo.substring(8);
1096                 Log.d(mTag, "Update iccid info = " + iccidInfo);
1097                 activeSimAppData.setIccidInfo(iccidInfo);
1098                 activeSimAppData.setIccid(iccid);
1099                 result = true;
1100             } else {
1101                 Log.e(mTag, "Data file size(" + iccidInfo.length() + ") is too large.");
1102             }
1103         } else {
1104             Log.e(mTag, "activeSimAppData = null");
1105         }
1106 
1107         return result;
1108     }
1109 
getICCID()1110     public String getICCID() {
1111         String iccid = "";
1112         SimAppData activeSimAppData = getActiveSimAppData();
1113 
1114         if (activeSimAppData != null) {
1115             iccid = activeSimAppData.getIccid();
1116         }
1117 
1118         return iccid;
1119     }
1120 
getUniversalPinState()1121     public int getUniversalPinState() {
1122         return mUniversalPinState;
1123     }
1124 
getGsmAppIndex()1125     public int getGsmAppIndex() {
1126         return mSimProfileInfoList[mSimProfileId].getGsmAppIndex();
1127     }
1128 
getCdmaAppIndex()1129     public int getCdmaAppIndex() {
1130         return mSimProfileInfoList[mSimProfileId].getCdmaAppIndex();
1131     }
1132 
getImsAppIndex()1133     public int getImsAppIndex() {
1134         return mSimProfileInfoList[mSimProfileId].getImsAppIndex();
1135     }
1136 
getNumOfSimApp()1137     public int getNumOfSimApp() {
1138         return mSimProfileInfoList[mSimProfileId].getNumOfSimApp();
1139     }
1140 
getSimApp()1141     public AppStatus[] getSimApp() {
1142         return mSimApp;
1143     }
1144 
getSimAppList()1145     public ArrayList<SimAppData> getSimAppList() {
1146         return mSimAppList;
1147     }
1148 
getActiveSimAppData()1149     public SimAppData getActiveSimAppData() {
1150         SimAppData activeSimAppData = null;
1151 
1152         for (int simAppIdx = 0; simAppIdx < mSimAppList.size(); simAppIdx++) {
1153             if (mSimAppList.get(simAppIdx).isCurrentActive()) {
1154                 activeSimAppData = mSimAppList.get(simAppIdx);
1155                 break;
1156             }
1157         }
1158 
1159         return activeSimAppData;
1160     }
1161 
getActiveSimAppId()1162     public String getActiveSimAppId() {
1163         String aid = "";
1164         SimAppData activeSimAppData = getActiveSimAppData();
1165 
1166         if (activeSimAppData != null) {
1167             aid = activeSimAppData.getAid();
1168         }
1169 
1170         return aid;
1171     }
1172 
setMcc(String mcc)1173     private boolean setMcc(String mcc) {
1174         boolean result = false;
1175 
1176         if (mcc.length() == 3) {
1177             SimAppData activeSimAppData = getActiveSimAppData();
1178             if (activeSimAppData != null) {
1179                 activeSimAppData.setMcc(mcc);
1180                 result = true;
1181             }
1182         }
1183 
1184         return result;
1185     }
1186 
setMnc(String mnc)1187     private boolean setMnc(String mnc) {
1188         boolean result = false;
1189 
1190         if (mnc.length() == 2 || mnc.length() == 3) {
1191             SimAppData activeSimAppData = getActiveSimAppData();
1192             if (activeSimAppData != null) {
1193                 activeSimAppData.setMnc(mnc);
1194                 result = true;
1195             }
1196         }
1197 
1198         return result;
1199     }
1200 
getMccMnc()1201     public String getMccMnc() {
1202         String mcc;
1203         String mnc;
1204         String result = "";
1205         SimAppData activeSimAppData = getActiveSimAppData();
1206 
1207         if (activeSimAppData != null) {
1208             mcc = activeSimAppData.getMcc();
1209             mnc = activeSimAppData.getMnc();
1210             if (mcc != null
1211                     && mcc.length() == 3
1212                     && mnc != null
1213                     && (mnc.length() == 2 || mnc.length() == 3)) {
1214                 result = mcc + mnc;
1215             } else {
1216                 Log.e(mTag, "Invalid Mcc or Mnc.");
1217             }
1218         }
1219         return result;
1220     }
1221 
getMsin()1222     public String getMsin() {
1223         String result = "";
1224         SimAppData activeSimAppData = getActiveSimAppData();
1225 
1226         if (activeSimAppData != null) {
1227             result = activeSimAppData.getMsin();
1228             if (result.length() <= 0 || result.length() > 10) {
1229                 Log.e(mTag, "Invalid Msin.");
1230             }
1231         }
1232 
1233         return result;
1234     }
1235 
setImsi(String mcc, String mnc, String msin)1236     public boolean setImsi(String mcc, String mnc, String msin) {
1237         boolean result = false;
1238 
1239         if (msin.length() > 0 && (mcc.length() + mnc.length() + msin.length()) <= 15) {
1240             SimAppData activeSimAppData = getActiveSimAppData();
1241             if (activeSimAppData != null) {
1242                 setMcc(mcc);
1243                 setMnc(mnc);
1244                 activeSimAppData.setMsin(msin);
1245                 result = true;
1246             } else {
1247                 Log.e(mTag, "activeSimAppData = null");
1248             }
1249         } else {
1250             Log.e(mTag, "Invalid IMSI");
1251         }
1252 
1253         return result;
1254     }
1255 
getImsi()1256     public String getImsi() {
1257         String imsi = "";
1258         String mccmnc;
1259         String msin;
1260         SimAppData activeSimAppData = getActiveSimAppData();
1261 
1262         if (activeSimAppData != null) {
1263             mccmnc = getMccMnc();
1264             msin = activeSimAppData.getMsin();
1265             if (mccmnc.length() > 0
1266                     && msin != null
1267                     && msin.length() > 0
1268                     && (mccmnc.length() + msin.length()) <= 15) {
1269                 imsi = mccmnc + msin;
1270             } else {
1271                 Log.e(mTag, "Invalid Imsi.");
1272             }
1273         }
1274         return imsi;
1275     }
1276 
getSimIoMap()1277     public Map<String, List<SimIoData>> getSimIoMap() {
1278         synchronized (mSimIoDataMap) {
1279             return Collections.unmodifiableMap(mSimIoDataMap);
1280         }
1281     }
1282 }
1283