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