Support iccIoForApp for reading EF_ICCID

Bug: 225082158
Test: atest TelephonyManagerTestOnMockModem -c
Change-Id: Ia7f9625354d03098a1e83cc507d6ffdc16a9e77d
diff --git a/tests/tests/telephony/current/mockmodem/assets/mock_sim_tw_cht.xml b/tests/tests/telephony/current/mockmodem/assets/mock_sim_tw_cht.xml
index aaabe62..f519c6f 100644
--- a/tests/tests/telephony/current/mockmodem/assets/mock_sim_tw_cht.xml
+++ b/tests/tests/telephony/current/mockmodem/assets/mock_sim_tw_cht.xml
@@ -1,4 +1,4 @@
-<MockSim numofapp="2" iccid="89886920042507847155">
+<MockSim numofapp="2">
 <MockSimProfile id="0" type="APPTYPE_USIM">
     <PinProfile appstate="APPSTATE_READY">
         <Pin1State>PINSTATE_DISABLED</Pin1State>
@@ -15,7 +15,9 @@
     </MF>
 
     <ADF aid="A0000000871002F886FF9289050B00FE">
-        <EF name="EF_IMSI" id="6F07">311740123456789</EF>
+        <EF name="EF_IMSI" id="6F07" command="">466920123456789</EF>
+        <EF name="EF_ICCID" id="2FE2" command="0xb0">89886920042507847155</EF>
+        <EF name="EF_ICCID" id="2FE2" command="0xc0">0000000A2FE2040000FFFF01020002</EF>
     </ADF>
 </MockSimProfile>
 
diff --git a/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/IRadioSimImpl.java b/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/IRadioSimImpl.java
index 827d7ef..8d94b59 100644
--- a/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/IRadioSimImpl.java
+++ b/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/IRadioSimImpl.java
@@ -16,6 +16,9 @@
 
 package android.telephony.mockmodem;
 
+import static android.telephony.mockmodem.MockSimService.COMMAND_GET_RESPONSE;
+import static android.telephony.mockmodem.MockSimService.COMMAND_READ_BINARY;
+
 import android.hardware.radio.RadioError;
 import android.hardware.radio.RadioIndicationType;
 import android.hardware.radio.RadioResponseInfo;
@@ -35,6 +38,8 @@
 public class IRadioSimImpl extends IRadioSim.Stub {
     private static final String TAG = "MRSIM";
 
+    private static final int EF_ICCID = 0x2FE2;
+
     private final MockModemService mService;
     private IRadioSimResponse mRadioSimResponse;
     private IRadioSimIndication mRadioSimIndication;
@@ -244,26 +249,28 @@
         boolean isFacilitySupport = true;
         int responseData = -1;
 
-        // TODO: check service class
-        for (simAppIdx = 0;
-                simAppIdx < numOfSimApp && isFacilitySupport && !isHandled;
-                simAppIdx++) {
-            switch (facility) {
-                case "FD": // FDN status query
-                    if (appId.equals(mSimAppList.get(simAppIdx).getAid())) {
-                        responseData = mSimAppList.get(simAppIdx).getFdnStatus();
-                        isHandled = true;
-                    }
-                    break;
-                case "SC": // PIN1 status query
-                    if (appId.equals(mSimAppList.get(simAppIdx).getAid())) {
-                        responseData = mSimAppList.get(simAppIdx).getPin1State();
-                        isHandled = true;
-                    }
-                    break;
-                default:
-                    isFacilitySupport = false;
-                    break;
+        synchronized (mCacheUpdateMutex) {
+            // TODO: check service class
+            for (simAppIdx = 0;
+                    simAppIdx < numOfSimApp && isFacilitySupport && !isHandled;
+                    simAppIdx++) {
+                switch (facility) {
+                    case "FD": // FDN status query
+                        if (appId.equals(mSimAppList.get(simAppIdx).getAid())) {
+                            responseData = mSimAppList.get(simAppIdx).getFdnStatus();
+                            isHandled = true;
+                        }
+                        break;
+                    case "SC": // PIN1 status query
+                        if (appId.equals(mSimAppList.get(simAppIdx).getAid())) {
+                            responseData = mSimAppList.get(simAppIdx).getPin1State();
+                            isHandled = true;
+                        }
+                        break;
+                    default:
+                        isFacilitySupport = false;
+                        break;
+                }
             }
         }
 
@@ -311,10 +318,14 @@
         int simAppIdx;
         boolean isHandled;
 
-        for (simAppIdx = 0, isHandled = false; simAppIdx < numOfSimApp && !isHandled; simAppIdx++) {
-            if (aid.equals(mSimAppList.get(simAppIdx).getAid())) {
-                imsi = mSimAppList.get(simAppIdx).getImsi();
-                isHandled = true;
+        synchronized (mCacheUpdateMutex) {
+            for (simAppIdx = 0, isHandled = false;
+                    simAppIdx < numOfSimApp && !isHandled;
+                    simAppIdx++) {
+                if (aid.equals(mSimAppList.get(simAppIdx).getAid())) {
+                    imsi = mSimAppList.get(simAppIdx).getImsi();
+                    isHandled = true;
+                }
             }
         }
 
@@ -371,14 +382,117 @@
         }
     }
 
+    private String encodeBcdString(String str) {
+        StringBuffer bcdString = new StringBuffer();
+
+        if (str.length() % 2 != 0) {
+            Log.d(TAG, "Invalid string(" + str + ") for Bcd format");
+            return "";
+        }
+
+        for (int i = 0; i < str.length(); i += 2) {
+            bcdString.append(str.substring(i + 1, i + 2));
+            bcdString.append(str.substring(i, i + 1));
+        }
+
+        return bcdString.toString();
+    }
+
+    private int getIccIoResult(
+            android.hardware.radio.sim.IccIoResult iccIoResult,
+            int command,
+            int fileId,
+            String path,
+            int p1,
+            int p2,
+            int p3,
+            String aid) {
+        int numOfSimApp = mSimAppList.size();
+        int simAppIdx;
+        boolean foundAid;
+        int responseError = RadioError.GENERIC_FAILURE;
+
+        if (iccIoResult == null) {
+            return responseError;
+        }
+
+        synchronized (mCacheUpdateMutex) {
+            for (simAppIdx = 0, foundAid = false; simAppIdx < numOfSimApp; simAppIdx++) {
+                if (aid.equals(mSimAppList.get(simAppIdx).getAid())) {
+                    foundAid = true;
+                    break;
+                }
+            }
+
+            if (!foundAid) {
+                Log.e(TAG, "Not support sim application aid = " + aid);
+                iccIoResult.sw1 = 0x6A;
+                iccIoResult.sw2 = 0x82;
+            } else {
+                switch (fileId) {
+                    case EF_ICCID:
+                        if (command == COMMAND_READ_BINARY) {
+                            String bcdIccid =
+                                    encodeBcdString(mSimAppList.get(simAppIdx).getIccid());
+                            iccIoResult.simResponse = bcdIccid;
+                            Log.d(TAG, "Get IccIo result: ICCID = " + iccIoResult.simResponse);
+                            iccIoResult.sw1 = 0x90;
+                            responseError = RadioError.NONE;
+                        } else if (command == COMMAND_GET_RESPONSE) {
+                            iccIoResult.simResponse = mSimAppList.get(simAppIdx).getIccidInfo();
+                            Log.d(TAG, "Get IccIo result: ICCID = " + iccIoResult.simResponse);
+                            iccIoResult.sw1 = 0x90;
+                            responseError = RadioError.NONE;
+                        } else {
+                            Log.d(
+                                    TAG,
+                                    "Command("
+                                            + command
+                                            + ") not support for file id = 0x"
+                                            + Integer.toHexString(fileId));
+                            iccIoResult.sw1 = 0x6A;
+                            iccIoResult.sw2 = 0x82;
+                        }
+                        break;
+                    default:
+                        Log.d(TAG, "Not find EF file id = 0x" + Integer.toHexString(fileId));
+                        iccIoResult.sw1 = 0x6A;
+                        iccIoResult.sw2 = 0x82;
+                        break;
+                }
+            }
+        }
+
+        return responseError;
+    }
+
     @Override
     public void iccIoForApp(int serial, android.hardware.radio.sim.IccIo iccIo) {
         Log.d(TAG, "iccIoForApp");
-        // TODO: cache value
+        int responseError = RadioError.NONE;
         android.hardware.radio.sim.IccIoResult iccIoResult =
                 new android.hardware.radio.sim.IccIoResult();
 
-        RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
+        switch (iccIo.command) {
+            case COMMAND_READ_BINARY:
+            case COMMAND_GET_RESPONSE:
+                responseError =
+                        getIccIoResult(
+                                iccIoResult,
+                                iccIo.command,
+                                iccIo.fileId,
+                                iccIo.path,
+                                iccIo.p1,
+                                iccIo.p2,
+                                iccIo.p3,
+                                iccIo.aid);
+                break;
+            default:
+                responseError = RadioError.REQUEST_NOT_SUPPORTED;
+                break;
+        }
+
+        RadioResponseInfo rsp = mService.makeSolRsp(serial, responseError);
         try {
             mRadioSimResponse.iccIoForAppResponse(rsp, iccIoResult);
         } catch (RemoteException ex) {
diff --git a/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockSimService.java b/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockSimService.java
index 811aafa..51c336c 100644
--- a/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockSimService.java
+++ b/tests/tests/telephony/current/mockmodem/src/android/telephony/mockmodem/MockSimService.java
@@ -35,6 +35,10 @@
     public static final int MOCK_SIM_PROFILE_ID_TWN_CHT = 1;
     public static final int MOCK_SIM_PROFILE_ID_MAX = 2;
 
+    /* Type of SIM IO command */
+    public static final int COMMAND_READ_BINARY = 0xb0;
+    public static final int COMMAND_GET_RESPONSE = 0xc0;
+
     /* SIM profile XML TAG definition */
     private static final String MOCK_SIM_TAG = "MockSim";
     private static final String MOCK_SIM_PROFILE_TAG = "MockSimProfile";
@@ -111,7 +115,6 @@
 
     // SIM card data
     private int mSimProfileId;
-    private String mICCID;
     private String mEID;
     private String mATR;
     private int mUniversalPinState;
@@ -120,6 +123,9 @@
     private ArrayList<SimAppData> mSimAppList;
 
     public class SimAppData {
+        private static final int EF_INFO_DATA = 0;
+        private static final int EF_BINARY_DATA = 1;
+
         private int mSimAppId;
         private String mAid;
         private boolean mIsCurrentActive;
@@ -127,12 +133,22 @@
         private int mFdnStatus;
         private int mPin1State;
         private String mImsi;
+        private String[] mIccid;
 
-        public SimAppData(int simappid, String aid, String path) {
+        private void initSimAppData(int simappid, String aid, String path, boolean status) {
             mSimAppId = simappid;
             mAid = aid;
-            mIsCurrentActive = false;
+            mIsCurrentActive = status;
             mPath = path;
+            mIccid = new String[2];
+        }
+
+        public SimAppData(int simappid, String aid, String path) {
+            initSimAppData(simappid, aid, path, false);
+        }
+
+        public SimAppData(int simappid, String aid, String path, boolean status) {
+            initSimAppData(simappid, aid, path, status);
         }
 
         public int getSimAppId() {
@@ -174,6 +190,22 @@
         public void setImsi(String imsi) {
             mImsi = imsi;
         }
+
+        public String getIccidInfo() {
+            return mIccid[EF_INFO_DATA];
+        }
+
+        public void setIccidInfo(String info) {
+            mIccid[EF_INFO_DATA] = info;
+        }
+
+        public String getIccid() {
+            return mIccid[EF_BINARY_DATA];
+        }
+
+        public void setIccid(String iccid) {
+            mIccid[EF_BINARY_DATA] = iccid;
+        }
     }
 
     public class SimProfileInfo {
@@ -443,12 +475,24 @@
         return idx;
     }
 
-    private boolean storeEfData(String aid, String name, String id, String value) {
+    private boolean storeEfData(String aid, String name, String id, String command, String value) {
         boolean result = true;
         switch (name) {
             case "EF_IMSI":
                 mSimAppList.get(getSimAppDataIndexByAid(aid)).setImsi(value);
                 break;
+            case "EF_ICCID":
+                if (command.length() > 2
+                        && Integer.parseInt(command.substring(2), 16) == COMMAND_READ_BINARY) {
+                    mSimAppList.get(getSimAppDataIndexByAid(aid)).setIccid(value);
+                } else if (command.length() > 2
+                        && Integer.parseInt(command.substring(2), 16) == COMMAND_GET_RESPONSE) {
+                    mSimAppList.get(getSimAppDataIndexByAid(aid)).setIccidInfo(value);
+                } else {
+                    Log.e(TAG, "No valid Iccid data found");
+                    result = false;
+                }
+                break;
             default:
                 result = false;
                 Log.w(TAG, "Not support EF field - " + name + "(" + id + ")");
@@ -471,6 +515,7 @@
             XmlPullParser parser = Xml.newPullParser();
             InputStream input;
             boolean mocksim_validation = false;
+            boolean mocksim_pf_validatiion = false;
             boolean mocksim_mf_validation = false;
             int appidx = 0;
             int fd_lock = 0;
@@ -484,16 +529,7 @@
                     case XmlPullParser.START_TAG:
                         if (MOCK_SIM_TAG.equals(parser.getName())) {
                             int numofapp = Integer.parseInt(parser.getAttributeValue(0));
-                            String iccid = parser.getAttributeValue(1);
-                            Log.d(
-                                    TAG,
-                                    "Found "
-                                            + MOCK_SIM_TAG
-                                            + ": numofapp = "
-                                            + numofapp
-                                            + " iccid = "
-                                            + iccid);
-                            mICCID = iccid;
+                            Log.d(TAG, "Found " + MOCK_SIM_TAG + ": numofapp = " + numofapp);
                             mSimApp = new AppStatus[numofapp];
                             if (mSimApp == null) {
                                 Log.e(TAG, "Create SIM app failed!");
@@ -502,7 +538,8 @@
                             }
                             mocksim_validation = true;
                         } else if (mocksim_validation
-                                && MOCK_SIM_PROFILE_TAG.equals(parser.getName())) {
+                                && MOCK_SIM_PROFILE_TAG.equals(parser.getName())
+                                && appidx < mSimApp.length) {
                             int id = Integer.parseInt(parser.getAttributeValue(0));
                             int type = convertMockSimAppType(parser.getAttributeValue(1));
                             mSimApp[appidx] = new AppStatus();
@@ -531,7 +568,9 @@
                                             + " ("
                                             + type
                                             + ")========");
+                            mocksim_pf_validatiion = true;
                         } else if (mocksim_validation
+                                && mocksim_pf_validatiion
                                 && MOCK_PIN_PROFILE_TAG.equals(parser.getName())) {
                             int appstate = convertMockSimAppState(parser.getAttributeValue(0));
                             mSimApp[appidx].appState = appstate;
@@ -545,6 +584,7 @@
                                             + appstate
                                             + ")");
                         } else if (mocksim_validation
+                                && mocksim_pf_validatiion
                                 && MOCK_PIN1_STATE_TAG.equals(parser.getName())) {
                             String state = parser.nextText();
                             int pin1state = convertMockSimPinState(state);
@@ -559,6 +599,7 @@
                                             + pin1state
                                             + ")");
                         } else if (mocksim_validation
+                                && mocksim_pf_validatiion
                                 && MOCK_PIN2_STATE_TAG.equals(parser.getName())) {
                             String state = parser.nextText();
                             int pin2state = convertMockSimPinState(state);
@@ -571,7 +612,9 @@
                                             + " ("
                                             + pin2state
                                             + ")");
+                            mSimApp[appidx].pin2 = pin2state;
                         } else if (mocksim_validation
+                                && mocksim_pf_validatiion
                                 && MOCK_FACILITY_LOCK_FD_TAG.equals(parser.getName())) {
                             fd_lock = convertMockSimFacilityLock(parser.nextText());
                             Log.d(
@@ -581,6 +624,7 @@
                                             + ": fd lock = "
                                             + fd_lock);
                         } else if (mocksim_validation
+                                && mocksim_pf_validatiion
                                 && MOCK_FACILITY_LOCK_SC_TAG.equals(parser.getName())) {
                             sc_lock = convertMockSimFacilityLock(parser.nextText());
                             Log.d(
@@ -589,7 +633,9 @@
                                             + MOCK_FACILITY_LOCK_SC_TAG
                                             + ": sc lock = "
                                             + sc_lock);
-                        } else if (mocksim_validation && MOCK_MF_TAG.equals(parser.getName())) {
+                        } else if (mocksim_validation
+                                && mocksim_pf_validatiion
+                                && MOCK_MF_TAG.equals(parser.getName())) {
                             SimAppData simAppData;
                             String name = parser.getAttributeValue(0);
                             String path = parser.getAttributeValue(1);
@@ -609,13 +655,14 @@
                                             + " path = "
                                             + path);
                         } else if (mocksim_validation
+                                && mocksim_pf_validatiion
                                 && !mocksim_mf_validation
                                 && MOCK_EF_DIR_TAG.equals(parser.getName())) {
                             SimAppData simAppData;
                             String name = parser.getAttributeValue(0);
                             boolean curr_active = Boolean.parseBoolean(parser.getAttributeValue(1));
                             String aid = parser.nextText();
-                            simAppData = new SimAppData(appidx, aid, name);
+                            simAppData = new SimAppData(appidx, aid, name, curr_active);
                             if (simAppData == null) {
                                 Log.e(TAG, "Create SIM app data failed!");
                                 result = false;
@@ -639,19 +686,22 @@
                                             + aid);
                             mocksim_mf_validation = true;
                         } else if (mocksim_validation
+                                && mocksim_pf_validatiion
                                 && mocksim_mf_validation
                                 && MOCK_ADF_TAG.equals(parser.getName())) {
                             String aid = parser.getAttributeValue(0);
                             Log.d(TAG, "Found " + MOCK_ADF_TAG + ": aid = " + aid);
                             adf_aid = aid;
                         } else if (mocksim_validation
+                                && mocksim_pf_validatiion
                                 && mocksim_mf_validation
                                 && (adf_aid.length() > 0)
                                 && MOCK_EF_TAG.equals(parser.getName())) {
                             String name = parser.getAttributeValue(0);
                             String id = parser.getAttributeValue(1);
+                            String command = parser.getAttributeValue(2);
                             String value = parser.nextText();
-                            if (storeEfData(adf_aid, name, id, value)) {
+                            if (storeEfData(adf_aid, name, id, command, value)) {
                                 Log.d(
                                         TAG,
                                         "Found "
@@ -659,13 +709,18 @@
                                                 + ": name = "
                                                 + name
                                                 + " id = "
-                                                + id);
+                                                + id
+                                                + " command = "
+                                                + command
+                                                + " value = "
+                                                + value);
                             }
                         }
                         break;
                     case XmlPullParser.END_TAG:
                         if (mocksim_validation && MOCK_SIM_PROFILE_TAG.equals(parser.getName())) {
                             appidx++;
+                            mocksim_pf_validatiion = false;
                             mocksim_mf_validation = false;
                         } else if (mocksim_validation && MOCK_ADF_TAG.equals(parser.getName())) {
                             adf_aid = "";
@@ -673,7 +728,7 @@
                         break;
                 }
             }
-            Log.d(TAG, "Totally create " + appidx + " SIM profiles");
+            Log.d(TAG, "Totally create " + Math.min(mSimApp.length, appidx) + " SIM profiles");
             mSimProfileInfoList[mSimProfileId].setNumOfSimApp(appidx);
             input.close();
         } catch (Exception e) {
@@ -731,19 +786,16 @@
                 case MOCK_SIM_SLOT_1:
                     mATR = DEFAULT_SIM1_ATR;
                     mEID = DEFAULT_SIM1_EID;
-                    mICCID = DEFAULT_SIM1_ICCID;
                     mUniversalPinState = DEFAULT_SIM1_UNIVERSAL_PIN_STATE;
                     break;
                 case MOCK_SIM_SLOT_2:
                     mATR = DEFAULT_SIM2_ATR;
                     mEID = DEFAULT_SIM2_EID;
-                    mICCID = DEFAULT_SIM2_ICCID;
                     mUniversalPinState = DEFAULT_SIM2_UNIVERSAL_PIN_STATE;
                     break;
                 case MOCK_SIM_SLOT_3:
                     mATR = DEFAULT_SIM3_ATR;
                     mEID = DEFAULT_SIM3_EID;
-                    mICCID = DEFAULT_SIM3_ICCID;
                     mUniversalPinState = DEFAULT_SIM3_UNIVERSAL_PIN_STATE;
                     break;
             }
@@ -794,7 +846,14 @@
     }
 
     public String getICCID() {
-        return mICCID;
+        String iccid = "";
+        SimAppData activeSimAppData = getActiveSimAppData();
+
+        if (activeSimAppData != null) {
+            iccid = activeSimAppData.getIccid();
+        }
+
+        return iccid;
     }
 
     public int getUniversalPinState() {
@@ -824,4 +883,17 @@
     public ArrayList<SimAppData> getSimAppList() {
         return mSimAppList;
     }
+
+    public SimAppData getActiveSimAppData() {
+        SimAppData activeSimAppData = null;
+
+        for (int simAppIdx = 0; simAppIdx < mSimAppList.size(); simAppIdx++) {
+            if (mSimAppList.get(simAppIdx).isCurrentActive()) {
+                activeSimAppData = mSimAppList.get(simAppIdx);
+                break;
+            }
+        }
+
+        return activeSimAppData;
+    }
 }