Add HAL API for enabling DSDS
setModemsConfig and getModemsConfig APIs will allow the framework
to set the number of live modems to switch to single/multi sim state

Bug: 122073700
Test: vts
Change-Id: Ib200ffa5f2aebe21caf2b761407c79828730e6f1
Merged-In: Ib200ffa5f2aebe21caf2b761407c79828730e6f1
diff --git a/radio/config/1.1/Android.bp b/radio/config/1.1/Android.bp
index 056510c..151a0a3 100644
--- a/radio/config/1.1/Android.bp
+++ b/radio/config/1.1/Android.bp
@@ -7,10 +7,10 @@
         enabled: true,
     },
     srcs: [
+        "types.hal",
         "IRadioConfig.hal",
         "IRadioConfigIndication.hal",
         "IRadioConfigResponse.hal",
-        "types.hal",
     ],
     interfaces: [
         "android.hardware.radio.config@1.0",
@@ -19,6 +19,7 @@
     ],
     types: [
         "ModemInfo",
+        "ModemsConfig",
         "PhoneCapability",
     ],
     gen_java: true,
diff --git a/radio/config/1.1/IRadioConfig.hal b/radio/config/1.1/IRadioConfig.hal
index bc63339..7b0c6b6 100644
--- a/radio/config/1.1/IRadioConfig.hal
+++ b/radio/config/1.1/IRadioConfig.hal
@@ -19,6 +19,7 @@
 import @1.0::IRadioConfig;
 import @1.1::IRadioConfigResponse;
 import @1.1::PhoneCapability;
+import @1.1::ModemsConfig;
 
 /**
  * Note: IRadioConfig 1.1 is an intermediate layer between Android P and Android Q.
@@ -56,4 +57,36 @@
      * Response callback is IRadioConfigResponse.setPreferredDataModemResponse()
      */
     oneway setPreferredDataModem(int32_t serial, uint8_t modemId);
+
+   /**
+     * Set modems configurations by specifying the number of live modems (i.e modems that are
+     * enabled and actively working as part of a working telephony stack).
+     *
+     * Example: this interface can be used to switch to single/multi sim mode by specifying
+     * the number of live modems as 1, 2, etc
+     *
+     * Note: by setting the number of live modems in this API, that number of modems will
+     * subsequently get enabled/disabled
+     *
+     * @param serial serial number of request.
+     * @param modemsConfig ModemsConfig object including the number of live modems
+     *
+     * Response callback is IRadioResponse.setModemsConfigResponse()
+     */
+    oneway setModemsConfig(int32_t serial, ModemsConfig modemsConfig);
+
+   /**
+     * Get modems configurations. This interface is used to get modem configurations
+     * which includes the number of live modems (i.e modems that are
+     * enabled and actively working as part of a working telephony stack)
+     *
+     * Note: in order to get the overall number of modems available on the phone,
+     * refer to getPhoneCapability API
+     *
+     * @param serial Serial number of request.
+     *
+     * Response callback is IRadioResponse.getModemsConfigResponse() which
+     * will return <@1.1::ModemsConfig>.
+     */
+    oneway getModemsConfig(int32_t serial);
 };
diff --git a/radio/config/1.1/IRadioConfigResponse.hal b/radio/config/1.1/IRadioConfigResponse.hal
index 42a31b1..d42ff06 100644
--- a/radio/config/1.1/IRadioConfigResponse.hal
+++ b/radio/config/1.1/IRadioConfigResponse.hal
@@ -19,6 +19,7 @@
 import @1.0::IRadioConfigResponse;
 import @1.1::PhoneCapability;
 import android.hardware.radio@1.0::RadioResponseInfo;
+import @1.1::ModemsConfig;
 
 /**
  * Note: IRadioConfig 1.1 is an intermediate layer between Android P and Android Q.
@@ -50,4 +51,27 @@
      *   RadioError:INVALID_ARGUMENTS
      */
     oneway setPreferredDataModemResponse(RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:INVALID_ARGUMENTS
+     */
+    oneway setModemsConfigResponse(RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param modemsConfig <@1.1::ModemsConfig> it defines all the modems' configurations
+     *        at this time, only the number of live modems
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    oneway getModemsConfigResponse(RadioResponseInfo info, ModemsConfig modemsConfig);
 };
diff --git a/radio/config/1.1/types.hal b/radio/config/1.1/types.hal
index a7b9f86..89a4723 100644
--- a/radio/config/1.1/types.hal
+++ b/radio/config/1.1/types.hal
@@ -61,3 +61,11 @@
      */
     vec<ModemInfo> logicalModemList;
 };
+
+struct ModemsConfig {
+    /**
+     * variable to indicate the number of live modems i.e modems that are enabled
+     * and actively working as part of a working connectivity stack
+     */
+    uint8_t numOfLiveModems;
+};
\ No newline at end of file
diff --git a/radio/config/1.1/vts/functional/Android.bp b/radio/config/1.1/vts/functional/Android.bp
new file mode 100644
index 0000000..de909a3
--- /dev/null
+++ b/radio/config/1.1/vts/functional/Android.bp
@@ -0,0 +1,33 @@
+//
+// Copyright (C) 2018 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.
+//
+
+cc_test {
+    name: "VtsHalRadioConfigV1_1TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "radio_config_hidl_hal_api.cpp",
+        "radio_config_hidl_hal_test.cpp",
+        "radio_config_response.cpp",
+        "VtsHalRadioConfigV1_1TargetTest.cpp",
+    ],
+    static_libs: [
+        "RadioVtsTestUtilBase",
+        "android.hardware.radio.config@1.0",
+        "android.hardware.radio.config@1.1",
+    ],
+    header_libs: ["radio.util.header@1.0"],
+    test_suites: ["general-tests"],
+}
diff --git a/radio/config/1.1/vts/functional/VtsHalRadioConfigV1_1TargetTest.cpp b/radio/config/1.1/vts/functional/VtsHalRadioConfigV1_1TargetTest.cpp
new file mode 100644
index 0000000..2fc6b62
--- /dev/null
+++ b/radio/config/1.1/vts/functional/VtsHalRadioConfigV1_1TargetTest.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#include <radio_config_hidl_hal_utils.h>
+
+int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(RadioConfigHidlEnvironment::Instance());
+    ::testing::InitGoogleTest(&argc, argv);
+    RadioConfigHidlEnvironment::Instance()->init(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    LOG(INFO) << "Test result = " << status;
+    return status;
+}
diff --git a/radio/config/1.1/vts/functional/radio_config_hidl_hal_api.cpp b/radio/config/1.1/vts/functional/radio_config_hidl_hal_api.cpp
new file mode 100644
index 0000000..a8e939c
--- /dev/null
+++ b/radio/config/1.1/vts/functional/radio_config_hidl_hal_api.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#include <radio_config_hidl_hal_utils.h>
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+
+/*
+ * Test IRadioConfig.getModemsConfig()
+ */
+TEST_F(RadioConfigHidlTest, getModemsConfig) {
+    serial = GetRandomSerialNumber();
+    Return<void> res = radioConfig->getModemsConfig(serial);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioConfigRsp->rspInfo.type);
+    EXPECT_EQ(serial, radioConfigRsp->rspInfo.serial);
+    ALOGI("getModemsConfig, rspInfo.error = %s\n", toString(radioConfigRsp->rspInfo.error).c_str());
+
+    ASSERT_TRUE(CheckAnyOfErrors(radioConfigRsp->rspInfo.error,
+                                 {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+}
+
+/*
+ * Test IRadioConfig.setModemsConfig()
+ */
+TEST_F(RadioConfigHidlTest, setModemsConfig_invalidArgument) {
+    serial = GetRandomSerialNumber();
+    ModemsConfig* mConfig = new ModemsConfig();
+    Return<void> res = radioConfig->setModemsConfig(serial, *mConfig);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioConfigRsp->rspInfo.type);
+    EXPECT_EQ(serial, radioConfigRsp->rspInfo.serial);
+    ALOGI("setModemsConfig, rspInfo.error = %s\n", toString(radioConfigRsp->rspInfo.error).c_str());
+
+    ASSERT_TRUE(
+            CheckAnyOfErrors(radioConfigRsp->rspInfo.error,
+                             {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+}
+
+/*
+ * Test IRadioConfig.setModemsConfig()
+ */
+TEST_F(RadioConfigHidlTest, setModemsConfig_goodRequest) {
+    serial = GetRandomSerialNumber();
+    ModemsConfig* mConfig = new ModemsConfig();
+    mConfig->numOfLiveModems = 1;
+    Return<void> res = radioConfig->setModemsConfig(serial, *mConfig);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioConfigRsp->rspInfo.type);
+    EXPECT_EQ(serial, radioConfigRsp->rspInfo.serial);
+    ALOGI("setModemsConfig, rspInfo.error = %s\n", toString(radioConfigRsp->rspInfo.error).c_str());
+
+    ASSERT_TRUE(CheckAnyOfErrors(radioConfigRsp->rspInfo.error,
+                                 {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+}
diff --git a/radio/config/1.1/vts/functional/radio_config_hidl_hal_test.cpp b/radio/config/1.1/vts/functional/radio_config_hidl_hal_test.cpp
new file mode 100644
index 0000000..6c1b382
--- /dev/null
+++ b/radio/config/1.1/vts/functional/radio_config_hidl_hal_test.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#include <radio_config_hidl_hal_utils.h>
+
+void RadioConfigHidlTest::SetUp() {
+    radioConfig = ::testing::VtsHalHidlTargetTestBase::getService<IRadioConfig>(
+            RadioConfigHidlEnvironment::Instance()->getServiceName<IRadioConfig>(
+                    hidl_string(RADIO_SERVICE_NAME)));
+    if (radioConfig == NULL) {
+        sleep(60);
+        radioConfig = ::testing::VtsHalHidlTargetTestBase::getService<IRadioConfig>(
+                RadioConfigHidlEnvironment::Instance()->getServiceName<IRadioConfig>(
+                        hidl_string(RADIO_SERVICE_NAME)));
+    }
+    ASSERT_NE(nullptr, radioConfig.get());
+
+    radioConfigRsp = new (std::nothrow) RadioConfigResponse(*this);
+    ASSERT_NE(nullptr, radioConfigRsp.get());
+
+    count_ = 0;
+
+    radioConfig->setResponseFunctions(radioConfigRsp, nullptr);
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioConfigRsp->rspInfo.type);
+    EXPECT_EQ(serial, radioConfigRsp->rspInfo.serial);
+    EXPECT_EQ(RadioError::NONE, radioConfigRsp->rspInfo.error);
+}
+
+/*
+ * Notify that the response message is received.
+ */
+void RadioConfigHidlTest::notify(int receivedSerial) {
+    std::unique_lock<std::mutex> lock(mtx_);
+    if (serial == receivedSerial) {
+        count_++;
+        cv_.notify_one();
+    }
+}
+
+/*
+ * Wait till the response message is notified or till TIMEOUT_PERIOD.
+ */
+std::cv_status RadioConfigHidlTest::wait() {
+    std::unique_lock<std::mutex> lock(mtx_);
+
+    std::cv_status status = std::cv_status::no_timeout;
+    auto now = std::chrono::system_clock::now();
+    while (count_ == 0) {
+        status = cv_.wait_until(lock, now + std::chrono::seconds(TIMEOUT_PERIOD));
+        if (status == std::cv_status::timeout) {
+            return status;
+        }
+    }
+    count_--;
+    return status;
+}
\ No newline at end of file
diff --git a/radio/config/1.1/vts/functional/radio_config_hidl_hal_utils.h b/radio/config/1.1/vts/functional/radio_config_hidl_hal_utils.h
new file mode 100644
index 0000000..592555f
--- /dev/null
+++ b/radio/config/1.1/vts/functional/radio_config_hidl_hal_utils.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#include <android-base/logging.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+#include <chrono>
+#include <condition_variable>
+#include <mutex>
+
+#include <android/hardware/radio/config/1.1/IRadioConfig.h>
+#include <android/hardware/radio/config/1.1/IRadioConfigResponse.h>
+#include <android/hardware/radio/config/1.1/types.h>
+
+#include "vts_test_util.h"
+
+using namespace ::android::hardware::radio::config::V1_1;
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::radio::config::V1_0::SimSlotStatus;
+using ::android::hardware::radio::V1_0::RadioResponseInfo;
+using ::android::hardware::radio::V1_0::RadioResponseType;
+
+#define TIMEOUT_PERIOD 75
+#define RADIO_SERVICE_NAME "slot1"
+
+class RadioConfigHidlTest;
+
+/* Callback class for radio config response */
+class RadioConfigResponse : public IRadioConfigResponse {
+   protected:
+    RadioConfigHidlTest& parent;
+
+   public:
+    RadioResponseInfo rspInfo;
+
+    RadioConfigResponse(RadioConfigHidlTest& parent);
+    virtual ~RadioConfigResponse() = default;
+
+    Return<void> getSimSlotsStatusResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_vec<SimSlotStatus>& slotStatus);
+
+    Return<void> setSimSlotsMappingResponse(const RadioResponseInfo& info);
+
+    Return<void> getPhoneCapabilityResponse(const RadioResponseInfo& info,
+                                            const PhoneCapability& phoneCapability);
+
+    Return<void> setPreferredDataModemResponse(const RadioResponseInfo& info);
+
+    Return<void> getModemsConfigResponse(const RadioResponseInfo& info,
+                                         const ModemsConfig& mConfig);
+
+    Return<void> setModemsConfigResponse(const RadioResponseInfo& info);
+};
+
+// Test environment for Radio HIDL HAL.
+class RadioConfigHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    // get the test environment singleton
+    static RadioConfigHidlEnvironment* Instance() {
+        static RadioConfigHidlEnvironment* instance = new RadioConfigHidlEnvironment;
+        return instance;
+    }
+    virtual void registerTestServices() override { registerTestService<IRadioConfig>(); }
+
+   private:
+    RadioConfigHidlEnvironment() {}
+};
+
+// The main test class for Radio config HIDL.
+class RadioConfigHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   protected:
+    std::mutex mtx_;
+    std::condition_variable cv_;
+    int count_;
+
+   public:
+    virtual void SetUp() override;
+
+    /* Used as a mechanism to inform the test about data/event callback */
+    void notify(int receivedSerial);
+
+    /* Test code calls this function to wait for response */
+    std::cv_status wait();
+
+    void updateSimCardStatus();
+
+    /* Serial number for radio request */
+    int serial;
+
+    /* radio config service handle */
+    sp<IRadioConfig> radioConfig;
+
+    /* radio config response handle */
+    sp<RadioConfigResponse> radioConfigRsp;
+};
diff --git a/radio/config/1.1/vts/functional/radio_config_response.cpp b/radio/config/1.1/vts/functional/radio_config_response.cpp
new file mode 100644
index 0000000..6e41aeb
--- /dev/null
+++ b/radio/config/1.1/vts/functional/radio_config_response.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#include <radio_config_hidl_hal_utils.h>
+
+// SimSlotStatus slotStatus;
+
+RadioConfigResponse::RadioConfigResponse(RadioConfigHidlTest& parent) : parent(parent) {}
+
+Return<void> RadioConfigResponse::getSimSlotsStatusResponse(
+        const RadioResponseInfo& /* info */,
+        const ::android::hardware::hidl_vec<SimSlotStatus>& /* slotStatus */) {
+    return Void();
+}
+
+Return<void> RadioConfigResponse::setSimSlotsMappingResponse(const RadioResponseInfo& /* info */) {
+    return Void();
+}
+
+Return<void> RadioConfigResponse::getPhoneCapabilityResponse(
+        const RadioResponseInfo& /* info */, const PhoneCapability& /* phoneCapability */) {
+    return Void();
+}
+
+Return<void> RadioConfigResponse::setPreferredDataModemResponse(
+        const RadioResponseInfo& /* info */) {
+    return Void();
+}
+
+Return<void> RadioConfigResponse::getModemsConfigResponse(const RadioResponseInfo& /* info */,
+                                                          const ModemsConfig& /* mConfig */) {
+    return Void();
+}
+
+Return<void> RadioConfigResponse::setModemsConfigResponse(const RadioResponseInfo& /* info */) {
+    return Void();
+}
\ No newline at end of file