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