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