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