/*
 * Copyright (C) 2022 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.
 */

#define LOG_TAG "DeviceHalAidl"
// #define LOG_NDEBUG 0

#include <algorithm>

#include <aidl/android/hardware/audio/core/BnStreamCallback.h>
#include <aidl/android/hardware/audio/core/BnStreamOutEventCallback.h>
#include <aidl/android/hardware/audio/core/StreamDescriptor.h>
#include <error/expected_utils.h>
#include <media/AidlConversionCppNdk.h>
#include <media/AidlConversionNdkCpp.h>
#include <media/AidlConversionUtil.h>
#include <mediautils/TimeCheck.h>
#include <system/audio.h>
#include <Utils.h>
#include <utils/Log.h>

#include "DeviceHalAidl.h"
#include "EffectHalAidl.h"
#include "StreamHalAidl.h"

using aidl::android::aidl_utils::statusTFromBinderStatus;
using aidl::android::media::audio::common::Boolean;
using aidl::android::media::audio::common::AudioConfig;
using aidl::android::media::audio::common::AudioDevice;
using aidl::android::media::audio::common::AudioDeviceType;
using aidl::android::media::audio::common::AudioIoFlags;
using aidl::android::media::audio::common::AudioLatencyMode;
using aidl::android::media::audio::common::AudioMMapPolicy;
using aidl::android::media::audio::common::AudioMMapPolicyInfo;
using aidl::android::media::audio::common::AudioMMapPolicyType;
using aidl::android::media::audio::common::AudioMode;
using aidl::android::media::audio::common::AudioOutputFlags;
using aidl::android::media::audio::common::AudioPort;
using aidl::android::media::audio::common::AudioPortConfig;
using aidl::android::media::audio::common::AudioPortExt;
using aidl::android::media::audio::common::AudioSource;
using aidl::android::media::audio::common::Float;
using aidl::android::media::audio::common::Int;
using aidl::android::media::audio::common::MicrophoneDynamicInfo;
using aidl::android::media::audio::common::MicrophoneInfo;
using aidl::android::media::audio::IHalAdapterVendorExtension;
using aidl::android::hardware::audio::common::getFrameSizeInBytes;
using aidl::android::hardware::audio::common::isBitPositionFlagSet;
using aidl::android::hardware::audio::common::RecordTrackMetadata;
using aidl::android::hardware::audio::core::sounddose::ISoundDose;
using aidl::android::hardware::audio::core::AudioPatch;
using aidl::android::hardware::audio::core::AudioRoute;
using aidl::android::hardware::audio::core::IBluetooth;
using aidl::android::hardware::audio::core::IBluetoothA2dp;
using aidl::android::hardware::audio::core::IBluetoothLe;
using aidl::android::hardware::audio::core::IModule;
using aidl::android::hardware::audio::core::ITelephony;
using aidl::android::hardware::audio::core::ModuleDebug;
using aidl::android::hardware::audio::core::VendorParameter;

namespace android {

namespace {

// Note: these converters are for types defined in different AIDL files. Although these
// AIDL files are copies of each other, however formally these are different types
// thus we don't use a conversion via a parcelable.
ConversionResult<media::AudioRoute> ndk2cpp_AudioRoute(const AudioRoute& ndk) {
    media::AudioRoute cpp;
    cpp.sourcePortIds.insert(
            cpp.sourcePortIds.end(), ndk.sourcePortIds.begin(), ndk.sourcePortIds.end());
    cpp.sinkPortId = ndk.sinkPortId;
    cpp.isExclusive = ndk.isExclusive;
    return cpp;
}

template<typename T>
std::shared_ptr<T> retrieveSubInterface(const std::shared_ptr<IModule>& module,
        ::ndk::ScopedAStatus (IModule::*getT)(std::shared_ptr<T>*)) {
    if (module != nullptr) {
        std::shared_ptr<T> instance;
        if (auto status = (module.get()->*getT)(&instance); status.isOk()) {
            return instance;
        }
    }
    return nullptr;
}

}  // namespace

DeviceHalAidl::DeviceHalAidl(const std::string& instance, const std::shared_ptr<IModule>& module,
                             const std::shared_ptr<IHalAdapterVendorExtension>& vext)
        : ConversionHelperAidl("DeviceHalAidl"),
          mInstance(instance), mModule(module), mVendorExt(vext),
          mTelephony(retrieveSubInterface<ITelephony>(module, &IModule::getTelephony)),
          mBluetooth(retrieveSubInterface<IBluetooth>(module, &IModule::getBluetooth)),
          mBluetoothA2dp(retrieveSubInterface<IBluetoothA2dp>(module, &IModule::getBluetoothA2dp)),
          mBluetoothLe(retrieveSubInterface<IBluetoothLe>(module, &IModule::getBluetoothLe)),
          mSoundDose(retrieveSubInterface<ISoundDose>(module, &IModule::getSoundDose)),
          mMapper(instance, module), mMapperAccessor(mMapper, mLock) {
}

status_t DeviceHalAidl::getAudioPorts(std::vector<media::audio::common::AudioPort> *ports) {
    std::lock_guard l(mLock);
    return mMapper.getAudioPorts(ports, ndk2cpp_AudioPort);
}

status_t DeviceHalAidl::getAudioRoutes(std::vector<media::AudioRoute> *routes) {
    std::lock_guard l(mLock);
    return mMapper.getAudioRoutes(routes, ndk2cpp_AudioRoute);
}

status_t DeviceHalAidl::getSupportedModes(std::vector<media::audio::common::AudioMode> *modes) {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    TIME_CHECK();
    if (mModule == nullptr) return NO_INIT;
    if (mTelephony == nullptr) return INVALID_OPERATION;
    if (modes == nullptr) {
        return BAD_VALUE;
    }
    std::vector<AudioMode> aidlModes;
    RETURN_STATUS_IF_ERROR(
            statusTFromBinderStatus(mTelephony->getSupportedAudioModes(&aidlModes)));
    *modes = VALUE_OR_RETURN_STATUS(
            ::aidl::android::convertContainer<std::vector<media::audio::common::AudioMode>>(
                    aidlModes, ndk2cpp_AudioMode));
    return OK;
}

status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
    // Obsolete.
    return INVALID_OPERATION;
}

status_t DeviceHalAidl::initCheck() {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    TIME_CHECK();
    if (mModule == nullptr) return NO_INIT;
    std::lock_guard l(mLock);
    return mMapper.initialize();
}

status_t DeviceHalAidl::setVoiceVolume(float volume) {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    TIME_CHECK();
    if (mModule == nullptr) return NO_INIT;
    if (mTelephony == nullptr) return INVALID_OPERATION;
    ITelephony::TelecomConfig inConfig{ .voiceVolume = Float{volume} }, outConfig;
    RETURN_STATUS_IF_ERROR(
            statusTFromBinderStatus(mTelephony->setTelecomConfig(inConfig, &outConfig)));
    ALOGW_IF(outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
            "%s: the resulting voice volume %f is not the same as requested %f",
            __func__, outConfig.voiceVolume.value().value, volume);
    return OK;
}

status_t DeviceHalAidl::setMasterVolume(float volume) {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    TIME_CHECK();
    if (mModule == nullptr) return NO_INIT;
    return statusTFromBinderStatus(mModule->setMasterVolume(volume));
}

status_t DeviceHalAidl::getMasterVolume(float *volume) {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    TIME_CHECK();
    if (mModule == nullptr) return NO_INIT;
    if (volume == nullptr) {
        return BAD_VALUE;
    }
    return statusTFromBinderStatus(mModule->getMasterVolume(volume));
}

status_t DeviceHalAidl::setMode(audio_mode_t mode) {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    TIME_CHECK();
    if (mModule == nullptr) return NO_INIT;
    AudioMode audioMode = VALUE_OR_FATAL(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
    if (mTelephony != nullptr) {
        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mTelephony->switchAudioMode(audioMode)));
    }
    return statusTFromBinderStatus(mModule->updateAudioMode(audioMode));
}

status_t DeviceHalAidl::setMicMute(bool state) {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    TIME_CHECK();
    if (mModule == nullptr) return NO_INIT;
    return statusTFromBinderStatus(mModule->setMicMute(state));
}

status_t DeviceHalAidl::getMicMute(bool *state) {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    TIME_CHECK();
    if (mModule == nullptr) return NO_INIT;
    if (state == nullptr) {
        return BAD_VALUE;
    }
    return statusTFromBinderStatus(mModule->getMicMute(state));
}

status_t DeviceHalAidl::setMasterMute(bool state) {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    TIME_CHECK();
    if (mModule == nullptr) return NO_INIT;
    return statusTFromBinderStatus(mModule->setMasterMute(state));
}

status_t DeviceHalAidl::getMasterMute(bool *state) {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    TIME_CHECK();
    if (mModule == nullptr) return NO_INIT;
    if (state == nullptr) {
        return BAD_VALUE;
    }
    return statusTFromBinderStatus(mModule->getMasterMute(state));
}

status_t DeviceHalAidl::setParameters(const String8& kvPairs) {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    TIME_CHECK();
    if (mModule == nullptr) return NO_INIT;
    AudioParameter parameters(kvPairs);
    ALOGD("%s: parameters: \"%s\"", __func__, parameters.toString().c_str());

    if (status_t status = filterAndUpdateBtA2dpParameters(parameters); status != OK) {
        ALOGW("%s: filtering or updating BT A2DP parameters failed: %d", __func__, status);
    }
    if (status_t status = filterAndUpdateBtHfpParameters(parameters); status != OK) {
        ALOGW("%s: filtering or updating BT HFP parameters failed: %d", __func__, status);
    }
    if (status_t status = filterAndUpdateBtLeParameters(parameters); status != OK) {
        ALOGW("%s: filtering or updating BT LE parameters failed: %d", __func__, status);
    }
    if (status_t status = filterAndUpdateBtScoParameters(parameters); status != OK) {
        ALOGW("%s: filtering or updating BT SCO parameters failed: %d", __func__, status);
    }
    if (status_t status = filterAndUpdateScreenParameters(parameters); status != OK) {
        ALOGW("%s: filtering or updating screen parameters failed: %d", __func__, status);
    }
    if (status_t status = filterAndUpdateTelephonyParameters(parameters); status != OK) {
        ALOGW("%s: filtering or updating telephony parameters failed: %d", __func__, status);
    }
    return parseAndSetVendorParameters(mVendorExt, mModule, parameters);
}

status_t DeviceHalAidl::getParameters(const String8& keys, String8 *values) {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    TIME_CHECK();
    if (mModule == nullptr) return NO_INIT;
    if (values == nullptr) {
        return BAD_VALUE;
    }
    AudioParameter parameterKeys(keys), result;
    if (status_t status = filterAndRetrieveBtA2dpParameters(parameterKeys, &result); status != OK) {
        ALOGW("%s: filtering or retrieving BT A2DP parameters failed: %d", __func__, status);
    }
    if (status_t status = filterAndRetrieveBtLeParameters(parameterKeys, &result); status != OK) {
        ALOGW("%s: filtering or retrieving BT LE parameters failed: %d", __func__, status);
    }
    *values = result.toString();
    return parseAndGetVendorParameters(mVendorExt, mModule, parameterKeys, values);
}

status_t DeviceHalAidl::getInputBufferSize(struct audio_config* config, size_t* size) {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    TIME_CHECK();
    if (mModule == nullptr) return NO_INIT;
    if (config == nullptr || size == nullptr) {
        return BAD_VALUE;
    }
    constexpr bool isInput = true;
    AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
            ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, isInput));
    AudioDevice aidlDevice;
    aidlDevice.type.type = AudioDeviceType::IN_DEFAULT;
    AudioSource aidlSource = AudioSource::DEFAULT;
    AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(0);
    AudioPortConfig mixPortConfig;
    Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
    AudioPatch aidlPatch;
    {
        std::lock_guard l(mLock);
        RETURN_STATUS_IF_ERROR(mMapper.prepareToOpenStream(
                        0 /*handle*/, aidlDevice, aidlFlags, aidlSource,
                        &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
    }
    *config = VALUE_OR_RETURN_STATUS(
            ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(aidlConfig, isInput));
    if (mixPortConfig.id == 0) return BAD_VALUE;  // HAL suggests a different config.
    *size = aidlConfig.frameCount *
            getFrameSizeInBytes(aidlConfig.base.format, aidlConfig.base.channelMask);
    // Do not disarm cleanups to release temporary port configs.
    return OK;
}

namespace {

class StreamCallbackBase {
  protected:
    explicit StreamCallbackBase(const sp<CallbackBroker>& broker) : mBroker(broker) {}
  public:
    void* getCookie() const { return mCookie; }
    void setCookie(void* cookie) { mCookie = cookie; }
    sp<CallbackBroker> getBroker() const {
        if (void* cookie = mCookie; cookie != nullptr) return mBroker.promote();
        return nullptr;
    }
  private:
    const wp<CallbackBroker> mBroker;
    std::atomic<void*> mCookie;
};

template<class C>
class StreamCallbackBaseHelper {
  protected:
    explicit StreamCallbackBaseHelper(const StreamCallbackBase& base) : mBase(base) {}
    sp<C> getCb(const sp<CallbackBroker>& broker, void* cookie);
    using CbRef = const sp<C>&;
    ndk::ScopedAStatus runCb(const std::function<void(CbRef cb)>& f) {
        if (auto cb = getCb(mBase.getBroker(), mBase.getCookie()); cb != nullptr) f(cb);
        return ndk::ScopedAStatus::ok();
    }
  private:
    const StreamCallbackBase& mBase;
};

template<>
sp<StreamOutHalInterfaceCallback> StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>::getCb(
        const sp<CallbackBroker>& broker, void* cookie) {
    if (broker != nullptr) return broker->getStreamOutCallback(cookie);
    return nullptr;
}

template<>
sp<StreamOutHalInterfaceEventCallback>
StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::getCb(
        const sp<CallbackBroker>& broker, void* cookie) {
    if (broker != nullptr) return broker->getStreamOutEventCallback(cookie);
    return nullptr;
}

template<>
sp<StreamOutHalInterfaceLatencyModeCallback>
StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::getCb(
        const sp<CallbackBroker>& broker, void* cookie) {
    if (broker != nullptr) return broker->getStreamOutLatencyModeCallback(cookie);
    return nullptr;
}

/*
Note on the callback ownership.

In the Binder ownership model, the server implementation is kept alive
as long as there is any client (proxy object) alive. This is done by
incrementing the refcount of the server-side object by the Binder framework.
When it detects that the last client is gone, it decrements the refcount back.

Thus, it is not needed to keep any references to StreamCallback on our
side (after we have sent an instance to the client), because we are
the server-side. The callback object will be kept alive as long as the HAL server
holds a strong ref to IStreamCallback proxy.
*/

class OutputStreamCallbackAidl : public StreamCallbackBase,
                             public StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>,
                             public ::aidl::android::hardware::audio::core::BnStreamCallback {
  public:
    explicit OutputStreamCallbackAidl(const sp<CallbackBroker>& broker)
            : StreamCallbackBase(broker),
              StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>(
                      *static_cast<StreamCallbackBase*>(this)) {}
    ndk::ScopedAStatus onTransferReady() override {
        return runCb([](CbRef cb) { cb->onWriteReady(); });
    }
    ndk::ScopedAStatus onError() override {
        return runCb([](CbRef cb) { cb->onError(); });
    }
    ndk::ScopedAStatus onDrainReady() override {
        return runCb([](CbRef cb) { cb->onDrainReady(); });
    }
};

class OutputStreamEventCallbackAidl :
            public StreamCallbackBase,
            public StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>,
            public StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>,
            public ::aidl::android::hardware::audio::core::BnStreamOutEventCallback {
  public:
    explicit OutputStreamEventCallbackAidl(const sp<CallbackBroker>& broker)
            : StreamCallbackBase(broker),
              StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>(
                      *static_cast<StreamCallbackBase*>(this)),
              StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>(
                      *static_cast<StreamCallbackBase*>(this)) {}
    ndk::ScopedAStatus onCodecFormatChanged(const std::vector<uint8_t>& halMetadata) override {
        return StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::runCb(
                [&halMetadata](auto cb) { cb->onCodecFormatChanged(halMetadata); });
    }
    ndk::ScopedAStatus onRecommendedLatencyModeChanged(
            const std::vector<AudioLatencyMode>& in_modes) override {
        auto halModes = VALUE_OR_FATAL(
                ::aidl::android::convertContainer<std::vector<audio_latency_mode_t>>(
                        in_modes,
                        ::aidl::android::aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
        return StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::runCb(
                [&halModes](auto cb) { cb->onRecommendedLatencyModeChanged(halModes); });
    }
};

}  // namespace

status_t DeviceHalAidl::openOutputStream(
        audio_io_handle_t handle, audio_devices_t devices,
        audio_output_flags_t flags, struct audio_config* config,
        const char* address,
        sp<StreamOutHalInterface>* outStream) {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    TIME_CHECK();
    if (mModule == nullptr) return NO_INIT;
    if (outStream == nullptr || config == nullptr) {
        return BAD_VALUE;
    }
    constexpr bool isInput = false;
    int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
            ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
    AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
            ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, isInput));
    AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
            ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
    int32_t aidlOutputFlags = VALUE_OR_RETURN_STATUS(
            ::aidl::android::legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
    AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
    AudioPortConfig mixPortConfig;
    AudioPatch aidlPatch;
    Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
    {
        std::lock_guard l(mLock);
        RETURN_STATUS_IF_ERROR(mMapper.prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags,
                        AudioSource::SYS_RESERVED_INVALID /*only needed for input*/,
                        &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
    }
    *config = VALUE_OR_RETURN_STATUS(
            ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(aidlConfig, isInput));
    if (mixPortConfig.id == 0) return BAD_VALUE;  // HAL suggests a different config.
    ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
    args.portConfigId = mixPortConfig.id;
    const bool isOffload = isBitPositionFlagSet(
            aidlOutputFlags, AudioOutputFlags::COMPRESS_OFFLOAD);
    std::shared_ptr<OutputStreamCallbackAidl> streamCb;
    if (isOffload) {
        streamCb = ndk::SharedRefBase::make<OutputStreamCallbackAidl>(this);
    }
    auto eventCb = ndk::SharedRefBase::make<OutputStreamEventCallbackAidl>(this);
    if (isOffload) {
        args.offloadInfo = aidlConfig.offloadInfo;
        args.callback = streamCb;
    }
    args.bufferSizeFrames = aidlConfig.frameCount;
    args.eventCallback = eventCb;
    ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
    StreamContextAidl context(ret.desc, isOffload);
    if (!context.isValid()) {
        ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
                __func__, ret.desc.toString().c_str());
        return NO_INIT;
    }
    *outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
            std::move(ret.stream), mVendorExt, this /*callbackBroker*/);
    void* cbCookie = (*outStream).get();
    {
        std::lock_guard l(mLock);
        mCallbacks.emplace(cbCookie, Callbacks{});
        mMapper.addStream(*outStream, mixPortConfig.id, aidlPatch.id);
    }
    if (streamCb) streamCb->setCookie(cbCookie);
    eventCb->setCookie(cbCookie);
    cleanups.disarmAll();
    return OK;
}

status_t DeviceHalAidl::openInputStream(
        audio_io_handle_t handle, audio_devices_t devices,
        struct audio_config* config, audio_input_flags_t flags,
        const char* address, audio_source_t source,
        audio_devices_t outputDevice, const char* outputDeviceAddress,
        sp<StreamInHalInterface>* inStream) {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    TIME_CHECK();
    if (mModule == nullptr) return NO_INIT;
    if (inStream == nullptr || config == nullptr) {
        return BAD_VALUE;
    }
    constexpr bool isInput = true;
    int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
            ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
    AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
            ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, isInput));
    AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
            ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
    int32_t aidlInputFlags = VALUE_OR_RETURN_STATUS(
            ::aidl::android::legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
    AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(aidlInputFlags);
    AudioSource aidlSource = VALUE_OR_RETURN_STATUS(
            ::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
    AudioPortConfig mixPortConfig;
    AudioPatch aidlPatch;
    Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
    {
        std::lock_guard l(mLock);
        RETURN_STATUS_IF_ERROR(mMapper.prepareToOpenStream(
                        aidlHandle, aidlDevice, aidlFlags, aidlSource,
                        &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
    }
    *config = VALUE_OR_RETURN_STATUS(
            ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(aidlConfig, isInput));
    if (mixPortConfig.id == 0) return BAD_VALUE;  // HAL suggests a different config.
    ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
    args.portConfigId = mixPortConfig.id;
    RecordTrackMetadata aidlTrackMetadata{
        .source = aidlSource, .gain = 1, .channelMask = aidlConfig.base.channelMask };
    if (outputDevice != AUDIO_DEVICE_NONE) {
        aidlTrackMetadata.destinationDevice = VALUE_OR_RETURN_STATUS(
            ::aidl::android::legacy2aidl_audio_device_AudioDevice(
                    outputDevice, outputDeviceAddress));
    }
    args.sinkMetadata.tracks.push_back(std::move(aidlTrackMetadata));
    args.bufferSizeFrames = aidlConfig.frameCount;
    ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
    StreamContextAidl context(ret.desc, false /*isAsynchronous*/);
    if (!context.isValid()) {
        ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
                __func__, ret.desc.toString().c_str());
        return NO_INIT;
    }
    *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
            std::move(ret.stream), mVendorExt, this /*micInfoProvider*/);
    {
        std::lock_guard l(mLock);
        mMapper.addStream(*inStream, mixPortConfig.id, aidlPatch.id);
    }
    cleanups.disarmAll();
    return OK;
}

status_t DeviceHalAidl::supportsAudioPatches(bool* supportsPatches) {
    if (supportsPatches == nullptr) {
        return BAD_VALUE;
    }
    *supportsPatches = true;
    return OK;
}

status_t DeviceHalAidl::createAudioPatch(unsigned int num_sources,
                                         const struct audio_port_config* sources,
                                         unsigned int num_sinks,
                                         const struct audio_port_config* sinks,
                                         audio_patch_handle_t* patch) {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    TIME_CHECK();
    if (mModule == nullptr) return NO_INIT;
    if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX ||
        sources == nullptr || sinks == nullptr || patch == nullptr) {
        return BAD_VALUE;
    }
    // When the patch handle (*patch) is AUDIO_PATCH_HANDLE_NONE, it means
    // the framework wants to create a new patch. The handle has to be generated
    // by the HAL. Since handles generated this way can only be unique within
    // a HAL module, the framework generates a globally unique handle, and maps
    // it on the <HAL module, patch handle> pair.
    // When the patch handle is set, it meant the framework intends to update
    // an existing patch.
    //
    // This behavior corresponds to HAL module behavior, with the only difference
    // that the HAL module uses `int32_t` for patch IDs. The following assert ensures
    // that both the framework and the HAL use the same value for "no ID":
    static_assert(AUDIO_PATCH_HANDLE_NONE == 0);

    // Upon conversion, mix port configs contain audio configuration, while
    // device port configs contain device address. This data is used to find
    // or create HAL configs.
    std::vector<AudioPortConfig> aidlSources, aidlSinks;
    for (unsigned int i = 0; i < num_sources; ++i) {
        bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
                        sources[i].role, sources[i].type)) ==
                ::aidl::android::AudioPortDirection::INPUT;
        aidlSources.push_back(VALUE_OR_RETURN_STATUS(
                        ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
                                sources[i], isInput, 0)));
    }
    for (unsigned int i = 0; i < num_sinks; ++i) {
        bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
                        sinks[i].role, sinks[i].type)) ==
                ::aidl::android::AudioPortDirection::INPUT;
        aidlSinks.push_back(VALUE_OR_RETURN_STATUS(
                        ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
                                sinks[i], isInput, 0)));
    }
    int32_t aidlPatchId = static_cast<int32_t>(*patch);
    Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
    {
        std::lock_guard l(mLock);
        // Check for patches that only exist for the framework, or have different HAL patch ID.
        if (int32_t aidlHalPatchId = mMapper.findFwkPatch(aidlPatchId); aidlHalPatchId != 0) {
            if (aidlHalPatchId == aidlPatchId) {
                // This patch was previously released by the HAL. Thus we need to pass '0'
                // to the HAL to obtain a new patch.
                int32_t newAidlPatchId = 0;
                RETURN_STATUS_IF_ERROR(mMapper.createOrUpdatePatch(
                                aidlSources, aidlSinks, &newAidlPatchId, &cleanups));
                mMapper.updateFwkPatch(aidlPatchId, newAidlPatchId);
            } else {
                RETURN_STATUS_IF_ERROR(mMapper.createOrUpdatePatch(
                                aidlSources, aidlSinks, &aidlHalPatchId, &cleanups));
            }
        } else {
            RETURN_STATUS_IF_ERROR(mMapper.createOrUpdatePatch(
                            aidlSources, aidlSinks, &aidlPatchId, &cleanups));
        }
    }
    *patch = static_cast<audio_patch_handle_t>(aidlPatchId);
    cleanups.disarmAll();
    return OK;
}

status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    TIME_CHECK();
    if (mModule == nullptr) return NO_INIT;
    static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
    if (patch == AUDIO_PATCH_HANDLE_NONE) {
        return BAD_VALUE;
    }
    std::lock_guard l(mLock);
    // Check for patches that only exist for the framework, or have different HAL patch ID.
    int32_t aidlPatchId = static_cast<int32_t>(patch);
    if (int32_t aidlHalPatchId = mMapper.findFwkPatch(aidlPatchId); aidlHalPatchId != 0) {
        if (aidlHalPatchId == aidlPatchId) {
            // This patch was previously released by the HAL, just need to finish its removal.
            mMapper.eraseFwkPatch(aidlPatchId);
            return OK;
        } else {
            // This patch has a HAL patch ID which is different
            aidlPatchId = aidlHalPatchId;
        }
    }
    RETURN_STATUS_IF_ERROR(mMapper.releaseAudioPatch(aidlPatchId));
    return OK;
}

status_t DeviceHalAidl::getAudioPort(struct audio_port* port) {
    if (port == nullptr) {
        return BAD_VALUE;
    }
    audio_port_v7 portV7;
    audio_populate_audio_port_v7(port, &portV7);
    RETURN_STATUS_IF_ERROR(getAudioPort(&portV7));
    return audio_populate_audio_port(&portV7, port) ? OK : BAD_VALUE;
}

status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port) {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    TIME_CHECK();
    if (mModule == nullptr) return NO_INIT;
    if (port == nullptr) {
        return BAD_VALUE;
    }
    bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
            ::aidl::android::AudioPortDirection::INPUT;
    auto aidlPort = VALUE_OR_RETURN_STATUS(
            ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
    if (aidlPort.ext.getTag() != AudioPortExt::device) {
        ALOGE("%s: provided port is not a device port (module %s): %s",
                __func__, mInstance.c_str(), aidlPort.toString().c_str());
        return BAD_VALUE;
    }
    const auto& matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
    // It seems that we don't have to call HAL since all valid ports have been added either
    // during initialization, or while handling connection of an external device.
    const int32_t fwkId = aidlPort.id;
    {
        std::lock_guard l(mLock);
        RETURN_STATUS_IF_ERROR(mMapper.getAudioPortCached(matchDevice, &aidlPort));
    }
    aidlPort.id = fwkId;
    *port = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
                    aidlPort, isInput));
    return OK;
}

status_t DeviceHalAidl::getAudioMixPort(const struct audio_port_v7 *devicePort,
                                        struct audio_port_v7 *mixPort) {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    TIME_CHECK();
    if (mModule == nullptr) return NO_INIT;
    if (devicePort == nullptr || mixPort == nullptr ||
            devicePort->type != AUDIO_PORT_TYPE_DEVICE || mixPort->type != AUDIO_PORT_TYPE_MIX) {
        return BAD_VALUE;
    }
    const int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
            ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(mixPort->ext.mix.handle));
    AudioPort port;
    {
        std::lock_guard l(mLock);
        RETURN_STATUS_IF_ERROR(mMapper.getAudioMixPort(aidlHandle, &port));
    }
    const bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
            mixPort->role, mixPort->type)) == ::aidl::android::AudioPortDirection::INPUT;
    *mixPort = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
            port, isInput));
    return OK;
}

status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config) {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    TIME_CHECK();
    if (mModule == nullptr) return NO_INIT;
    if (config == nullptr) {
        return BAD_VALUE;
    }
    bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
                    config->role, config->type)) == ::aidl::android::AudioPortDirection::INPUT;
    AudioPortConfig requestedPortConfig = VALUE_OR_RETURN_STATUS(
            ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
                    *config, isInput, 0 /*portId*/));
    AudioPortConfig portConfig;
    std::lock_guard l(mLock);
    return mMapper.setPortConfig(requestedPortConfig, std::set<int32_t>(), &portConfig);
}

MicrophoneInfoProvider::Info const* DeviceHalAidl::getMicrophoneInfo() {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    TIME_CHECK();
    if (!mModule) return {};
    std::lock_guard l(mLock);
    if (mMicrophones.status == Microphones::Status::UNKNOWN) {
        TIME_CHECK();
        std::vector<MicrophoneInfo> aidlInfo;
        status_t status = statusTFromBinderStatus(mModule->getMicrophones(&aidlInfo));
        if (status == OK) {
            mMicrophones.status = Microphones::Status::QUERIED;
            mMicrophones.info = std::move(aidlInfo);
        } else if (status == INVALID_OPERATION) {
            mMicrophones.status = Microphones::Status::NOT_SUPPORTED;
        } else {
            ALOGE("%s: Unexpected status from 'IModule.getMicrophones': %d", __func__, status);
            return {};
        }
    }
    if (mMicrophones.status == Microphones::Status::QUERIED) {
        return &mMicrophones.info;
    }
    return {};  // NOT_SUPPORTED
}

status_t DeviceHalAidl::getMicrophones(
        std::vector<audio_microphone_characteristic_t>* microphones) {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    TIME_CHECK();
    if (mModule == nullptr) return NO_INIT;
    if (microphones == nullptr) {
        return BAD_VALUE;
    }
    auto staticInfo = getMicrophoneInfo();
    if (!staticInfo) return INVALID_OPERATION;
    std::vector<MicrophoneDynamicInfo> emptyDynamicInfo;
    emptyDynamicInfo.reserve(staticInfo->size());
    std::transform(staticInfo->begin(), staticInfo->end(), std::back_inserter(emptyDynamicInfo),
            [](const auto& info) { return MicrophoneDynamicInfo{ .id = info.id }; });
    *microphones = VALUE_OR_RETURN_STATUS(
            ::aidl::android::convertContainers<std::vector<audio_microphone_characteristic_t>>(
                    *staticInfo, emptyDynamicInfo,
                    ::aidl::android::aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t)
    );
    return OK;
}

status_t DeviceHalAidl::addDeviceEffect(
        const struct audio_port_config *device, sp<EffectHalInterface> effect) {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    TIME_CHECK();
    if (mModule == nullptr) return NO_INIT;
    if (device == nullptr || effect == nullptr) {
        return BAD_VALUE;
    }
    bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
                    device->role, device->type)) == ::aidl::android::AudioPortDirection::INPUT;
    auto requestedPortConfig = VALUE_OR_RETURN_STATUS(
            ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
                    *device, isInput, 0));
    if (requestedPortConfig.ext.getTag() != AudioPortExt::Tag::device) {
        ALOGE("%s: provided port config is not a device port config: %s",
                __func__, requestedPortConfig.toString().c_str());
        return BAD_VALUE;
    }
    AudioPortConfig devicePortConfig;
    Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
    {
        std::lock_guard l(mLock);
        RETURN_STATUS_IF_ERROR(mMapper.setPortConfig(
                    requestedPortConfig, {} /*destinationPortIds*/, &devicePortConfig, &cleanups));
    }
    auto aidlEffect = sp<effect::EffectHalAidl>::cast(effect);
    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->addDeviceEffect(
                            devicePortConfig.id, aidlEffect->getIEffect())));
    cleanups.disarmAll();
    return OK;
}
status_t DeviceHalAidl::removeDeviceEffect(
        const struct audio_port_config *device, sp<EffectHalInterface> effect) {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    TIME_CHECK();
    if (mModule == nullptr) return NO_INIT;
    if (device == nullptr || effect == nullptr) {
        return BAD_VALUE;
    }
    bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
                    device->role, device->type)) == ::aidl::android::AudioPortDirection::INPUT;
    auto requestedPortConfig = VALUE_OR_RETURN_STATUS(
            ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
                    *device, isInput, 0));
    if (requestedPortConfig.ext.getTag() != AudioPortExt::Tag::device) {
        ALOGE("%s: provided port config is not a device port config: %s",
                __func__, requestedPortConfig.toString().c_str());
        return BAD_VALUE;
    }
    AudioPortConfig devicePortConfig;
    {
        std::lock_guard l(mLock);
        RETURN_STATUS_IF_ERROR(mMapper.findPortConfig(
                        requestedPortConfig.ext.get<AudioPortExt::Tag::device>().device,
                        &devicePortConfig));
    }
    auto aidlEffect = sp<effect::EffectHalAidl>::cast(effect);
    return statusTFromBinderStatus(mModule->removeDeviceEffect(
                    devicePortConfig.id, aidlEffect->getIEffect()));
}

status_t DeviceHalAidl::getMmapPolicyInfos(
        media::audio::common::AudioMMapPolicyType policyType,
        std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    TIME_CHECK();
    if (mModule == nullptr) return NO_INIT;
    AudioMMapPolicyType mmapPolicyType = VALUE_OR_RETURN_STATUS(
            cpp2ndk_AudioMMapPolicyType(policyType));

    std::vector<AudioMMapPolicyInfo> mmapPolicyInfos;

    if (status_t status = statusTFromBinderStatus(
            mModule->getMmapPolicyInfos(mmapPolicyType, &mmapPolicyInfos)); status != OK) {
        return status;
    }

    *policyInfos = VALUE_OR_RETURN_STATUS(
            convertContainer<std::vector<media::audio::common::AudioMMapPolicyInfo>>(
                mmapPolicyInfos, ndk2cpp_AudioMMapPolicyInfo));
    return OK;
}

int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    TIME_CHECK();
    if (mModule == nullptr) return NO_INIT;
    int32_t mixerBurstCount = 0;
    if (mModule->getAAudioMixerBurstCount(&mixerBurstCount).isOk()) {
        return mixerBurstCount;
    }
    return 0;
}

int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    TIME_CHECK();
    if (mModule == nullptr) return NO_INIT;
    int32_t hardwareBurstMinUsec = 0;
    if (mModule->getAAudioHardwareBurstMinUsec(&hardwareBurstMinUsec).isOk()) {
        return hardwareBurstMinUsec;
    }
    return 0;
}

error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    TIME_CHECK();
    if (mModule == nullptr) return NO_INIT;
    int32_t aidlHwAvSync;
    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->generateHwAvSyncId(&aidlHwAvSync)));
    return VALUE_OR_RETURN_STATUS(
            ::aidl::android::aidl2legacy_int32_t_audio_hw_sync_t(aidlHwAvSync));
}

status_t DeviceHalAidl::dump(int fd, const Vector<String16>& args) {
    TIME_CHECK();
    if (mModule == nullptr) return NO_INIT;
    return mModule->dump(fd, Args(args).args(), args.size());
}

status_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    TIME_CHECK();
    if (mModule == nullptr) return NO_INIT;
    if (supports == nullptr) {
        return BAD_VALUE;
    }
    return statusTFromBinderStatus(mModule->supportsVariableLatency(supports));
}

status_t DeviceHalAidl::getSoundDoseInterface(const std::string& module,
                                              ::ndk::SpAIBinder* soundDoseBinder)  {
    if (soundDoseBinder == nullptr) {
        return BAD_VALUE;
    }
    if (mSoundDose == nullptr) {
        ALOGE("%s failed to retrieve the sound dose interface for module %s",
                __func__, module.c_str());
        return BAD_VALUE;
    }

    if (mSoundDose == nullptr) {
        ALOGE("%s failed to return the sound dose interface for module %s: not implemented",
                  __func__,
                  module.c_str());
        return NO_INIT;
    }

    *soundDoseBinder = mSoundDose->asBinder();
    ALOGI("%s using audio AIDL HAL sound dose interface", __func__);
    return OK;
}

status_t DeviceHalAidl::prepareToDisconnectExternalDevice(const struct audio_port_v7* port) {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    TIME_CHECK();
    if (mModule == nullptr) return NO_INIT;
    if (port == nullptr) {
        return BAD_VALUE;
    }
    const bool isInput = VALUE_OR_RETURN_STATUS(
            ::aidl::android::portDirection(port->role, port->type)) ==
                    ::aidl::android::AudioPortDirection::INPUT;
    AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
            ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
    if (aidlPort.ext.getTag() != AudioPortExt::device) {
        ALOGE("%s: provided port is not a device port (module %s): %s",
              __func__, mInstance.c_str(), aidlPort.toString().c_str());
        return BAD_VALUE;
    }
    status_t status = NO_ERROR;
    {
        std::lock_guard l(mLock);
        status = mMapper.prepareToDisconnectExternalDevice(aidlPort);
    }
    if (status == UNKNOWN_TRANSACTION) {
        // If there is not AIDL API defined for `prepareToDisconnectExternalDevice`.
        // Call `setConnectedState` instead.
        RETURN_STATUS_IF_ERROR(setConnectedState(port, false /*connected*/));
        std::lock_guard l(mLock);
        mDeviceDisconnectionNotified.insert(port->id);
        // Return that there was no error as otherwise the disconnection procedure will not be
        // considered complete for upper layers, and 'setConnectedState' will not be called again
        return OK;
    } else {
        return status;
    }
}

status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
    TIME_CHECK();
    if (mModule == nullptr) return NO_INIT;
    if (port == nullptr) {
        return BAD_VALUE;
    }
    if (!connected) {
        std::lock_guard l(mLock);
        if (mDeviceDisconnectionNotified.erase(port->id) > 0) {
            // For device disconnection, APM will first call `prepareToDisconnectExternalDevice`
            // and then call `setConnectedState`. If `prepareToDisconnectExternalDevice` doesn't
            // exit, `setConnectedState` will be called when calling
            // `prepareToDisconnectExternalDevice`. Do not call to the HAL if previous call is
            // successful. Also remove the cache here to avoid a large cache after a long run.
            return OK;
        }
    }
    bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
            ::aidl::android::AudioPortDirection::INPUT;
    AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
            ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
    if (aidlPort.ext.getTag() != AudioPortExt::device) {
        ALOGE("%s: provided port is not a device port (module %s): %s",
                __func__, mInstance.c_str(), aidlPort.toString().c_str());
        return BAD_VALUE;
    }
    std::lock_guard l(mLock);
    return mMapper.setDevicePortConnectedState(aidlPort, connected);
}

status_t DeviceHalAidl::setSimulateDeviceConnections(bool enabled) {
    TIME_CHECK();
    if (mModule == nullptr) return NO_INIT;
    {
        std::lock_guard l(mLock);
        mMapper.resetUnusedPatchesAndPortConfigs();
    }
    ModuleDebug debug{ .simulateDeviceConnections = enabled };
    status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
    // This is important to log as it affects HAL behavior.
    if (status == OK) {
        ALOGI("%s: set enabled: %d", __func__, enabled);
    } else {
        ALOGW("%s: set enabled to %d failed: %d", __func__, enabled, status);
    }
    return status;
}

status_t DeviceHalAidl::filterAndRetrieveBtA2dpParameters(
        AudioParameter &keys, AudioParameter *result) {
    if (String8 key = String8(AudioParameter::keyReconfigA2dpSupported); keys.containsKey(key)) {
        keys.remove(key);
        if (mBluetoothA2dp != nullptr) {
            bool supports;
            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
                            mBluetoothA2dp->supportsOffloadReconfiguration(&supports)));
            result->addInt(key, supports ? 1 : 0);
        } else {
            ALOGI("%s: no IBluetoothA2dp on %s", __func__, mInstance.c_str());
            result->addInt(key, 0);
        }
    }
    return OK;
}

status_t DeviceHalAidl::filterAndRetrieveBtLeParameters(
        AudioParameter &keys, AudioParameter *result) {
    if (String8 key = String8(AudioParameter::keyReconfigLeSupported); keys.containsKey(key)) {
        keys.remove(key);
        if (mBluetoothLe != nullptr) {
            bool supports;
            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
                            mBluetoothLe->supportsOffloadReconfiguration(&supports)));
            result->addInt(key, supports ? 1 : 0);
        } else {
            ALOGI("%s: no mBluetoothLe on %s", __func__, mInstance.c_str());
            result->addInt(key, 0);
        }
    }
    return OK;
}

status_t DeviceHalAidl::filterAndUpdateBtA2dpParameters(AudioParameter &parameters) {
    std::optional<bool> a2dpEnabled;
    std::optional<std::vector<VendorParameter>> reconfigureOffload;
    (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
                    parameters, String8(AudioParameter::keyBtA2dpSuspended),
                    [&a2dpEnabled](const String8& trueOrFalse) {
                        if (trueOrFalse == AudioParameter::valueTrue) {
                            a2dpEnabled = false;  // 'suspended' == true
                            return OK;
                        } else if (trueOrFalse == AudioParameter::valueFalse) {
                            a2dpEnabled = true;  // 'suspended' == false
                            return OK;
                        }
                        ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
                                AudioParameter::keyBtA2dpSuspended, trueOrFalse.c_str());
                        return BAD_VALUE;
                    }));
    (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
                    parameters, String8(AudioParameter::keyReconfigA2dp),
                    [&](const String8& value) -> status_t {
                        std::vector<VendorParameter> result;
                        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
                                mVendorExt->parseBluetoothA2dpReconfigureOffload(
                                        std::string(value.c_str()), &result)));
                        reconfigureOffload = std::move(result);
                        return OK;
                    }));
    if (mBluetoothA2dp != nullptr && a2dpEnabled.has_value()) {
        return statusTFromBinderStatus(mBluetoothA2dp->setEnabled(a2dpEnabled.value()));
    }
    if (mBluetoothA2dp != nullptr && reconfigureOffload.has_value()) {
        return statusTFromBinderStatus(mBluetoothA2dp->reconfigureOffload(
                        reconfigureOffload.value()));
    }
    return OK;
}

status_t DeviceHalAidl::filterAndUpdateBtHfpParameters(AudioParameter &parameters) {
    IBluetooth::HfpConfig hfpConfig;
    (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
                    parameters, String8(AudioParameter::keyBtHfpEnable),
                    [&hfpConfig](const String8& trueOrFalse) {
                        if (trueOrFalse == AudioParameter::valueTrue) {
                            hfpConfig.isEnabled = Boolean{ .value = true };
                            return OK;
                        } else if (trueOrFalse == AudioParameter::valueFalse) {
                            hfpConfig.isEnabled = Boolean{ .value = false };
                            return OK;
                        }
                        ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
                                AudioParameter::keyBtHfpEnable, trueOrFalse.c_str());
                        return BAD_VALUE;
                    }));
    (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
                    parameters, String8(AudioParameter::keyBtHfpSamplingRate),
                    [&hfpConfig](int sampleRate) {
                        return sampleRate > 0 ?
                                hfpConfig.sampleRate = Int{ .value = sampleRate }, OK : BAD_VALUE;
                    }));
    (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
                    parameters, String8(AudioParameter::keyBtHfpVolume),
                    [&hfpConfig](int volume0to15) {
                        if (volume0to15 >= 0 && volume0to15 <= 15) {
                            hfpConfig.volume = Float{ .value = volume0to15 / 15.0f };
                            return OK;
                        }
                        return BAD_VALUE;
                    }));
    if (mBluetooth != nullptr && hfpConfig != IBluetooth::HfpConfig{}) {
        IBluetooth::HfpConfig newHfpConfig;
        return statusTFromBinderStatus(mBluetooth->setHfpConfig(hfpConfig, &newHfpConfig));
    }
    return OK;
}

status_t DeviceHalAidl::filterAndUpdateBtLeParameters(AudioParameter &parameters) {
    std::optional<bool> leEnabled;
    std::optional<std::vector<VendorParameter>> reconfigureOffload;
    (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
                    parameters, String8(AudioParameter::keyBtLeSuspended),
                    [&leEnabled](const String8& trueOrFalse) {
                        if (trueOrFalse == AudioParameter::valueTrue) {
                            leEnabled = false;  // 'suspended' == true
                            return OK;
                        } else if (trueOrFalse == AudioParameter::valueFalse) {
                            leEnabled = true;  // 'suspended' == false
                            return OK;
                        }
                        ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
                                AudioParameter::keyBtLeSuspended, trueOrFalse.c_str());
                        return BAD_VALUE;
                    }));
    (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
                    parameters, String8(AudioParameter::keyReconfigLe),
                    [&](const String8& value) -> status_t {
                        if (mVendorExt != nullptr) {
                            std::vector<VendorParameter> result;
                            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
                                    mVendorExt->parseBluetoothLeReconfigureOffload(
                                            std::string(value.c_str()), &result)));
                            reconfigureOffload = std::move(result);
                        } else {
                            reconfigureOffload = std::vector<VendorParameter>();
                        }
                        return OK;
                    }));
    if (mBluetoothLe != nullptr && leEnabled.has_value()) {
        return statusTFromBinderStatus(mBluetoothLe->setEnabled(leEnabled.value()));
    }
    if (mBluetoothLe != nullptr && reconfigureOffload.has_value()) {
        return statusTFromBinderStatus(mBluetoothLe->reconfigureOffload(
                        reconfigureOffload.value()));
    }
    return OK;
}

status_t DeviceHalAidl::filterAndUpdateBtScoParameters(AudioParameter &parameters) {
    IBluetooth::ScoConfig scoConfig;
    (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
                    parameters, String8(AudioParameter::keyBtSco),
                    [&scoConfig](const String8& onOrOff) {
                        if (onOrOff == AudioParameter::valueOn) {
                            scoConfig.isEnabled = Boolean{ .value = true };
                            return OK;
                        } else if (onOrOff == AudioParameter::valueOff) {
                            scoConfig.isEnabled = Boolean{ .value = false };
                            return OK;
                        }
                        ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
                                AudioParameter::keyBtSco, onOrOff.c_str());
                        return BAD_VALUE;
                    }));
    (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
                    parameters, String8(AudioParameter::keyBtScoHeadsetName),
                    [&scoConfig](const String8& name) {
                        scoConfig.debugName = name;
                        return OK;
                    }));
    (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
                    parameters, String8(AudioParameter::keyBtNrec),
                    [&scoConfig](const String8& onOrOff) {
                        if (onOrOff == AudioParameter::valueOn) {
                            scoConfig.isNrecEnabled = Boolean{ .value = true };
                            return OK;
                        } else if (onOrOff == AudioParameter::valueOff) {
                            scoConfig.isNrecEnabled = Boolean{ .value = false };
                            return OK;
                        }
                        ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
                                AudioParameter::keyBtNrec, onOrOff.c_str());
                        return BAD_VALUE;
                    }));
    (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
                    parameters, String8(AudioParameter::keyBtScoWb),
                    [&scoConfig](const String8& onOrOff) {
                        if (onOrOff == AudioParameter::valueOn) {
                            scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO_WB;
                            return OK;
                        } else if (onOrOff == AudioParameter::valueOff) {
                            scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO;
                            return OK;
                        }
                        ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
                                AudioParameter::keyBtScoWb, onOrOff.c_str());
                        return BAD_VALUE;
                    }));
    if (mBluetooth != nullptr && scoConfig != IBluetooth::ScoConfig{}) {
        IBluetooth::ScoConfig newScoConfig;
        return statusTFromBinderStatus(mBluetooth->setScoConfig(scoConfig, &newScoConfig));
    }
    return OK;
}

status_t DeviceHalAidl::filterAndUpdateScreenParameters(AudioParameter &parameters) {
    (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
                    parameters, String8(AudioParameter::keyScreenState),
                    [&](const String8& onOrOff) -> status_t {
                        std::optional<bool> isTurnedOn;
                        if (onOrOff == AudioParameter::valueOn) {
                            isTurnedOn = true;
                        } else if (onOrOff == AudioParameter::valueOff) {
                            isTurnedOn = false;
                        }
                        if (!isTurnedOn.has_value()) {
                            ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
                                    AudioParameter::keyScreenState, onOrOff.c_str());
                            return BAD_VALUE;
                        }
                        return statusTFromBinderStatus(
                                mModule->updateScreenState(isTurnedOn.value()));
                    }));
    (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
                    parameters, String8(AudioParameter::keyScreenRotation),
            [&](int rotationDegrees) -> status_t {
                IModule::ScreenRotation rotation;
                switch (rotationDegrees) {
                    case 0: rotation = IModule::ScreenRotation::DEG_0; break;
                    case 90: rotation = IModule::ScreenRotation::DEG_90; break;
                    case 180: rotation = IModule::ScreenRotation::DEG_180; break;
                    case 270: rotation = IModule::ScreenRotation::DEG_270; break;
                    default:
                        ALOGE("setParameters: parameter key \"%s\" has invalid value %d",
                                AudioParameter::keyScreenRotation, rotationDegrees);
                        return BAD_VALUE;
                }
                return statusTFromBinderStatus(mModule->updateScreenRotation(rotation));
            }));
    return OK;
}

status_t DeviceHalAidl::filterAndUpdateTelephonyParameters(AudioParameter &parameters) {
    using TtyMode = ITelephony::TelecomConfig::TtyMode;
    ITelephony::TelecomConfig telConfig;
    (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
                    parameters, String8(AudioParameter::keyTtyMode),
                    [&telConfig](const String8& mode) {
                        if (mode == AudioParameter::valueTtyModeOff) {
                            telConfig.ttyMode = TtyMode::OFF;
                            return OK;
                        } else if (mode == AudioParameter::valueTtyModeFull) {
                            telConfig.ttyMode = TtyMode::FULL;
                            return OK;
                        } else if (mode == AudioParameter::valueTtyModeHco) {
                            telConfig.ttyMode = TtyMode::HCO;
                            return OK;
                        } else if (mode == AudioParameter::valueTtyModeVco) {
                            telConfig.ttyMode = TtyMode::VCO;
                            return OK;
                        }
                        ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
                                AudioParameter::keyTtyMode, mode.c_str());
                        return BAD_VALUE;
                    }));
    (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
                    parameters, String8(AudioParameter::keyHacSetting),
                    [&telConfig](const String8& onOrOff) {
                        if (onOrOff == AudioParameter::valueHacOn) {
                            telConfig.isHacEnabled = Boolean{ .value = true };
                            return OK;
                        } else if (onOrOff == AudioParameter::valueHacOff) {
                            telConfig.isHacEnabled = Boolean{ .value = false };
                            return OK;
                        }
                        ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
                                AudioParameter::keyHacSetting, onOrOff.c_str());
                        return BAD_VALUE;
                    }));
    if (mTelephony != nullptr && telConfig != ITelephony::TelecomConfig{}) {
        ITelephony::TelecomConfig newTelConfig;
        return statusTFromBinderStatus(
                mTelephony->setTelecomConfig(telConfig, &newTelConfig));
    }
    return OK;
}

void DeviceHalAidl::clearCallbacks(void* cookie) {
    std::lock_guard l(mLock);
    mCallbacks.erase(cookie);
}

sp<StreamOutHalInterfaceCallback> DeviceHalAidl::getStreamOutCallback(void* cookie) {
    return getCallbackImpl(cookie, &Callbacks::out);
}

void DeviceHalAidl::setStreamOutCallback(
        void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) {
    setCallbackImpl(cookie, &Callbacks::out, cb);
}

sp<StreamOutHalInterfaceEventCallback> DeviceHalAidl::getStreamOutEventCallback(
        void* cookie) {
    return getCallbackImpl(cookie, &Callbacks::event);
}

void DeviceHalAidl::setStreamOutEventCallback(
        void* cookie, const sp<StreamOutHalInterfaceEventCallback>& cb) {
    setCallbackImpl(cookie, &Callbacks::event, cb);
}

sp<StreamOutHalInterfaceLatencyModeCallback> DeviceHalAidl::getStreamOutLatencyModeCallback(
        void* cookie) {
    return getCallbackImpl(cookie, &Callbacks::latency);
}

void DeviceHalAidl::setStreamOutLatencyModeCallback(
        void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) {
    setCallbackImpl(cookie, &Callbacks::latency, cb);
}

template<class C>
sp<C> DeviceHalAidl::getCallbackImpl(void* cookie, wp<C> DeviceHalAidl::Callbacks::* field) {
    std::lock_guard l(mLock);
    if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
        return ((it->second).*field).promote();
    }
    return nullptr;
}
template<class C>
void DeviceHalAidl::setCallbackImpl(
        void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
    std::lock_guard l(mLock);
    if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
        (it->second).*field = cb;
    }
}

} // namespace android
