Merge "Add new API for iccCloseLogicalChannel to pass isEs10 information."
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSim.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSim.aidl
index 85a0c71..901b251 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSim.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSim.aidl
@@ -46,6 +46,9 @@
   oneway void getImsiForApp(in int serial, in String aid);
   oneway void getSimPhonebookCapacity(in int serial);
   oneway void getSimPhonebookRecords(in int serial);
+  /**
+   * @deprecated use iccCloseLogicalChannelWithSessionInfo instead.
+   */
   oneway void iccCloseLogicalChannel(in int serial, in int channelId);
   oneway void iccIoForApp(in int serial, in android.hardware.radio.sim.IccIo iccIo);
   oneway void iccOpenLogicalChannel(in int serial, in String aid, in int p2);
@@ -70,4 +73,5 @@
   oneway void supplyIccPukForApp(in int serial, in String puk, in String pin, in String aid);
   oneway void supplySimDepersonalization(in int serial, in android.hardware.radio.sim.PersoSubstate persoType, in String controlKey);
   oneway void updateSimPhonebookRecords(in int serial, in android.hardware.radio.sim.PhonebookRecordInfo recordInfo);
+  oneway void iccCloseLogicalChannelWithSessionInfo(in int serial, in android.hardware.radio.sim.SessionInfo sessionInfo);
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSimResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSimResponse.aidl
index 8e68e30..d7c2100 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSimResponse.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSimResponse.aidl
@@ -47,6 +47,9 @@
   oneway void getImsiForAppResponse(in android.hardware.radio.RadioResponseInfo info, in String imsi);
   oneway void getSimPhonebookCapacityResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.sim.PhonebookCapacity capacity);
   oneway void getSimPhonebookRecordsResponse(in android.hardware.radio.RadioResponseInfo info);
+  /**
+   * @deprecated use iccCloseLogicalChannelWithSessionInfoResponse instead.
+   */
   oneway void iccCloseLogicalChannelResponse(in android.hardware.radio.RadioResponseInfo info);
   oneway void iccIoForAppResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.sim.IccIoResult iccIo);
   oneway void iccOpenLogicalChannelResponse(in android.hardware.radio.RadioResponseInfo info, in int channelId, in byte[] selectResponse);
@@ -69,4 +72,5 @@
   oneway void supplyIccPukForAppResponse(in android.hardware.radio.RadioResponseInfo info, in int remainingRetries);
   oneway void supplySimDepersonalizationResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.sim.PersoSubstate persoType, in int remainingRetries);
   oneway void updateSimPhonebookRecordsResponse(in android.hardware.radio.RadioResponseInfo info, in int updatedRecordIndex);
+  oneway void iccCloseLogicalChannelWithSessionInfoResponse(in android.hardware.radio.RadioResponseInfo info);
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SessionInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SessionInfo.aidl
new file mode 100644
index 0000000..1329141
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SessionInfo.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.sim;
+@JavaDerive(toString=true) @VintfStability
+parcelable SessionInfo {
+  int sessionId;
+  boolean isEs10 = false;
+}
diff --git a/radio/aidl/android/hardware/radio/sim/IRadioSim.aidl b/radio/aidl/android/hardware/radio/sim/IRadioSim.aidl
index 7923b14..3823a71 100644
--- a/radio/aidl/android/hardware/radio/sim/IRadioSim.aidl
+++ b/radio/aidl/android/hardware/radio/sim/IRadioSim.aidl
@@ -26,6 +26,7 @@
 import android.hardware.radio.sim.PersoSubstate;
 import android.hardware.radio.sim.PhonebookRecordInfo;
 import android.hardware.radio.sim.SelectUiccSub;
+import android.hardware.radio.sim.SessionInfo;
 import android.hardware.radio.sim.SimApdu;
 import android.hardware.radio.sim.SimLockMultiSimPolicy;
 
@@ -184,6 +185,8 @@
      * @param channelId session id of the logical channel (+CCHC).
      *
      * Response function is IRadioSimResponse.iccCloseLogicalChannelResponse()
+     *
+     * @deprecated use iccCloseLogicalChannelWithSessionInfo instead.
      */
     void iccCloseLogicalChannel(in int serial, in int channelId);
 
@@ -494,4 +497,19 @@
      * Response function is IRadioSimResponse.updateSimPhonebookRecordsResponse()
      */
     void updateSimPhonebookRecords(in int serial, in PhonebookRecordInfo recordInfo);
+
+    /**
+     * Close a previously opened logical channel. This command reflects TS 27.007
+     * "close logical channel" operation (+CCHC).
+     *
+     * Per spec SGP.22 V3.0, ES10 commands needs to be sent over command port of MEP-A. In order
+     * to close proper logical channel, should pass information about whether the logical channel
+     * was opened for sending ES10 commands or not.
+     *
+     * @param serial Serial number of request.
+     * @param sessionInfo Details of the opened logical channel info like sessionId and isEs10.
+     *
+     * Response function is IRadioSimResponse.iccCloseLogicalChannelWithSessionInfoResponse()
+     */
+    void iccCloseLogicalChannelWithSessionInfo(in int serial, in SessionInfo sessionInfo);
 }
diff --git a/radio/aidl/android/hardware/radio/sim/IRadioSimResponse.aidl b/radio/aidl/android/hardware/radio/sim/IRadioSimResponse.aidl
index b3df504..90f172f 100644
--- a/radio/aidl/android/hardware/radio/sim/IRadioSimResponse.aidl
+++ b/radio/aidl/android/hardware/radio/sim/IRadioSimResponse.aidl
@@ -241,6 +241,8 @@
      *   RadioError:NO_MEMORY
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
+     *
+     * @deprecated use iccCloseLogicalChannelWithSessionInfoResponse instead.
      */
     void iccCloseLogicalChannelResponse(in RadioResponseInfo info);
 
@@ -591,4 +593,17 @@
      *   RadioError:NO_RESOURCES
      */
     void updateSimPhonebookRecordsResponse(in RadioResponseInfo info, in int updatedRecordIndex);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void iccCloseLogicalChannelWithSessionInfoResponse(in RadioResponseInfo info);
 }
diff --git a/radio/aidl/android/hardware/radio/sim/SessionInfo.aidl b/radio/aidl/android/hardware/radio/sim/SessionInfo.aidl
new file mode 100644
index 0000000..9e3e8ed
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/sim/SessionInfo.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.sim;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable SessionInfo {
+    /**
+     * Session id of the logical channel from TS 27.007 (+CCHC).
+     */
+    int sessionId;
+    /**
+     * Whether the logical channel was opened for sending ES10 commands.
+     */
+    boolean isEs10 = false;
+}
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioSim.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioSim.h
index ff91aef..f12e532 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioSim.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioSim.h
@@ -41,6 +41,8 @@
     ::ndk::ScopedAStatus getSimPhonebookCapacity(int32_t serial) override;
     ::ndk::ScopedAStatus getSimPhonebookRecords(int32_t serial) override;
     ::ndk::ScopedAStatus iccCloseLogicalChannel(int32_t serial, int32_t channelId) override;
+    ::ndk::ScopedAStatus iccCloseLogicalChannelWithSessionInfo(int32_t serial,
+            const ::aidl::android::hardware::radio::sim::SessionInfo& recordInfo) override;
     ::ndk::ScopedAStatus iccIoForApp(
             int32_t serial, const ::aidl::android::hardware::radio::sim::IccIo& iccIo) override;
     ::ndk::ScopedAStatus iccOpenLogicalChannel(int32_t serial, const std::string& aid,
diff --git a/radio/aidl/compat/libradiocompat/sim/RadioSim.cpp b/radio/aidl/compat/libradiocompat/sim/RadioSim.cpp
index b43f64f..490b07b 100644
--- a/radio/aidl/compat/libradiocompat/sim/RadioSim.cpp
+++ b/radio/aidl/compat/libradiocompat/sim/RadioSim.cpp
@@ -124,6 +124,14 @@
     return ok();
 }
 
+ScopedAStatus RadioSim::iccCloseLogicalChannelWithSessionInfo(int32_t serial,
+                                                        const aidl::SessionInfo& /*SessionInfo*/) {
+    LOG_CALL << serial;
+    LOG(ERROR) << " iccCloseLogicalChannelWithSessionInfo is unsupported by HIDL HALs";
+    respond()->iccCloseLogicalChannelWithSessionInfoResponse(notSupported(serial));
+    return ok();
+}
+
 ScopedAStatus RadioSim::iccIoForApp(int32_t serial, const aidl::IccIo& iccIo) {
     LOG_CALL << serial;
     mHal1_5->iccIOForApp(serial, toHidl(iccIo));
@@ -289,5 +297,4 @@
     }
     return ok();
 }
-
 }  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/vts/radio_sim_response.cpp b/radio/aidl/vts/radio_sim_response.cpp
index 391c9cb..296c65c 100644
--- a/radio/aidl/vts/radio_sim_response.cpp
+++ b/radio/aidl/vts/radio_sim_response.cpp
@@ -118,6 +118,13 @@
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus RadioSimResponse::iccCloseLogicalChannelWithSessionInfoResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
 ndk::ScopedAStatus RadioSimResponse::iccIoForAppResponse(const RadioResponseInfo& info,
                                                          const IccIoResult& /*iccIo*/) {
     rspInfo = info;
diff --git a/radio/aidl/vts/radio_sim_test.cpp b/radio/aidl/vts/radio_sim_test.cpp
index e69247d..44be258 100644
--- a/radio/aidl/vts/radio_sim_test.cpp
+++ b/radio/aidl/vts/radio_sim_test.cpp
@@ -762,6 +762,27 @@
 }
 
 /*
+ * Test IRadioSim.iccCloseLogicalChannelWithSessionInfo() for the response returned.
+ */
+TEST_P(RadioSimTest, iccCloseLogicalChannelWithSessionInfo) {
+    LOG(DEBUG) << "iccCloseLogicalChannelWithSessionInfo";
+    serial = GetRandomSerialNumber();
+    SessionInfo info;
+    memset(&info, 0, sizeof(info));
+    info.sessionId = 0;
+    info.isEs10 = false;
+
+    // Try closing invalid channel and check INVALID_ARGUMENTS returned as error
+    radio_sim->iccCloseLogicalChannelWithSessionInfo(serial, info);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+
+    EXPECT_EQ(RadioError::INVALID_ARGUMENTS, radioRsp_sim->rspInfo.error);
+    LOG(DEBUG) << "iccCloseLogicalChannelWithSessionInfo finished";
+}
+
+/*
  * Test IRadioSim.iccTransmitApduLogicalChannel() for the response returned.
  */
 TEST_P(RadioSimTest, iccTransmitApduLogicalChannel) {
diff --git a/radio/aidl/vts/radio_sim_utils.h b/radio/aidl/vts/radio_sim_utils.h
index 83f1cbc..71c7eb8 100644
--- a/radio/aidl/vts/radio_sim_utils.h
+++ b/radio/aidl/vts/radio_sim_utils.h
@@ -87,6 +87,9 @@
     virtual ndk::ScopedAStatus iccCloseLogicalChannelResponse(
             const RadioResponseInfo& info) override;
 
+    virtual ndk::ScopedAStatus iccCloseLogicalChannelWithSessionInfoResponse(
+            const RadioResponseInfo& info) override;
+
     virtual ndk::ScopedAStatus iccIoForAppResponse(const RadioResponseInfo& info,
                                                    const IccIoResult& iccIo) override;