Implement RadioModem for AIDL-HIDL Telephony HAL translator

Bug: 203699028
Test: Boot and grep logcat against radiocompat
Change-Id: I670f78af2cd7a0ce0b49dfc802fd363f47d9b6a6
diff --git a/radio/aidl/compat/libradiocompat/Android.bp b/radio/aidl/compat/libradiocompat/Android.bp
index 715a1c2..43d9378 100644
--- a/radio/aidl/compat/libradiocompat/Android.bp
+++ b/radio/aidl/compat/libradiocompat/Android.bp
@@ -39,6 +39,7 @@
         "android.hardware.radio.config@1.3",
         "android.hardware.radio.data-V1-ndk",
         "android.hardware.radio.messaging-V1-ndk",
+        "android.hardware.radio.modem-V1-ndk",
         "android.hardware.radio.network-V1-ndk",
         "android.hardware.radio.sim-V1-ndk",
         "android.hardware.radio.voice-V1-ndk",
@@ -56,7 +57,6 @@
     ],
     srcs: [
         "RadioCompatBase.cpp",
-        "RadioIndication.cpp",
         "RadioResponse.cpp",
         "commonStructs.cpp",
         "config/RadioConfig.cpp",
@@ -71,6 +71,10 @@
         "messaging/RadioMessaging.cpp",
         "messaging/RadioResponse-messaging.cpp",
         "messaging/structs.cpp",
+        "modem/RadioIndication-modem.cpp",
+        "modem/RadioResponse-modem.cpp",
+        "modem/RadioModem.cpp",
+        "modem/structs.cpp",
         "network/RadioIndication-network.cpp",
         "network/RadioNetwork.cpp",
         "network/RadioResponse-network.cpp",
diff --git a/radio/aidl/compat/libradiocompat/RadioResponse.cpp b/radio/aidl/compat/libradiocompat/RadioResponse.cpp
index a39f575..35b0ac1 100644
--- a/radio/aidl/compat/libradiocompat/RadioResponse.cpp
+++ b/radio/aidl/compat/libradiocompat/RadioResponse.cpp
@@ -18,9 +18,6 @@
 
 #include "debug.h"
 
-// TODO(b/203699028): remove when fully implemented
-#pragma GCC diagnostic ignored "-Wunused-parameter"
-
 #define RADIO_MODULE "Common"
 
 namespace android::hardware::radio::compat {
@@ -30,87 +27,11 @@
     // TODO(b/203699028): send to correct requestor or confirm if spam is not a problem
     if (mDataCb) mDataCb->acknowledgeRequest(serial);
     if (mMessagingCb) mMessagingCb->acknowledgeRequest(serial);
+    if (mModemCb) mModemCb->acknowledgeRequest(serial);
     if (mNetworkCb) mNetworkCb->acknowledgeRequest(serial);
     if (mSimCb) mSimCb->acknowledgeRequest(serial);
     if (mVoiceCb) mVoiceCb->acknowledgeRequest(serial);
     return {};
 }
 
-Return<void> RadioResponse::setRadioPowerResponse(const V1_0::RadioResponseInfo& info) {
-    return {};
-}
-
-Return<void> RadioResponse::getBasebandVersionResponse(const V1_0::RadioResponseInfo& info,
-                                                       const hidl_string& version) {
-    return {};
-}
-
-Return<void> RadioResponse::getDeviceIdentityResponse(  //
-        const V1_0::RadioResponseInfo& info, const hidl_string& imei, const hidl_string& imeisv,
-        const hidl_string& esn, const hidl_string& meid) {
-    return {};
-}
-
-Return<void> RadioResponse::nvReadItemResponse(const V1_0::RadioResponseInfo& info,
-                                               const hidl_string& result) {
-    return {};
-}
-
-Return<void> RadioResponse::nvWriteItemResponse(const V1_0::RadioResponseInfo& info) {
-    return {};
-}
-
-Return<void> RadioResponse::nvWriteCdmaPrlResponse(const V1_0::RadioResponseInfo& info) {
-    return {};
-}
-
-Return<void> RadioResponse::nvResetConfigResponse(const V1_0::RadioResponseInfo& info) {
-    return {};
-}
-
-Return<void> RadioResponse::getHardwareConfigResponse(
-        const V1_0::RadioResponseInfo& info, const hidl_vec<V1_0::HardwareConfig>& config) {
-    return {};
-}
-
-Return<void> RadioResponse::requestShutdownResponse(const V1_0::RadioResponseInfo& info) {
-    return {};
-}
-
-Return<void> RadioResponse::getRadioCapabilityResponse(const V1_0::RadioResponseInfo& info,
-                                                       const V1_0::RadioCapability& rc) {
-    return {};
-}
-
-Return<void> RadioResponse::setRadioCapabilityResponse(const V1_0::RadioResponseInfo& info,
-                                                       const V1_0::RadioCapability& rc) {
-    return {};
-}
-
-Return<void> RadioResponse::getModemActivityInfoResponse(
-        const V1_0::RadioResponseInfo& info, const V1_0::ActivityStatsInfo& activityInfo) {
-    return {};
-}
-
-Return<void> RadioResponse::sendDeviceStateResponse(const V1_0::RadioResponseInfo& info) {
-    return {};
-}
-
-Return<void> RadioResponse::enableModemResponse(const V1_0::RadioResponseInfo& info) {
-    return {};
-}
-
-Return<void> RadioResponse::getModemStackStatusResponse(const V1_0::RadioResponseInfo& info,
-                                                        bool isEnabled) {
-    return {};
-}
-
-Return<void> RadioResponse::setRadioPowerResponse_1_5(const V1_0::RadioResponseInfo& info) {
-    return {};
-}
-
-Return<void> RadioResponse::setRadioPowerResponse_1_6(const V1_6::RadioResponseInfo& info) {
-    return {};
-}
-
 }  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/collections.h b/radio/aidl/compat/libradiocompat/collections.h
index e3439a7..082ef17 100644
--- a/radio/aidl/compat/libradiocompat/collections.h
+++ b/radio/aidl/compat/libradiocompat/collections.h
@@ -55,6 +55,22 @@
 }
 
 /**
+ * Converts hidl_array<T> HIDL list to std::vector<T> AIDL list.
+ *
+ * To convert values, the template uses toAidl functions for a given type T, assuming it's defined.
+ *
+ * \param inp array to convert
+ */
+template <typename T, size_t N>
+auto toAidl(const hidl_array<T, N>& inp) {
+    std::vector<decltype(toAidl(T{}))> out(N);
+    for (size_t i = 0; i < N; i++) {
+        out[i] = toAidl(inp[i]);
+    }
+    return out;
+}
+
+/**
  * Converts T=OptionalX HIDL value to std::optional<X> AIDL value.
  *
  * To convert values, the template uses toAidl functions for a given type T.value.
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioIndication.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioIndication.h
index 51cdccb..20e0973 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioIndication.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioIndication.h
@@ -17,6 +17,7 @@
 
 #include <aidl/android/hardware/radio/data/IRadioDataIndication.h>
 #include <aidl/android/hardware/radio/messaging/IRadioMessagingIndication.h>
+#include <aidl/android/hardware/radio/modem/IRadioModemIndication.h>
 #include <aidl/android/hardware/radio/network/IRadioNetworkIndication.h>
 #include <aidl/android/hardware/radio/sim/IRadioSimIndication.h>
 #include <aidl/android/hardware/radio/voice/IRadioVoiceIndication.h>
@@ -28,6 +29,7 @@
     std::shared_ptr<::aidl::android::hardware::radio::data::IRadioDataIndication> mDataCb;
     std::shared_ptr<::aidl::android::hardware::radio::messaging::IRadioMessagingIndication>
             mMessagingCb;
+    std::shared_ptr<::aidl::android::hardware::radio::modem::IRadioModemIndication> mModemCb;
     std::shared_ptr<::aidl::android::hardware::radio::network::IRadioNetworkIndication> mNetworkCb;
     std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimIndication> mSimCb;
     std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceIndication> mVoiceCb;
@@ -185,6 +187,8 @@
             std::shared_ptr<::aidl::android::hardware::radio::messaging::IRadioMessagingIndication>
                     radioMessagingIndication);
     void setResponseFunction(
+            std::shared_ptr<::aidl::android::hardware::radio::modem::IRadioModemIndication> modmCb);
+    void setResponseFunction(
             std::shared_ptr<::aidl::android::hardware::radio::network::IRadioNetworkIndication> ni);
     void setResponseFunction(
             std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimIndication> simCb);
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioModem.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioModem.h
new file mode 100644
index 0000000..666ff47
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioModem.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+#pragma once
+
+#include "RadioCompatBase.h"
+
+#include <aidl/android/hardware/radio/modem/BnRadioModem.h>
+
+namespace android::hardware::radio::compat {
+
+class RadioModem : public RadioCompatBase,
+                   public aidl::android::hardware::radio::modem::BnRadioModem {
+    ::ndk::ScopedAStatus enableModem(int32_t serial, bool on) override;
+    ::ndk::ScopedAStatus getBasebandVersion(int32_t serial) override;
+    ::ndk::ScopedAStatus getDeviceIdentity(int32_t serial) override;
+    ::ndk::ScopedAStatus getHardwareConfig(int32_t serial) override;
+    ::ndk::ScopedAStatus getModemActivityInfo(int32_t serial) override;
+    ::ndk::ScopedAStatus getModemStackStatus(int32_t serial) override;
+    ::ndk::ScopedAStatus getRadioCapability(int32_t serial) override;
+    ::ndk::ScopedAStatus nvReadItem(
+            int32_t serial, ::aidl::android::hardware::radio::modem::NvItem itemId) override;
+    ::ndk::ScopedAStatus nvResetConfig(
+            int32_t serial, ::aidl::android::hardware::radio::modem::ResetNvType type) override;
+    ::ndk::ScopedAStatus nvWriteCdmaPrl(int32_t serial, const std::vector<uint8_t>& prl) override;
+    ::ndk::ScopedAStatus nvWriteItem(
+            int32_t serial, const ::aidl::android::hardware::radio::modem::NvWriteItem& i) override;
+    ::ndk::ScopedAStatus requestShutdown(int32_t serial) override;
+    ::ndk::ScopedAStatus responseAcknowledgement() override;
+    ::ndk::ScopedAStatus sendDeviceState(
+            int32_t serial, ::aidl::android::hardware::radio::modem::DeviceStateType stateType,
+            bool state) override;
+    ::ndk::ScopedAStatus setRadioCapability(
+            int32_t s, const ::aidl::android::hardware::radio::modem::RadioCapability& rc) override;
+    ::ndk::ScopedAStatus setRadioPower(int32_t serial, bool powerOn, bool forEmergencyCall,
+                                       bool preferredForEmergencyCall) override;
+    ::ndk::ScopedAStatus setResponseFunctions(
+            const std::shared_ptr<::aidl::android::hardware::radio::modem::IRadioModemResponse>&
+                    radioModemResponse,
+            const std::shared_ptr<::aidl::android::hardware::radio::modem::IRadioModemIndication>&
+                    radioModemIndication) override;
+
+  public:
+    using RadioCompatBase::RadioCompatBase;
+};
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioResponse.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioResponse.h
index 826d385..5db963f 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioResponse.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioResponse.h
@@ -17,6 +17,7 @@
 
 #include <aidl/android/hardware/radio/data/IRadioDataResponse.h>
 #include <aidl/android/hardware/radio/messaging/IRadioMessagingResponse.h>
+#include <aidl/android/hardware/radio/modem/IRadioModemResponse.h>
 #include <aidl/android/hardware/radio/network/IRadioNetworkResponse.h>
 #include <aidl/android/hardware/radio/sim/IRadioSimResponse.h>
 #include <aidl/android/hardware/radio/voice/IRadioVoiceResponse.h>
@@ -28,6 +29,7 @@
     std::shared_ptr<::aidl::android::hardware::radio::data::IRadioDataResponse> mDataCb;
     std::shared_ptr<::aidl::android::hardware::radio::messaging::IRadioMessagingResponse>
             mMessagingCb;
+    std::shared_ptr<::aidl::android::hardware::radio::modem::IRadioModemResponse> mModemCb;
     std::shared_ptr<::aidl::android::hardware::radio::network::IRadioNetworkResponse> mNetworkCb;
     std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimResponse> mSimCb;
     std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceResponse> mVoiceCb;
@@ -413,6 +415,8 @@
             std::shared_ptr<::aidl::android::hardware::radio::messaging::IRadioMessagingResponse>
                     radioMessagingResponse);
     void setResponseFunction(
+            std::shared_ptr<::aidl::android::hardware::radio::modem::IRadioModemResponse> modemCb);
+    void setResponseFunction(
             std::shared_ptr<::aidl::android::hardware::radio::network::IRadioNetworkResponse> nwCb);
     void setResponseFunction(
             std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimResponse> simCb);
diff --git a/radio/aidl/compat/libradiocompat/RadioIndication.cpp b/radio/aidl/compat/libradiocompat/modem/RadioIndication-modem.cpp
similarity index 60%
rename from radio/aidl/compat/libradiocompat/RadioIndication.cpp
rename to radio/aidl/compat/libradiocompat/modem/RadioIndication-modem.cpp
index df97841..8fc4da6 100644
--- a/radio/aidl/compat/libradiocompat/RadioIndication.cpp
+++ b/radio/aidl/compat/libradiocompat/modem/RadioIndication-modem.cpp
@@ -16,32 +16,57 @@
 
 #include <libradiocompat/RadioIndication.h>
 
-// TODO(b/203699028): remove when fully implemented
-#pragma GCC diagnostic ignored "-Wunused-parameter"
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "ModemIndication"
 
 namespace android::hardware::radio::compat {
 
-Return<void> RadioIndication::radioStateChanged(V1_0::RadioIndicationType type,
-                                                V1_0::RadioState radioState) {
-    return {};
-}
+namespace aidl = ::aidl::android::hardware::radio::modem;
 
-Return<void> RadioIndication::rilConnected(V1_0::RadioIndicationType type) {
-    return {};
+void RadioIndication::setResponseFunction(std::shared_ptr<aidl::IRadioModemIndication> modemCb) {
+    CHECK(modemCb);
+    mModemCb = modemCb;
 }
 
 Return<void> RadioIndication::hardwareConfigChanged(V1_0::RadioIndicationType type,
                                                     const hidl_vec<V1_0::HardwareConfig>& configs) {
+    LOG_CALL << type;
+    CHECK_CB(mModemCb);
+    mModemCb->hardwareConfigChanged(toAidl(type), toAidl(configs));
+    return {};
+}
+
+Return<void> RadioIndication::modemReset(V1_0::RadioIndicationType type, const hidl_string& reasn) {
+    LOG_CALL << type;
+    CHECK_CB(mModemCb);
+    mModemCb->modemReset(toAidl(type), reasn);
     return {};
 }
 
 Return<void> RadioIndication::radioCapabilityIndication(V1_0::RadioIndicationType type,
                                                         const V1_0::RadioCapability& rc) {
+    LOG_CALL << type;
+    CHECK_CB(mModemCb);
+    mModemCb->radioCapabilityIndication(toAidl(type), toAidl(rc));
     return {};
 }
 
-Return<void> RadioIndication::modemReset(V1_0::RadioIndicationType type,
-                                         const hidl_string& reason) {
+Return<void> RadioIndication::radioStateChanged(V1_0::RadioIndicationType t, V1_0::RadioState st) {
+    LOG_CALL << t;
+    CHECK_CB(mModemCb);
+    mModemCb->radioStateChanged(toAidl(t), aidl::RadioState(st));
+    return {};
+}
+
+Return<void> RadioIndication::rilConnected(V1_0::RadioIndicationType type) {
+    LOG_CALL << type;
+    CHECK_CB(mModemCb);
+    mModemCb->rilConnected(toAidl(type));
     return {};
 }
 
diff --git a/radio/aidl/compat/libradiocompat/modem/RadioModem.cpp b/radio/aidl/compat/libradiocompat/modem/RadioModem.cpp
new file mode 100644
index 0000000..660ae9f
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/modem/RadioModem.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2021 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 <libradiocompat/RadioModem.h>
+
+#include "debug.h"
+#include "structs.h"
+
+#define RADIO_MODULE "Modem"
+
+namespace android::hardware::radio::compat {
+
+using ::ndk::ScopedAStatus;
+namespace aidl = ::aidl::android::hardware::radio::modem;
+constexpr auto ok = &ScopedAStatus::ok;
+
+ScopedAStatus RadioModem::enableModem(int32_t serial, bool on) {
+    LOG_CALL << serial;
+    mHal1_5->enableModem(serial, on);
+    return ok();
+}
+
+ScopedAStatus RadioModem::getBasebandVersion(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getBasebandVersion(serial);
+    return ok();
+}
+
+ScopedAStatus RadioModem::getDeviceIdentity(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getDeviceIdentity(serial);
+    return ok();
+}
+
+ScopedAStatus RadioModem::getHardwareConfig(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getHardwareConfig(serial);
+    return ok();
+}
+
+ScopedAStatus RadioModem::getModemActivityInfo(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getModemActivityInfo(serial);
+    return ok();
+}
+
+ScopedAStatus RadioModem::getModemStackStatus(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getModemStackStatus(serial);
+    return ok();
+}
+
+ScopedAStatus RadioModem::getRadioCapability(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getRadioCapability(serial);
+    return ok();
+}
+
+ScopedAStatus RadioModem::nvReadItem(int32_t serial, aidl::NvItem itemId) {
+    LOG_CALL << serial;
+    mHal1_5->nvReadItem(serial, V1_0::NvItem(itemId));
+    return ok();
+}
+
+ScopedAStatus RadioModem::nvResetConfig(int32_t serial, aidl::ResetNvType resetType) {
+    LOG_CALL << serial;
+    mHal1_5->nvResetConfig(serial, V1_0::ResetNvType(resetType));
+    return ok();
+}
+
+ScopedAStatus RadioModem::nvWriteCdmaPrl(int32_t serial, const std::vector<uint8_t>& prl) {
+    LOG_CALL << serial;
+    mHal1_5->nvWriteCdmaPrl(serial, prl);
+    return ok();
+}
+
+ScopedAStatus RadioModem::nvWriteItem(int32_t serial, const aidl::NvWriteItem& item) {
+    LOG_CALL << serial;
+    mHal1_5->nvWriteItem(serial, toHidl(item));
+    return ok();
+}
+
+ScopedAStatus RadioModem::requestShutdown(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->requestShutdown(serial);
+    return ok();
+}
+
+ScopedAStatus RadioModem::responseAcknowledgement() {
+    LOG_CALL;
+    mHal1_5->responseAcknowledgement();
+    return ok();
+}
+
+ScopedAStatus RadioModem::sendDeviceState(int32_t serial, aidl::DeviceStateType type, bool state) {
+    LOG_CALL << serial;
+    mHal1_5->sendDeviceState(serial, V1_0::DeviceStateType(type), state);
+    return ok();
+}
+
+ScopedAStatus RadioModem::setRadioCapability(int32_t serial, const aidl::RadioCapability& rc) {
+    LOG_CALL << serial;
+    mHal1_5->setRadioCapability(serial, toHidl(rc));
+    return ok();
+}
+
+ScopedAStatus RadioModem::setRadioPower(int32_t serial, bool powerOn, bool forEmergencyCall,
+                                        bool preferredForEmergencyCall) {
+    LOG_CALL << serial;
+    if (mHal1_6) {
+        mHal1_6->setRadioPower_1_6(serial, powerOn, forEmergencyCall, preferredForEmergencyCall);
+    } else {
+        mHal1_5->setRadioPower_1_5(serial, powerOn, forEmergencyCall, preferredForEmergencyCall);
+    }
+    return ok();
+}
+
+ScopedAStatus RadioModem::setResponseFunctions(
+        const std::shared_ptr<aidl::IRadioModemResponse>& modemResponse,
+        const std::shared_ptr<aidl::IRadioModemIndication>& modemIndication) {
+    LOG_CALL << modemResponse << ' ' << modemIndication;
+
+    CHECK(modemResponse);
+    CHECK(modemIndication);
+
+    mRadioResponse->setResponseFunction(modemResponse);
+    mRadioIndication->setResponseFunction(modemIndication);
+
+    return ok();
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/modem/RadioResponse-modem.cpp b/radio/aidl/compat/libradiocompat/modem/RadioResponse-modem.cpp
new file mode 100644
index 0000000..300627c
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/modem/RadioResponse-modem.cpp
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2021 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 <libradiocompat/RadioResponse.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "ModemResponse"
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::modem;
+
+void RadioResponse::setResponseFunction(std::shared_ptr<aidl::IRadioModemResponse> modemCb) {
+    CHECK(modemCb);
+    mModemCb = modemCb;
+}
+
+Return<void> RadioResponse::enableModemResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mModemCb);
+    mModemCb->enableModemResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::getBasebandVersionResponse(const V1_0::RadioResponseInfo& info,
+                                                       const hidl_string& version) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mModemCb);
+    mModemCb->getBasebandVersionResponse(toAidl(info), version);
+    return {};
+}
+
+Return<void> RadioResponse::getDeviceIdentityResponse(  //
+        const V1_0::RadioResponseInfo& info, const hidl_string& imei, const hidl_string& imeisv,
+        const hidl_string& esn, const hidl_string& meid) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mModemCb);
+    mModemCb->getDeviceIdentityResponse(toAidl(info), imei, imeisv, esn, meid);
+    return {};
+}
+
+Return<void> RadioResponse::getHardwareConfigResponse(
+        const V1_0::RadioResponseInfo& info, const hidl_vec<V1_0::HardwareConfig>& config) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mModemCb);
+    mModemCb->getHardwareConfigResponse(toAidl(info), toAidl(config));
+    return {};
+}
+
+Return<void> RadioResponse::getModemActivityInfoResponse(
+        const V1_0::RadioResponseInfo& info, const V1_0::ActivityStatsInfo& activityInfo) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mModemCb);
+    mModemCb->getModemActivityInfoResponse(toAidl(info), toAidl(activityInfo));
+    return {};
+}
+
+Return<void> RadioResponse::getModemStackStatusResponse(const V1_0::RadioResponseInfo& info,
+                                                        bool isEnabled) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mModemCb);
+    mModemCb->getModemStackStatusResponse(toAidl(info), isEnabled);
+    return {};
+}
+
+Return<void> RadioResponse::getRadioCapabilityResponse(const V1_0::RadioResponseInfo& info,
+                                                       const V1_0::RadioCapability& rc) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mModemCb);
+    mModemCb->getRadioCapabilityResponse(toAidl(info), toAidl(rc));
+    return {};
+}
+
+Return<void> RadioResponse::nvReadItemResponse(const V1_0::RadioResponseInfo& info,
+                                               const hidl_string& result) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mModemCb);
+    mModemCb->nvReadItemResponse(toAidl(info), result);
+    return {};
+}
+
+Return<void> RadioResponse::nvResetConfigResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mModemCb);
+    mModemCb->nvResetConfigResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::nvWriteCdmaPrlResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mModemCb);
+    mModemCb->nvWriteCdmaPrlResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::nvWriteItemResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mModemCb);
+    mModemCb->nvWriteItemResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::requestShutdownResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mModemCb);
+    mModemCb->requestShutdownResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::sendDeviceStateResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mModemCb);
+    mModemCb->sendDeviceStateResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setRadioCapabilityResponse(const V1_0::RadioResponseInfo& info,
+                                                       const V1_0::RadioCapability& rc) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mModemCb);
+    mModemCb->setRadioCapabilityResponse(toAidl(info), toAidl(rc));
+    return {};
+}
+
+Return<void> RadioResponse::setRadioPowerResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mModemCb);
+    mModemCb->setRadioPowerResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setRadioPowerResponse_1_5(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mModemCb);
+    mModemCb->setRadioPowerResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setRadioPowerResponse_1_6(const V1_6::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mModemCb);
+    mModemCb->setRadioPowerResponse(toAidl(info));
+    return {};
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/modem/structs.cpp b/radio/aidl/compat/libradiocompat/modem/structs.cpp
new file mode 100644
index 0000000..c1cd64c
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/modem/structs.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2021 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 "structs.h"
+
+#include "commonStructs.h"
+
+#include "collections.h"
+
+#include <android-base/logging.h>
+
+namespace android::hardware::radio::compat {
+
+using ::aidl::android::hardware::radio::RadioAccessFamily;
+using ::aidl::android::hardware::radio::RadioTechnology;
+namespace aidl = ::aidl::android::hardware::radio::modem;
+
+V1_0::NvWriteItem toHidl(const aidl::NvWriteItem& item) {
+    return {
+            .itemId = V1_0::NvItem{item.itemId},
+            .value = item.value,
+    };
+}
+
+aidl::RadioCapability toAidl(const V1_0::RadioCapability& capa) {
+    return {
+            .session = capa.session,
+            .phase = static_cast<int32_t>(capa.phase),
+            .raf = RadioAccessFamily(capa.raf),
+            .logicalModemUuid = capa.logicalModemUuid,
+            .status = static_cast<int32_t>(capa.status),
+    };
+}
+
+V1_0::RadioCapability toHidl(const aidl::RadioCapability& capa) {
+    return {
+            .session = capa.session,
+            .phase = V1_0::RadioCapabilityPhase{capa.phase},
+            .raf = toHidlBitfield<V1_0::RadioAccessFamily>(capa.raf),
+            .logicalModemUuid = capa.logicalModemUuid,
+            .status = V1_0::RadioCapabilityStatus{capa.status},
+    };
+}
+
+aidl::HardwareConfig toAidl(const V1_0::HardwareConfig& config) {
+    return {
+            .type = static_cast<int32_t>(config.type),
+            .uuid = config.uuid,
+            .state = static_cast<int32_t>(config.state),
+            .modem = toAidl(config.modem),
+            .sim = toAidl(config.sim),
+    };
+}
+
+aidl::HardwareConfigModem toAidl(const V1_0::HardwareConfigModem& modem) {
+    return {
+            .rilModel = modem.rilModel,
+            .rat = RadioTechnology(modem.rat),
+            .maxVoiceCalls = modem.maxVoice,
+            .maxDataCalls = modem.maxData,
+            .maxStandby = modem.maxStandby,
+    };
+}
+
+aidl::HardwareConfigSim toAidl(const V1_0::HardwareConfigSim& sim) {
+    return {
+            .modemUuid = sim.modemUuid,
+    };
+}
+
+aidl::ActivityStatsInfo toAidl(const V1_0::ActivityStatsInfo& info) {
+    return {
+            .sleepModeTimeMs = static_cast<int32_t>(info.sleepModeTimeMs),
+            .idleModeTimeMs = static_cast<int32_t>(info.idleModeTimeMs),
+            .txmModetimeMs = toAidl(info.txmModetimeMs),
+            .rxModeTimeMs = static_cast<int32_t>(info.rxModeTimeMs),
+    };
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/modem/structs.h b/radio/aidl/compat/libradiocompat/modem/structs.h
new file mode 100644
index 0000000..3ac1edb
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/modem/structs.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+#pragma once
+
+#include <aidl/android/hardware/radio/modem/ActivityStatsInfo.h>
+#include <aidl/android/hardware/radio/modem/HardwareConfig.h>
+#include <aidl/android/hardware/radio/modem/HardwareConfigModem.h>
+#include <aidl/android/hardware/radio/modem/HardwareConfigSim.h>
+#include <aidl/android/hardware/radio/modem/NvWriteItem.h>
+#include <aidl/android/hardware/radio/modem/RadioCapability.h>
+#include <android/hardware/radio/1.0/types.h>
+
+namespace android::hardware::radio::compat {
+
+V1_0::NvWriteItem toHidl(const ::aidl::android::hardware::radio::modem::NvWriteItem& item);
+
+::aidl::android::hardware::radio::modem::RadioCapability toAidl(const V1_0::RadioCapability& capa);
+V1_0::RadioCapability toHidl(const ::aidl::android::hardware::radio::modem::RadioCapability& capa);
+
+::aidl::android::hardware::radio::modem::HardwareConfig toAidl(const V1_0::HardwareConfig& config);
+
+::aidl::android::hardware::radio::modem::HardwareConfigModem  //
+toAidl(const V1_0::HardwareConfigModem& modem);
+
+::aidl::android::hardware::radio::modem::HardwareConfigSim toAidl(const V1_0::HardwareConfigSim& s);
+
+::aidl::android::hardware::radio::modem::ActivityStatsInfo toAidl(const V1_0::ActivityStatsInfo& i);
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/service/Android.bp b/radio/aidl/compat/service/Android.bp
index 0536c1c..52eb71f 100644
--- a/radio/aidl/compat/service/Android.bp
+++ b/radio/aidl/compat/service/Android.bp
@@ -41,6 +41,7 @@
         "android.hardware.radio.config@1.3",
         "android.hardware.radio.data-V1-ndk",
         "android.hardware.radio.messaging-V1-ndk",
+        "android.hardware.radio.modem-V1-ndk",
         "android.hardware.radio.network-V1-ndk",
         "android.hardware.radio.sim-V1-ndk",
         "android.hardware.radio.voice-V1-ndk",
diff --git a/radio/aidl/compat/service/radio-compat.xml b/radio/aidl/compat/service/radio-compat.xml
index d3f4212..a7089e6 100644
--- a/radio/aidl/compat/service/radio-compat.xml
+++ b/radio/aidl/compat/service/radio-compat.xml
@@ -18,6 +18,10 @@
         <fqname>IRadioMessaging/slot1</fqname>
     </hal>
     <hal format="aidl">
+        <name>android.hardware.radio.modem</name>
+        <fqname>IRadioModem/slot1</fqname>
+    </hal>
+    <hal format="aidl">
         <name>android.hardware.radio.network</name>
         <fqname>IRadioNetwork/slot1</fqname>
     </hal>
diff --git a/radio/aidl/compat/service/service.cpp b/radio/aidl/compat/service/service.cpp
index 3d60ffe..2a67569 100644
--- a/radio/aidl/compat/service/service.cpp
+++ b/radio/aidl/compat/service/service.cpp
@@ -23,6 +23,7 @@
 #include <libradiocompat/RadioData.h>
 #include <libradiocompat/RadioIndication.h>
 #include <libradiocompat/RadioMessaging.h>
+#include <libradiocompat/RadioModem.h>
 #include <libradiocompat/RadioNetwork.h>
 #include <libradiocompat/RadioResponse.h>
 #include <libradiocompat/RadioSim.h>
@@ -62,6 +63,7 @@
 
     publishRadioHal<compat::RadioData>(radioHidl, responseCb, indicationCb, slot);
     publishRadioHal<compat::RadioMessaging>(radioHidl, responseCb, indicationCb, slot);
+    publishRadioHal<compat::RadioModem>(radioHidl, responseCb, indicationCb, slot);
     publishRadioHal<compat::RadioNetwork>(radioHidl, responseCb, indicationCb, slot);
     publishRadioHal<compat::RadioSim>(radioHidl, responseCb, indicationCb, slot);
     publishRadioHal<compat::RadioVoice>(radioHidl, responseCb, indicationCb, slot);