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