Implement RadioVoice for AIDL-HIDL Telephony HAL translator

Bug: 203699028
Test: Boot and grep logcat against radiocompat
Change-Id: Ie2dce95ba1a468c10d92a74bfdca03d2a8d744b0
diff --git a/radio/aidl/compat/libradiocompat/voice/RadioIndication-voice.cpp b/radio/aidl/compat/libradiocompat/voice/RadioIndication-voice.cpp
new file mode 100644
index 0000000..6d9bda8
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/voice/RadioIndication-voice.cpp
@@ -0,0 +1,142 @@
+/*
+ * 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/RadioIndication.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "VoiceIndication"
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::voice;
+
+void RadioIndication::setResponseFunction(std::shared_ptr<aidl::IRadioVoiceIndication> voiceCb) {
+    CHECK(voiceCb);
+    mVoiceCb = voiceCb;
+}
+
+Return<void> RadioIndication::callRing(V1_0::RadioIndicationType type, bool isGsm,
+                                       const V1_0::CdmaSignalInfoRecord& record) {
+    LOG_CALL << type;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->callRing(toAidl(type), isGsm, toAidl(record));
+    return {};
+}
+
+Return<void> RadioIndication::callStateChanged(V1_0::RadioIndicationType type) {
+    LOG_CALL << type;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->callStateChanged(toAidl(type));
+    return {};
+}
+
+Return<void> RadioIndication::cdmaCallWaiting(V1_0::RadioIndicationType type,
+                                              const V1_0::CdmaCallWaiting& callWaitingRecord) {
+    LOG_CALL << type;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->cdmaCallWaiting(toAidl(type), toAidl(callWaitingRecord));
+    return {};
+}
+
+Return<void> RadioIndication::cdmaInfoRec(V1_0::RadioIndicationType type,
+                                          const V1_0::CdmaInformationRecords& records) {
+    LOG_CALL << type;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->cdmaInfoRec(toAidl(type), toAidl(records.infoRec));
+    return {};
+}
+
+Return<void> RadioIndication::cdmaOtaProvisionStatus(V1_0::RadioIndicationType type,
+                                                     V1_0::CdmaOtaProvisionStatus status) {
+    LOG_CALL << type;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->cdmaOtaProvisionStatus(toAidl(type), aidl::CdmaOtaProvisionStatus(status));
+    return {};
+}
+
+Return<void> RadioIndication::currentEmergencyNumberList(
+        V1_0::RadioIndicationType type, const hidl_vec<V1_4::EmergencyNumber>& emergencyNumbers) {
+    LOG_CALL << type;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->currentEmergencyNumberList(toAidl(type), toAidl(emergencyNumbers));
+    return {};
+}
+
+Return<void> RadioIndication::enterEmergencyCallbackMode(V1_0::RadioIndicationType type) {
+    LOG_CALL << type;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->enterEmergencyCallbackMode(toAidl(type));
+    return {};
+}
+
+Return<void> RadioIndication::exitEmergencyCallbackMode(V1_0::RadioIndicationType type) {
+    LOG_CALL << type;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->exitEmergencyCallbackMode(toAidl(type));
+    return {};
+}
+
+Return<void> RadioIndication::indicateRingbackTone(V1_0::RadioIndicationType type, bool start) {
+    LOG_CALL << type;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->indicateRingbackTone(toAidl(type), start);
+    return {};
+}
+
+Return<void> RadioIndication::onSupplementaryServiceIndication(V1_0::RadioIndicationType type,
+                                                               const V1_0::StkCcUnsolSsResult& ss) {
+    LOG_CALL << type;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->onSupplementaryServiceIndication(toAidl(type), toAidl(ss));
+    return {};
+}
+
+Return<void> RadioIndication::resendIncallMute(V1_0::RadioIndicationType type) {
+    LOG_CALL << type;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->resendIncallMute(toAidl(type));
+    return {};
+}
+
+Return<void> RadioIndication::srvccStateNotify(V1_0::RadioIndicationType type,
+                                               V1_0::SrvccState state) {
+    LOG_CALL << type;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->srvccStateNotify(toAidl(type), aidl::SrvccState(state));
+    return {};
+}
+
+Return<void> RadioIndication::stkCallControlAlphaNotify(V1_0::RadioIndicationType type,
+                                                        const hidl_string& alpha) {
+    LOG_CALL << type;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->stkCallControlAlphaNotify(toAidl(type), alpha);
+    return {};
+}
+
+Return<void> RadioIndication::stkCallSetup(V1_0::RadioIndicationType type, int64_t timeout) {
+    LOG_CALL << type;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->stkCallSetup(toAidl(type), timeout);
+    return {};
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/voice/RadioResponse-voice.cpp b/radio/aidl/compat/libradiocompat/voice/RadioResponse-voice.cpp
new file mode 100644
index 0000000..0a64c56
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/voice/RadioResponse-voice.cpp
@@ -0,0 +1,294 @@
+/*
+ * 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 "VoiceResponse"
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::voice;
+
+void RadioResponse::setResponseFunction(std::shared_ptr<aidl::IRadioVoiceResponse> voiceCb) {
+    CHECK(voiceCb);
+    mVoiceCb = voiceCb;
+}
+
+Return<void> RadioResponse::acceptCallResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->acceptCallResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::conferenceResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->conferenceResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::dialResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->dialResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::emergencyDialResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->emergencyDialResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::exitEmergencyCallbackModeResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->exitEmergencyCallbackModeResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::explicitCallTransferResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->explicitCallTransferResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::getCallForwardStatusResponse(
+        const V1_0::RadioResponseInfo& info, const hidl_vec<V1_0::CallForwardInfo>& callFwdInfos) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->getCallForwardStatusResponse(toAidl(info), toAidl(callFwdInfos));
+    return {};
+}
+
+Return<void> RadioResponse::getCallWaitingResponse(const V1_0::RadioResponseInfo& info, bool enable,
+                                                   int32_t serviceClass) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->getCallWaitingResponse(toAidl(info), enable, serviceClass);
+    return {};
+}
+
+Return<void> RadioResponse::getClipResponse(const V1_0::RadioResponseInfo& info,
+                                            V1_0::ClipStatus status) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->getClipResponse(toAidl(info), aidl::ClipStatus(status));
+    return {};
+}
+
+Return<void> RadioResponse::getClirResponse(const V1_0::RadioResponseInfo& info, int32_t n,
+                                            int32_t m) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->getClirResponse(toAidl(info), n, m);
+    return {};
+}
+
+Return<void> RadioResponse::getCurrentCallsResponse(const V1_0::RadioResponseInfo& info,
+                                                    const hidl_vec<V1_0::Call>& calls) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->getCurrentCallsResponse(toAidl(info), toAidl(calls));
+    return {};
+}
+
+Return<void> RadioResponse::getCurrentCallsResponse_1_2(const V1_0::RadioResponseInfo& info,
+                                                        const hidl_vec<V1_2::Call>& calls) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->getCurrentCallsResponse(toAidl(info), toAidl(calls));
+    return {};
+}
+
+Return<void> RadioResponse::getCurrentCallsResponse_1_6(const V1_6::RadioResponseInfo& info,
+                                                        const hidl_vec<V1_6::Call>& calls) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->getCurrentCallsResponse(toAidl(info), toAidl(calls));
+    return {};
+}
+
+Return<void> RadioResponse::getLastCallFailCauseResponse(
+        const V1_0::RadioResponseInfo& info, const V1_0::LastCallFailCauseInfo& failCauseinfo) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->getLastCallFailCauseResponse(toAidl(info), toAidl(failCauseinfo));
+    return {};
+}
+
+Return<void> RadioResponse::getMuteResponse(const V1_0::RadioResponseInfo& info, bool enable) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->getMuteResponse(toAidl(info), enable);
+    return {};
+}
+
+Return<void> RadioResponse::getPreferredVoicePrivacyResponse(const V1_0::RadioResponseInfo& info,
+                                                             bool enable) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->getPreferredVoicePrivacyResponse(toAidl(info), enable);
+    return {};
+}
+
+Return<void> RadioResponse::getTTYModeResponse(const V1_0::RadioResponseInfo& info,
+                                               V1_0::TtyMode mode) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->getTtyModeResponse(toAidl(info), aidl::TtyMode(mode));
+    return {};
+}
+
+Return<void> RadioResponse::handleStkCallSetupRequestFromSimResponse(
+        const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->handleStkCallSetupRequestFromSimResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::hangupConnectionResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->hangupConnectionResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::hangupForegroundResumeBackgroundResponse(
+        const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->hangupForegroundResumeBackgroundResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::hangupWaitingOrBackgroundResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->hangupWaitingOrBackgroundResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::rejectCallResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->rejectCallResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::sendBurstDtmfResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->sendBurstDtmfResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::sendCDMAFeatureCodeResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->sendCdmaFeatureCodeResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::sendDtmfResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->sendDtmfResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::separateConnectionResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->separateConnectionResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setCallForwardResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->setCallForwardResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setCallWaitingResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->setCallWaitingResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setClirResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->setClirResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setMuteResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->setMuteResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setPreferredVoicePrivacyResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->setPreferredVoicePrivacyResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setTTYModeResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->setTtyModeResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::startDtmfResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->startDtmfResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::stopDtmfResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->stopDtmfResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::switchWaitingOrHoldingAndActiveResponse(
+        const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    CHECK_CB(mVoiceCb);
+    mVoiceCb->switchWaitingOrHoldingAndActiveResponse(toAidl(info));
+    return {};
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/voice/RadioVoice.cpp b/radio/aidl/compat/libradiocompat/voice/RadioVoice.cpp
new file mode 100644
index 0000000..16c6b14
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/voice/RadioVoice.cpp
@@ -0,0 +1,270 @@
+/*
+ * 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/RadioVoice.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "Voice"
+
+namespace android::hardware::radio::compat {
+
+using ::ndk::ScopedAStatus;
+namespace aidl = ::aidl::android::hardware::radio::voice;
+constexpr auto ok = &ScopedAStatus::ok;
+
+ScopedAStatus RadioVoice::acceptCall(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->acceptCall(serial);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::conference(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->conference(serial);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::dial(int32_t serial, const aidl::Dial& dialInfo) {
+    LOG_CALL << serial;
+    mHal1_5->dial(serial, toHidl(dialInfo));
+    return ok();
+}
+
+ScopedAStatus RadioVoice::emergencyDial(  //
+        int32_t serial, const aidl::Dial& dialInfo, aidl::EmergencyServiceCategory categories,
+        const std::vector<std::string>& urns, aidl::EmergencyCallRouting routing,
+        bool hasKnownUserIntentEmerg, bool isTesting) {
+    LOG_CALL << serial;
+    mHal1_5->emergencyDial(serial, toHidl(dialInfo),
+                           toHidlBitfield<V1_4::EmergencyServiceCategory>(categories), toHidl(urns),
+                           V1_4::EmergencyCallRouting(routing), hasKnownUserIntentEmerg, isTesting);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::exitEmergencyCallbackMode(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->exitEmergencyCallbackMode(serial);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::explicitCallTransfer(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->explicitCallTransfer(serial);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::getCallForwardStatus(int32_t serial,
+                                               const aidl::CallForwardInfo& callInfo) {
+    LOG_CALL << serial;
+    mHal1_5->getCallForwardStatus(serial, toHidl(callInfo));
+    return ok();
+}
+
+ScopedAStatus RadioVoice::getCallWaiting(int32_t serial, int32_t serviceClass) {
+    LOG_CALL << serial;
+    mHal1_5->getCallWaiting(serial, serviceClass);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::getClip(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getClip(serial);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::getClir(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getClir(serial);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::getCurrentCalls(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getCurrentCalls(serial);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::getLastCallFailCause(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getLastCallFailCause(serial);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::getMute(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getMute(serial);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::getPreferredVoicePrivacy(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getPreferredVoicePrivacy(serial);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::getTtyMode(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getTTYMode(serial);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::handleStkCallSetupRequestFromSim(int32_t serial, bool accept) {
+    LOG_CALL << serial;
+    mHal1_5->handleStkCallSetupRequestFromSim(serial, accept);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::hangup(int32_t serial, int32_t gsmIndex) {
+    LOG_CALL << serial;
+    mHal1_5->hangup(serial, gsmIndex);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::hangupForegroundResumeBackground(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->hangupForegroundResumeBackground(serial);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::hangupWaitingOrBackground(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->hangupWaitingOrBackground(serial);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::isVoNrEnabled(int32_t serial) {
+    LOG_CALL << serial;
+    // TODO(b/203699028): can't call isVoNrEnabledResponse with 1.6 callback
+    return ok();
+}
+
+ScopedAStatus RadioVoice::rejectCall(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->rejectCall(serial);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::responseAcknowledgement() {
+    LOG_CALL;
+    mHal1_5->responseAcknowledgement();
+    return ok();
+}
+
+ScopedAStatus RadioVoice::sendBurstDtmf(int32_t serial, const std::string& dtmf, int32_t on,
+                                        int32_t off) {
+    LOG_CALL << serial;
+    mHal1_5->sendBurstDtmf(serial, dtmf, on, off);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::sendCdmaFeatureCode(int32_t serial, const std::string& featureCode) {
+    LOG_CALL << serial;
+    mHal1_5->sendCDMAFeatureCode(serial, featureCode);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::sendDtmf(int32_t serial, const std::string& s) {
+    LOG_CALL << serial;
+    mHal1_5->sendDtmf(serial, s);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::separateConnection(int32_t serial, int32_t gsmIndex) {
+    LOG_CALL << serial;
+    mHal1_5->separateConnection(serial, gsmIndex);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::setCallForward(int32_t serial, const aidl::CallForwardInfo& callInfo) {
+    LOG_CALL << serial;
+    mHal1_5->setCallForward(serial, toHidl(callInfo));
+    return ok();
+}
+
+ScopedAStatus RadioVoice::setCallWaiting(int32_t serial, bool enable, int32_t serviceClass) {
+    LOG_CALL << serial;
+    mHal1_5->setCallWaiting(serial, enable, serviceClass);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::setClir(int32_t serial, int32_t status) {
+    LOG_CALL << serial;
+    mHal1_5->setClir(serial, status);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::setMute(int32_t serial, bool enable) {
+    LOG_CALL << serial;
+    mHal1_5->setMute(serial, enable);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::setPreferredVoicePrivacy(int32_t serial, bool enable) {
+    LOG_CALL << serial;
+    mHal1_5->setPreferredVoicePrivacy(serial, enable);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::setResponseFunctions(
+        const std::shared_ptr<aidl::IRadioVoiceResponse>& voiceResponse,
+        const std::shared_ptr<aidl::IRadioVoiceIndication>& voiceIndication) {
+    LOG_CALL << voiceResponse << ' ' << voiceIndication;
+
+    CHECK(voiceResponse);
+    CHECK(voiceIndication);
+
+    mRadioResponse->setResponseFunction(voiceResponse);
+    mRadioIndication->setResponseFunction(voiceIndication);
+
+    return ok();
+}
+
+ScopedAStatus RadioVoice::setTtyMode(int32_t serial, aidl::TtyMode mode) {
+    LOG_CALL << serial;
+    mHal1_5->setTTYMode(serial, V1_0::TtyMode(mode));
+    return ok();
+}
+
+ndk::ScopedAStatus RadioVoice::setVoNrEnabled(int32_t serial, [[maybe_unused]] bool enable) {
+    LOG_CALL << serial;
+    // TODO(b/203699028): should set `persist.radio.is_vonr_enabled_` property instead
+    return ok();
+}
+
+ScopedAStatus RadioVoice::startDtmf(int32_t serial, const std::string& s) {
+    LOG_CALL << serial;
+    mHal1_5->startDtmf(serial, s);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::stopDtmf(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->stopDtmf(serial);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::switchWaitingOrHoldingAndActive(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->switchWaitingOrHoldingAndActive(serial);
+    return ok();
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/voice/structs.cpp b/radio/aidl/compat/libradiocompat/voice/structs.cpp
new file mode 100644
index 0000000..ae6342e
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/voice/structs.cpp
@@ -0,0 +1,223 @@
+/*
+ * 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 {
+
+namespace aidl = ::aidl::android::hardware::radio::voice;
+
+V1_0::Dial toHidl(const aidl::Dial& info) {
+    return {
+            .address = info.address,
+            .clir = V1_0::Clir{info.clir},
+            .uusInfo = toHidl(info.uusInfo),
+    };
+}
+
+V1_0::UusInfo toHidl(const aidl::UusInfo& info) {
+    return {
+            .uusType = V1_0::UusType{info.uusType},
+            .uusDcs = V1_0::UusDcs{info.uusDcs},
+            .uusData = info.uusData,
+    };
+}
+
+aidl::CallForwardInfo toAidl(const V1_0::CallForwardInfo& info) {
+    return {
+            .status = static_cast<int32_t>(info.status),
+            .reason = info.reason,
+            .serviceClass = info.serviceClass,
+            .toa = info.toa,
+            .number = info.number,
+            .timeSeconds = info.timeSeconds,
+    };
+}
+
+V1_0::CallForwardInfo toHidl(const aidl::CallForwardInfo& info) {
+    return {
+            .status = V1_0::CallForwardInfoStatus{info.status},
+            .reason = info.reason,
+            .serviceClass = info.serviceClass,
+            .toa = info.toa,
+            .number = info.number,
+            .timeSeconds = info.timeSeconds,
+    };
+}
+
+aidl::CdmaSignalInfoRecord toAidl(const V1_0::CdmaSignalInfoRecord& record) {
+    return {
+            .isPresent = record.isPresent,
+            .signalType = record.signalType,
+            .alertPitch = record.alertPitch,
+            .signal = record.signal,
+    };
+}
+
+aidl::CdmaCallWaiting toAidl(const V1_0::CdmaCallWaiting& call) {
+    return {
+            .number = call.number,
+            .numberPresentation = static_cast<int32_t>(call.numberPresentation),
+            .name = call.name,
+            .signalInfoRecord = toAidl(call.signalInfoRecord),
+            .numberType = static_cast<int32_t>(call.numberType),
+            .numberPlan = static_cast<int32_t>(call.numberPlan),
+    };
+}
+
+aidl::CdmaInformationRecord toAidl(const V1_0::CdmaInformationRecord& record) {
+    return {
+            .name = static_cast<int32_t>(record.name),
+            .display = toAidl(record.display),
+            .number = toAidl(record.number),
+            .signal = toAidl(record.signal),
+            .redir = toAidl(record.redir),
+            .lineCtrl = toAidl(record.lineCtrl),
+            .clir = toAidl(record.clir),
+            .audioCtrl = toAidl(record.audioCtrl),
+    };
+}
+
+aidl::CdmaDisplayInfoRecord toAidl(const V1_0::CdmaDisplayInfoRecord& record) {
+    return {
+            .alphaBuf = record.alphaBuf,
+    };
+}
+
+aidl::CdmaNumberInfoRecord toAidl(const V1_0::CdmaNumberInfoRecord& record) {
+    return {
+            .number = record.number,
+            .numberType = static_cast<int8_t>(record.numberType),
+            .numberPlan = static_cast<int8_t>(record.numberPlan),
+            .pi = static_cast<int8_t>(record.pi),
+            .si = static_cast<int8_t>(record.si),
+    };
+}
+
+aidl::CdmaRedirectingNumberInfoRecord toAidl(const V1_0::CdmaRedirectingNumberInfoRecord& record) {
+    return {
+            .redirectingNumber = toAidl(record.redirectingNumber),
+            .redirectingReason = static_cast<int32_t>(record.redirectingReason),
+    };
+}
+
+aidl::CdmaLineControlInfoRecord toAidl(const V1_0::CdmaLineControlInfoRecord& record) {
+    return {
+            .lineCtrlPolarityIncluded = static_cast<int8_t>(record.lineCtrlPolarityIncluded),
+            .lineCtrlToggle = static_cast<int8_t>(record.lineCtrlToggle),
+            .lineCtrlReverse = static_cast<int8_t>(record.lineCtrlReverse),
+            .lineCtrlPowerDenial = static_cast<int8_t>(record.lineCtrlPowerDenial),
+    };
+}
+
+aidl::CdmaT53ClirInfoRecord toAidl(const V1_0::CdmaT53ClirInfoRecord& record) {
+    return {
+            .cause = static_cast<int8_t>(record.cause),
+    };
+}
+
+aidl::CdmaT53AudioControlInfoRecord toAidl(const V1_0::CdmaT53AudioControlInfoRecord& record) {
+    return {
+            .upLink = static_cast<int8_t>(record.upLink),
+            .downLink = static_cast<int8_t>(record.downLink),
+    };
+}
+
+aidl::EmergencyNumber toAidl(const V1_4::EmergencyNumber& num) {
+    return {
+            .number = num.number,
+            .mcc = num.mcc,
+            .mnc = num.mnc,
+            .categories = aidl::EmergencyServiceCategory(num.categories),
+            .urns = toAidl(num.urns),
+            .sources = num.sources,
+    };
+}
+
+aidl::StkCcUnsolSsResult toAidl(const V1_0::StkCcUnsolSsResult& res) {
+    return {
+            .serviceType = static_cast<int32_t>(res.serviceType),
+            .requestType = static_cast<int32_t>(res.requestType),
+            .teleserviceType = static_cast<int32_t>(res.teleserviceType),
+            .serviceClass = res.serviceClass,
+            .result = toAidl(res.result),
+            .ssInfo = toAidl(res.ssInfo),
+            .cfData = toAidl(res.cfData),
+    };
+}
+
+aidl::SsInfoData toAidl(const V1_0::SsInfoData& info) {
+    return {
+            .ssInfo = info.ssInfo,
+    };
+}
+
+aidl::CfData toAidl(const V1_0::CfData& data) {
+    return {
+            .cfInfo = toAidl(data.cfInfo),
+    };
+}
+
+aidl::Call toAidl(const V1_0::Call& call) {
+    return toAidl(V1_2::Call{call, {}});
+}
+
+aidl::Call toAidl(const V1_2::Call& call) {
+    return toAidl(V1_6::Call{call, {}});
+}
+
+aidl::Call toAidl(const V1_6::Call& call) {
+    return {
+            .state = static_cast<int32_t>(call.base.base.state),
+            .index = call.base.base.index,
+            .toa = call.base.base.toa,
+            .isMpty = call.base.base.isMpty,
+            .isMT = call.base.base.isMT,
+            .als = static_cast<int8_t>(call.base.base.als),
+            .isVoice = call.base.base.isVoice,
+            .isVoicePrivacy = call.base.base.isVoicePrivacy,
+            .number = call.base.base.number,
+            .numberPresentation = static_cast<int32_t>(call.base.base.numberPresentation),
+            .name = call.base.base.name,
+            .namePresentation = static_cast<int32_t>(call.base.base.namePresentation),
+            .uusInfo = toAidl(call.base.base.uusInfo),
+            .audioQuality = aidl::AudioQuality(call.base.audioQuality),
+            .forwardedNumber = call.forwardedNumber,
+    };
+}
+
+aidl::UusInfo toAidl(const V1_0::UusInfo& info) {
+    return {
+            .uusType = static_cast<int32_t>(info.uusType),
+            .uusDcs = static_cast<int32_t>(info.uusDcs),
+            .uusData = info.uusData,
+    };
+}
+
+aidl::LastCallFailCauseInfo toAidl(const V1_0::LastCallFailCauseInfo& info) {
+    return {
+            .causeCode = aidl::LastCallFailCause(info.causeCode),
+            .vendorCause = info.vendorCause,
+    };
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/voice/structs.h b/radio/aidl/compat/libradiocompat/voice/structs.h
new file mode 100644
index 0000000..b55a089
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/voice/structs.h
@@ -0,0 +1,91 @@
+/*
+ * 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/voice/Call.h>
+#include <aidl/android/hardware/radio/voice/CallForwardInfo.h>
+#include <aidl/android/hardware/radio/voice/CdmaCallWaiting.h>
+#include <aidl/android/hardware/radio/voice/CdmaDisplayInfoRecord.h>
+#include <aidl/android/hardware/radio/voice/CdmaInformationRecord.h>
+#include <aidl/android/hardware/radio/voice/CdmaLineControlInfoRecord.h>
+#include <aidl/android/hardware/radio/voice/CdmaNumberInfoRecord.h>
+#include <aidl/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.h>
+#include <aidl/android/hardware/radio/voice/CdmaSignalInfoRecord.h>
+#include <aidl/android/hardware/radio/voice/CdmaT53AudioControlInfoRecord.h>
+#include <aidl/android/hardware/radio/voice/CdmaT53ClirInfoRecord.h>
+#include <aidl/android/hardware/radio/voice/CfData.h>
+#include <aidl/android/hardware/radio/voice/Dial.h>
+#include <aidl/android/hardware/radio/voice/EmergencyNumber.h>
+#include <aidl/android/hardware/radio/voice/LastCallFailCauseInfo.h>
+#include <aidl/android/hardware/radio/voice/SsInfoData.h>
+#include <aidl/android/hardware/radio/voice/StkCcUnsolSsResult.h>
+#include <aidl/android/hardware/radio/voice/UusInfo.h>
+#include <android/hardware/radio/1.6/types.h>
+
+namespace android::hardware::radio::compat {
+
+V1_0::Dial toHidl(const ::aidl::android::hardware::radio::voice::Dial& info);
+
+V1_0::UusInfo toHidl(const ::aidl::android::hardware::radio::voice::UusInfo& info);
+
+::aidl::android::hardware::radio::voice::CallForwardInfo toAidl(const V1_0::CallForwardInfo& info);
+V1_0::CallForwardInfo toHidl(const ::aidl::android::hardware::radio::voice::CallForwardInfo& info);
+
+::aidl::android::hardware::radio::voice::CdmaSignalInfoRecord  //
+toAidl(const V1_0::CdmaSignalInfoRecord& record);
+
+::aidl::android::hardware::radio::voice::CdmaCallWaiting toAidl(const V1_0::CdmaCallWaiting& call);
+
+::aidl::android::hardware::radio::voice::CdmaInformationRecord  //
+toAidl(const V1_0::CdmaInformationRecord& record);
+
+::aidl::android::hardware::radio::voice::CdmaDisplayInfoRecord  //
+toAidl(const V1_0::CdmaDisplayInfoRecord& record);
+
+::aidl::android::hardware::radio::voice::CdmaNumberInfoRecord  //
+toAidl(const V1_0::CdmaNumberInfoRecord& record);
+
+::aidl::android::hardware::radio::voice::CdmaRedirectingNumberInfoRecord  //
+toAidl(const V1_0::CdmaRedirectingNumberInfoRecord& record);
+
+::aidl::android::hardware::radio::voice::CdmaLineControlInfoRecord  //
+toAidl(const V1_0::CdmaLineControlInfoRecord& record);
+
+::aidl::android::hardware::radio::voice::CdmaT53ClirInfoRecord  //
+toAidl(const V1_0::CdmaT53ClirInfoRecord& record);
+
+::aidl::android::hardware::radio::voice::CdmaT53AudioControlInfoRecord  //
+toAidl(const V1_0::CdmaT53AudioControlInfoRecord& record);
+
+::aidl::android::hardware::radio::voice::EmergencyNumber toAidl(const V1_4::EmergencyNumber& num);
+
+::aidl::android::hardware::radio::voice::StkCcUnsolSsResult  //
+toAidl(const V1_0::StkCcUnsolSsResult& res);
+
+::aidl::android::hardware::radio::voice::SsInfoData toAidl(const V1_0::SsInfoData& info);
+
+::aidl::android::hardware::radio::voice::CfData toAidl(const V1_0::CfData& data);
+
+::aidl::android::hardware::radio::voice::Call toAidl(const V1_0::Call& call);
+::aidl::android::hardware::radio::voice::Call toAidl(const V1_2::Call& call);
+::aidl::android::hardware::radio::voice::Call toAidl(const V1_6::Call& call);
+
+::aidl::android::hardware::radio::voice::UusInfo toAidl(const V1_0::UusInfo& info);
+
+::aidl::android::hardware::radio::voice::LastCallFailCauseInfo  //
+toAidl(const V1_0::LastCallFailCauseInfo& info);
+
+}  // namespace android::hardware::radio::compat