#include <inttypes.h>

#include <unordered_set>

#define LOG_TAG "AHAL_Config"
#include <android-base/logging.h>
#include <android-base/strings.h>

#include <aidl/android/media/audio/common/AudioPort.h>
#include <aidl/android/media/audio/common/AudioPortConfig.h>
#include <media/AidlConversionCppNdk.h>
#include <media/TypeConverter.h>
#include <media/convert.h>
#include <utils/FastStrcmp.h>

#include <Utils.h>

#include "core-impl/XmlConverter.h"
#include "core-impl/XsdcConversion.h"

using aidl::android::hardware::audio::common::iequals;
using aidl::android::hardware::audio::common::isValidAudioMode;
using aidl::android::hardware::audio::common::isValidAudioPolicyForcedConfig;
using aidl::android::hardware::audio::common::kValidAudioModes;
using aidl::android::hardware::audio::common::kValidAudioPolicyForcedConfig;
using aidl::android::media::audio::common::AudioChannelLayout;
using aidl::android::media::audio::common::AudioContentType;
using aidl::android::media::audio::common::AudioDevice;
using aidl::android::media::audio::common::AudioDeviceAddress;
using aidl::android::media::audio::common::AudioDeviceDescription;
using aidl::android::media::audio::common::AudioDeviceType;
using aidl::android::media::audio::common::AudioFormatDescription;
using aidl::android::media::audio::common::AudioFormatType;
using aidl::android::media::audio::common::AudioGain;
using aidl::android::media::audio::common::AudioHalCapCriterion;
using aidl::android::media::audio::common::AudioHalCapCriterionType;
using aidl::android::media::audio::common::AudioHalCapCriterionV2;
using aidl::android::media::audio::common::AudioHalVolumeCurve;
using aidl::android::media::audio::common::AudioIoFlags;
using aidl::android::media::audio::common::AudioMode;
using aidl::android::media::audio::common::AudioPolicyForcedConfig;
using aidl::android::media::audio::common::AudioPolicyForceUse;
using aidl::android::media::audio::common::AudioPort;
using aidl::android::media::audio::common::AudioPortConfig;
using aidl::android::media::audio::common::AudioPortDeviceExt;
using aidl::android::media::audio::common::AudioPortExt;
using aidl::android::media::audio::common::AudioPortMixExt;
using aidl::android::media::audio::common::AudioProfile;
using aidl::android::media::audio::common::AudioSource;
using aidl::android::media::audio::common::AudioStreamType;
using aidl::android::media::audio::common::AudioUsage;
using ::android::BAD_VALUE;
using ::android::base::unexpected;
using ::android::utilities::convertTo;

namespace ap_xsd = android::audio::policy::configuration;
namespace eng_xsd = android::audio::policy::engine::configuration;

namespace aidl::android::hardware::audio::core::internal {

static constexpr const char kXsdcForceConfigForCommunication[] = "ForceUseForCommunication";
static constexpr const char kXsdcForceConfigForMedia[] = "ForceUseForMedia";
static constexpr const char kXsdcForceConfigForRecord[] = "ForceUseForRecord";
static constexpr const char kXsdcForceConfigForDock[] = "ForceUseForDock";
static constexpr const char kXsdcForceConfigForSystem[] = "ForceUseForSystem";
static constexpr const char kXsdcForceConfigForHdmiSystemAudio[] = "ForceUseForHdmiSystemAudio";
static constexpr const char kXsdcForceConfigForEncodedSurround[] = "ForceUseForEncodedSurround";
static constexpr const char kXsdcForceConfigForVibrateRinging[] = "ForceUseForVibrateRinging";

inline ConversionResult<std::string> assertNonEmpty(const std::string& s) {
    if (s.empty()) {
        LOG(ERROR) << __func__ << " Review Audio Policy config: "
                   << " empty string is not valid.";
        return unexpected(BAD_VALUE);
    }
    return s;
}

#define NON_EMPTY_STRING_OR_FATAL(s) VALUE_OR_FATAL(assertNonEmpty(s))

ConversionResult<int32_t> convertAudioFlagsToAidl(
        const std::vector<eng_xsd::FlagType>& xsdcFlagTypeVec) {
    int legacyFlagMask = 0;
    for (const eng_xsd::FlagType& xsdcFlagType : xsdcFlagTypeVec) {
        if (xsdcFlagType != eng_xsd::FlagType::AUDIO_FLAG_NONE) {
            audio_flags_mask_t legacyFlag = AUDIO_FLAG_NONE;
            if (!::android::AudioFlagConverter::fromString(eng_xsd::toString(xsdcFlagType),
                                                           legacyFlag)) {
                LOG(ERROR) << __func__ << " Review Audio Policy config, "
                           << eng_xsd::toString(xsdcFlagType) << " is not a valid flag.";
                return unexpected(BAD_VALUE);
            }
            legacyFlagMask |= static_cast<int>(legacyFlag);
        }
    }
    ConversionResult<int32_t> result = legacy2aidl_audio_flags_mask_t_int32_t_mask(
            static_cast<audio_flags_mask_t>(legacyFlagMask));
    if (!result.ok()) {
        LOG(ERROR) << __func__ << " Review Audio Policy config, " << legacyFlagMask
                   << " has invalid flag(s).";
        return unexpected(BAD_VALUE);
    }
    return result;
}

ConversionResult<AudioStreamType> convertAudioStreamTypeToAidl(const eng_xsd::Stream& xsdcStream) {
    audio_stream_type_t legacyStreamType;
    if (!::android::StreamTypeConverter::fromString(eng_xsd::toString(xsdcStream),
                                                    legacyStreamType)) {
        LOG(ERROR) << __func__ << " Review Audio Policy config, " << eng_xsd::toString(xsdcStream)
                   << " is not a valid audio stream type.";
        return unexpected(BAD_VALUE);
    }
    ConversionResult<AudioStreamType> result =
            legacy2aidl_audio_stream_type_t_AudioStreamType(legacyStreamType);
    if (!result.ok()) {
        LOG(ERROR) << __func__ << " Review Audio Policy config, " << legacyStreamType
                   << " is not a valid audio stream type.";
        return unexpected(BAD_VALUE);
    }
    return result;
}

ConversionResult<AudioSource> convertAudioSourceToAidl(
        const eng_xsd::SourceEnumType& xsdcSourceType) {
    audio_source_t legacySourceType;
    if (!::android::SourceTypeConverter::fromString(eng_xsd::toString(xsdcSourceType),
                                                    legacySourceType)) {
        LOG(ERROR) << __func__ << " Review Audio Policy config, "
                   << eng_xsd::toString(xsdcSourceType) << " is not a valid audio source.";
        return unexpected(BAD_VALUE);
    }
    ConversionResult<AudioSource> result = legacy2aidl_audio_source_t_AudioSource(legacySourceType);
    if (!result.ok()) {
        LOG(ERROR) << __func__ << " Review Audio Policy config, " << legacySourceType
                   << " is not a valid audio source.";
        return unexpected(BAD_VALUE);
    }
    return result;
}

ConversionResult<AudioContentType> convertAudioContentTypeToAidl(
        const eng_xsd::ContentType& xsdcContentType) {
    audio_content_type_t legacyContentType;
    if (!::android::AudioContentTypeConverter::fromString(eng_xsd::toString(xsdcContentType),
                                                          legacyContentType)) {
        LOG(ERROR) << __func__ << " Review Audio Policy config, "
                   << eng_xsd::toString(xsdcContentType) << " is not a valid audio content type.";
        return unexpected(BAD_VALUE);
    }
    ConversionResult<AudioContentType> result =
            legacy2aidl_audio_content_type_t_AudioContentType(legacyContentType);
    if (!result.ok()) {
        LOG(ERROR) << __func__ << " Review Audio Policy config, " << legacyContentType
                   << " is not a valid audio content type.";
        return unexpected(BAD_VALUE);
    }
    return result;
}

ConversionResult<AudioUsage> convertAudioUsageToAidl(const eng_xsd::UsageEnumType& xsdcUsage) {
    audio_usage_t legacyUsage;
    if (!::android::UsageTypeConverter::fromString(eng_xsd::toString(xsdcUsage), legacyUsage)) {
        LOG(ERROR) << __func__ << " Review Audio Policy config, not a valid audio usage.";
        return unexpected(BAD_VALUE);
    }
    ConversionResult<AudioUsage> result = legacy2aidl_audio_usage_t_AudioUsage(legacyUsage);
    if (!result.ok()) {
        LOG(ERROR) << __func__ << " Review Audio Policy config, not a valid audio usage.";
        return unexpected(BAD_VALUE);
    }
    return result;
}

ConversionResult<AudioFormatDescription> convertAudioFormatToAidl(const std::string& xsdcFormat) {
    audio_format_t legacyFormat = ::android::formatFromString(xsdcFormat, AUDIO_FORMAT_DEFAULT);
    ConversionResult<AudioFormatDescription> result =
            legacy2aidl_audio_format_t_AudioFormatDescription(legacyFormat);
    if ((legacyFormat == AUDIO_FORMAT_DEFAULT && xsdcFormat.compare("AUDIO_FORMAT_DEFAULT") != 0) ||
        !result.ok()) {
        LOG(ERROR) << __func__ << " Review Audio Policy config: " << xsdcFormat
                   << " is not a valid audio format.";
        return unexpected(BAD_VALUE);
    }
    return result;
}

std::unordered_set<std::string> getAttachedDevices(const ap_xsd::Modules::Module& moduleConfig) {
    std::unordered_set<std::string> attachedDeviceSet;
    if (moduleConfig.hasAttachedDevices()) {
        for (const ap_xsd::AttachedDevices& attachedDevices : moduleConfig.getAttachedDevices()) {
            if (attachedDevices.hasItem()) {
                attachedDeviceSet.insert(attachedDevices.getItem().begin(),
                                         attachedDevices.getItem().end());
            }
        }
    }
    return attachedDeviceSet;
}

ConversionResult<AudioDeviceDescription> convertDeviceTypeToAidl(const std::string& xType) {
    audio_devices_t legacyDeviceType = AUDIO_DEVICE_NONE;
    ::android::DeviceConverter::fromString(xType, legacyDeviceType);
    ConversionResult<AudioDeviceDescription> result =
            legacy2aidl_audio_devices_t_AudioDeviceDescription(legacyDeviceType);
    if ((legacyDeviceType == AUDIO_DEVICE_NONE) || !result.ok()) {
        LOG(ERROR) << __func__ << " Review Audio Policy config: " << xType
                   << " is not a valid device type.";
        return unexpected(BAD_VALUE);
    }
    return result;
}

ConversionResult<AudioDevice> createAudioDevice(
        const ap_xsd::DevicePorts::DevicePort& xDevicePort) {
    AudioDevice device = {
            .type = VALUE_OR_FATAL(convertDeviceTypeToAidl(xDevicePort.getType())),
            .address = xDevicePort.hasAddress()
                               ? AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>(
                                         xDevicePort.getAddress())
                               : AudioDeviceAddress{}};
    if (device.type.type == AudioDeviceType::IN_MICROPHONE && device.type.connection.empty()) {
        device.address = "bottom";
    } else if (device.type.type == AudioDeviceType::IN_MICROPHONE_BACK &&
               device.type.connection.empty()) {
        device.address = "back";
    }
    return device;
}

ConversionResult<AudioPortExt> createAudioPortExt(
        const ap_xsd::DevicePorts::DevicePort& xDevicePort,
        const std::string& xDefaultOutputDevice) {
    AudioPortDeviceExt deviceExt = {
            .device = VALUE_OR_FATAL(createAudioDevice(xDevicePort)),
            .flags = (xDevicePort.getTagName() == xDefaultOutputDevice)
                             ? 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE
                             : 0,
            .encodedFormats =
                    xDevicePort.hasEncodedFormats()
                            ? VALUE_OR_FATAL(
                                      (convertCollectionToAidl<std::string, AudioFormatDescription>(
                                              xDevicePort.getEncodedFormats(),
                                              &convertAudioFormatToAidl)))
                            : std::vector<AudioFormatDescription>{},
    };
    return AudioPortExt::make<AudioPortExt::Tag::device>(deviceExt);
}

ConversionResult<AudioPortExt> createAudioPortExt(const ap_xsd::MixPorts::MixPort& xMixPort) {
    AudioPortMixExt mixExt = {
            .maxOpenStreamCount =
                    xMixPort.hasMaxOpenCount() ? static_cast<int>(xMixPort.getMaxOpenCount()) : 0,
            .maxActiveStreamCount = xMixPort.hasMaxActiveCount()
                                            ? static_cast<int>(xMixPort.getMaxActiveCount())
                                            : 1,
            .recommendedMuteDurationMs =
                    xMixPort.hasRecommendedMuteDurationMs()
                            ? static_cast<int>(xMixPort.getRecommendedMuteDurationMs())
                            : 0};
    return AudioPortExt::make<AudioPortExt::Tag::mix>(mixExt);
}

ConversionResult<int> convertGainModeToAidl(const std::vector<ap_xsd::AudioGainMode>& gainModeVec) {
    int gainModeMask = 0;
    for (const ap_xsd::AudioGainMode& gainMode : gainModeVec) {
        audio_gain_mode_t legacyGainMode;
        if (::android::GainModeConverter::fromString(ap_xsd::toString(gainMode), legacyGainMode)) {
            gainModeMask |= static_cast<int>(legacyGainMode);
        }
    }
    return gainModeMask;
}

ConversionResult<AudioChannelLayout> convertChannelMaskToAidl(
        const ap_xsd::AudioChannelMask& xChannelMask) {
    std::string xChannelMaskLiteral = ap_xsd::toString(xChannelMask);
    audio_channel_mask_t legacyChannelMask = ::android::channelMaskFromString(xChannelMaskLiteral);
    ConversionResult<AudioChannelLayout> result =
            legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
                    legacyChannelMask,
                    /* isInput= */ xChannelMaskLiteral.find("AUDIO_CHANNEL_IN_") == 0);
    if ((legacyChannelMask == AUDIO_CHANNEL_INVALID) || !result.ok()) {
        LOG(ERROR) << __func__ << " Review Audio Policy config: " << xChannelMaskLiteral
                   << " is not a valid audio channel mask.";
        return unexpected(BAD_VALUE);
    }
    return result;
}

ConversionResult<AudioGain> convertGainToAidl(const ap_xsd::Gains::Gain& xGain) {
    return AudioGain{
            .mode = VALUE_OR_FATAL(convertGainModeToAidl(xGain.getMode())),
            .channelMask =
                    xGain.hasChannel_mask()
                            ? VALUE_OR_FATAL(convertChannelMaskToAidl(xGain.getChannel_mask()))
                            : AudioChannelLayout{},
            .minValue = xGain.hasMinValueMB() ? xGain.getMinValueMB() : 0,
            .maxValue = xGain.hasMaxValueMB() ? xGain.getMaxValueMB() : 0,
            .defaultValue = xGain.hasDefaultValueMB() ? xGain.getDefaultValueMB() : 0,
            .stepValue = xGain.hasStepValueMB() ? xGain.getStepValueMB() : 0,
            .minRampMs = xGain.hasMinRampMs() ? xGain.getMinRampMs() : 0,
            .maxRampMs = xGain.hasMaxRampMs() ? xGain.getMaxRampMs() : 0,
            .useForVolume = xGain.hasUseForVolume() ? xGain.getUseForVolume() : false,
    };
}

ConversionResult<AudioProfile> convertAudioProfileToAidl(const ap_xsd::Profile& xProfile) {
    return AudioProfile{
            .format = xProfile.hasFormat()
                              ? VALUE_OR_FATAL(convertAudioFormatToAidl(xProfile.getFormat()))
                              : AudioFormatDescription{},
            .channelMasks =
                    xProfile.hasChannelMasks()
                            ? VALUE_OR_FATAL((convertCollectionToAidl<ap_xsd::AudioChannelMask,
                                                                      AudioChannelLayout>(
                                      xProfile.getChannelMasks(), &convertChannelMaskToAidl)))
                            : std::vector<AudioChannelLayout>{},
            .sampleRates = xProfile.hasSamplingRates()
                                   ? VALUE_OR_FATAL((convertCollectionToAidl<int64_t, int>(
                                             xProfile.getSamplingRates(),
                                             [](const int64_t x) -> int { return x; })))
                                   : std::vector<int>{}};
}

ConversionResult<AudioIoFlags> convertIoFlagsToAidl(
        const std::vector<ap_xsd::AudioInOutFlag>& flags, const ap_xsd::Role role,
        bool flagsForMixPort) {
    int legacyFlagMask = 0;
    if ((role == ap_xsd::Role::sink && flagsForMixPort) ||
        (role == ap_xsd::Role::source && !flagsForMixPort)) {
        for (const ap_xsd::AudioInOutFlag& flag : flags) {
            audio_input_flags_t legacyFlag;
            if (::android::InputFlagConverter::fromString(ap_xsd::toString(flag), legacyFlag)) {
                legacyFlagMask |= static_cast<int>(legacyFlag);
            }
        }
        return AudioIoFlags::make<AudioIoFlags::Tag::input>(
                VALUE_OR_FATAL(legacy2aidl_audio_input_flags_t_int32_t_mask(
                        static_cast<audio_input_flags_t>(legacyFlagMask))));
    } else {
        for (const ap_xsd::AudioInOutFlag& flag : flags) {
            audio_output_flags_t legacyFlag;
            if (::android::OutputFlagConverter::fromString(ap_xsd::toString(flag), legacyFlag)) {
                legacyFlagMask |= static_cast<int>(legacyFlag);
            }
        }
        return AudioIoFlags::make<AudioIoFlags::Tag::output>(
                VALUE_OR_FATAL(legacy2aidl_audio_output_flags_t_int32_t_mask(
                        static_cast<audio_output_flags_t>(legacyFlagMask))));
    }
}

ConversionResult<AudioPort> convertDevicePortToAidl(
        const ap_xsd::DevicePorts::DevicePort& xDevicePort, const std::string& xDefaultOutputDevice,
        int32_t& nextPortId) {
    return AudioPort{
            .id = nextPortId++,
            .name = NON_EMPTY_STRING_OR_FATAL(xDevicePort.getTagName()),
            .profiles = VALUE_OR_FATAL((convertCollectionToAidl<ap_xsd::Profile, AudioProfile>(
                    xDevicePort.getProfile(), convertAudioProfileToAidl))),
            .flags = VALUE_OR_FATAL(convertIoFlagsToAidl({}, xDevicePort.getRole(), false)),
            .gains = VALUE_OR_FATAL(
                    (convertWrappedCollectionToAidl<ap_xsd::Gains, ap_xsd::Gains::Gain, AudioGain>(
                            xDevicePort.getGains(), &ap_xsd::Gains::getGain, convertGainToAidl))),

            .ext = VALUE_OR_FATAL(createAudioPortExt(xDevicePort, xDefaultOutputDevice))};
}

ConversionResult<std::vector<AudioPort>> convertDevicePortsInModuleToAidl(
        const ap_xsd::Modules::Module& xModuleConfig, int32_t& nextPortId) {
    std::vector<AudioPort> audioPortVec;
    std::vector<ap_xsd::DevicePorts> xDevicePortsVec = xModuleConfig.getDevicePorts();
    if (xDevicePortsVec.size() > 1) {
        LOG(ERROR) << __func__ << "Having multiple '<devicePorts>' elements is not allowed, found: "
                   << xDevicePortsVec.size();
        return unexpected(BAD_VALUE);
    }
    if (!xDevicePortsVec.empty()) {
        const std::string xDefaultOutputDevice = xModuleConfig.hasDefaultOutputDevice()
                                                         ? xModuleConfig.getDefaultOutputDevice()
                                                         : "";
        audioPortVec.reserve(xDevicePortsVec[0].getDevicePort().size());
        for (const ap_xsd::DevicePorts& xDevicePortsType : xDevicePortsVec) {
            for (const ap_xsd::DevicePorts::DevicePort& xDevicePort :
                 xDevicePortsType.getDevicePort()) {
                audioPortVec.push_back(VALUE_OR_FATAL(
                        convertDevicePortToAidl(xDevicePort, xDefaultOutputDevice, nextPortId)));
            }
        }
    }
    const std::unordered_set<std::string> xAttachedDeviceSet = getAttachedDevices(xModuleConfig);
    for (const auto& port : audioPortVec) {
        const auto& devicePort = port.ext.get<AudioPortExt::device>();
        if (xAttachedDeviceSet.count(port.name) != devicePort.device.type.connection.empty()) {
            LOG(ERROR) << __func__ << ": Review Audio Policy config: <attachedDevices> "
                       << "list is incorrect or devicePort \"" << port.name
                       << "\" type= " << devicePort.device.type.toString() << " is incorrect.";
            return unexpected(BAD_VALUE);
        }
    }
    return audioPortVec;
}

ConversionResult<AudioPort> convertMixPortToAidl(const ap_xsd::MixPorts::MixPort& xMixPort,
                                                 int32_t& nextPortId) {
    return AudioPort{
            .id = nextPortId++,
            .name = NON_EMPTY_STRING_OR_FATAL(xMixPort.getName()),
            .profiles = VALUE_OR_FATAL((convertCollectionToAidl<ap_xsd::Profile, AudioProfile>(
                    xMixPort.getProfile(), convertAudioProfileToAidl))),
            .flags = xMixPort.hasFlags()
                             ? VALUE_OR_FATAL(convertIoFlagsToAidl(xMixPort.getFlags(),
                                                                   xMixPort.getRole(), true))
                             : VALUE_OR_FATAL(convertIoFlagsToAidl({}, xMixPort.getRole(), true)),
            .gains = VALUE_OR_FATAL(
                    (convertWrappedCollectionToAidl<ap_xsd::Gains, ap_xsd::Gains::Gain, AudioGain>(
                            xMixPort.getGains(), &ap_xsd::Gains::getGain, &convertGainToAidl))),
            .ext = VALUE_OR_FATAL(createAudioPortExt(xMixPort)),
    };
}

ConversionResult<std::vector<AudioPort>> convertMixPortsInModuleToAidl(
        const ap_xsd::Modules::Module& xModuleConfig, int32_t& nextPortId) {
    std::vector<AudioPort> audioPortVec;
    std::vector<ap_xsd::MixPorts> xMixPortsVec = xModuleConfig.getMixPorts();
    if (xMixPortsVec.size() > 1) {
        LOG(ERROR) << __func__ << "Having multiple '<mixPorts>' elements is not allowed, found: "
                   << xMixPortsVec.size();
        return unexpected(BAD_VALUE);
    }
    if (!xMixPortsVec.empty()) {
        audioPortVec.reserve(xMixPortsVec[0].getMixPort().size());
        for (const ap_xsd::MixPorts& xMixPortsType : xMixPortsVec) {
            for (const ap_xsd::MixPorts::MixPort& xMixPort : xMixPortsType.getMixPort()) {
                audioPortVec.push_back(VALUE_OR_FATAL(convertMixPortToAidl(xMixPort, nextPortId)));
            }
        }
    }
    return audioPortVec;
}

ConversionResult<int32_t> getSinkPortId(const ap_xsd::Routes::Route& xRoute,
                                        const std::unordered_map<std::string, int32_t>& portMap) {
    auto portMapIter = portMap.find(xRoute.getSink());
    if (portMapIter == portMap.end()) {
        LOG(ERROR) << __func__ << " Review Audio Policy config: audio route"
                   << "has sink: " << xRoute.getSink()
                   << " which is neither a device port nor mix port.";
        return unexpected(BAD_VALUE);
    }
    return portMapIter->second;
}

ConversionResult<std::vector<int32_t>> getSourcePortIds(
        const ap_xsd::Routes::Route& xRoute,
        const std::unordered_map<std::string, int32_t>& portMap) {
    std::vector<int32_t> sourcePortIds;
    for (const std::string& rawSource : ::android::base::Split(xRoute.getSources(), ",")) {
        const std::string source = ::android::base::Trim(rawSource);
        auto portMapIter = portMap.find(source);
        if (portMapIter == portMap.end()) {
            LOG(ERROR) << __func__ << " Review Audio Policy config: audio route"
                       << "has source \"" << source
                       << "\" which is neither a device port nor mix port.";
            return unexpected(BAD_VALUE);
        }
        sourcePortIds.push_back(portMapIter->second);
    }
    return sourcePortIds;
}

ConversionResult<AudioRoute> convertRouteToAidl(const ap_xsd::Routes::Route& xRoute,
                                                const std::vector<AudioPort>& aidlAudioPorts) {
    std::unordered_map<std::string, int32_t> portMap;
    for (const AudioPort& port : aidlAudioPorts) {
        portMap.insert({port.name, port.id});
    }
    return AudioRoute{.sourcePortIds = VALUE_OR_FATAL(getSourcePortIds(xRoute, portMap)),
                      .sinkPortId = VALUE_OR_FATAL(getSinkPortId(xRoute, portMap)),
                      .isExclusive = (xRoute.getType() == ap_xsd::MixType::mux)};
}

ConversionResult<std::vector<AudioRoute>> convertRoutesInModuleToAidl(
        const ap_xsd::Modules::Module& xModuleConfig,
        const std::vector<AudioPort>& aidlAudioPorts) {
    std::vector<AudioRoute> audioRouteVec;
    std::vector<ap_xsd::Routes> xRoutesVec = xModuleConfig.getRoutes();
    if (!xRoutesVec.empty()) {
        /*
         * xRoutesVec likely only contains one element; that is, it's
         * likely that all ap_xsd::Routes::MixPort types that we need to convert
         * are inside of xRoutesVec[0].
         */
        audioRouteVec.reserve(xRoutesVec[0].getRoute().size());
        for (const ap_xsd::Routes& xRoutesType : xRoutesVec) {
            for (const ap_xsd::Routes::Route& xRoute : xRoutesType.getRoute()) {
                audioRouteVec.push_back(VALUE_OR_FATAL(convertRouteToAidl(xRoute, aidlAudioPorts)));
            }
        }
    }
    return audioRouteVec;
}

ConversionResult<std::unique_ptr<Module::Configuration>> convertModuleConfigToAidl(
        const ap_xsd::Modules::Module& xModuleConfig) {
    auto result = std::make_unique<Module::Configuration>();
    auto& aidlModuleConfig = *result;
    std::vector<AudioPort> devicePorts = VALUE_OR_FATAL(
            convertDevicePortsInModuleToAidl(xModuleConfig, aidlModuleConfig.nextPortId));

    // The XML config does not specify the default input device.
    // Assign the first attached input device as the default.
    for (auto& port : devicePorts) {
        if (port.flags.getTag() != AudioIoFlags::input) continue;
        auto& deviceExt = port.ext.get<AudioPortExt::device>();
        if (!deviceExt.device.type.connection.empty()) continue;
        deviceExt.flags |= 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE;
        break;
    }

    std::vector<AudioPort> mixPorts = VALUE_OR_FATAL(
            convertMixPortsInModuleToAidl(xModuleConfig, aidlModuleConfig.nextPortId));
    aidlModuleConfig.ports.reserve(devicePorts.size() + mixPorts.size());
    aidlModuleConfig.ports.insert(aidlModuleConfig.ports.end(), devicePorts.begin(),
                                  devicePorts.end());
    aidlModuleConfig.ports.insert(aidlModuleConfig.ports.end(), mixPorts.begin(), mixPorts.end());

    aidlModuleConfig.routes =
            VALUE_OR_FATAL(convertRoutesInModuleToAidl(xModuleConfig, aidlModuleConfig.ports));
    return result;
}

ConversionResult<AudioPolicyForcedConfig> convertForcedConfigToAidl(
        const std::string& xsdcForcedConfigCriterionType) {
    const auto it = std::find_if(
            kValidAudioPolicyForcedConfig.begin(), kValidAudioPolicyForcedConfig.end(),
            [&](const auto& config) { return toString(config) == xsdcForcedConfigCriterionType; });
    if (it == kValidAudioPolicyForcedConfig.end()) {
        LOG(ERROR) << __func__ << " invalid forced config " << xsdcForcedConfigCriterionType;
        return unexpected(BAD_VALUE);
    }
    return *it;
}

ConversionResult<AudioMode> convertTelephonyModeToAidl(const std::string& xsdcModeCriterionType) {
    const auto it = std::find_if(kValidAudioModes.begin(), kValidAudioModes.end(),
                                 [&xsdcModeCriterionType](const auto& mode) {
                                     return toString(mode) == xsdcModeCriterionType;
                                 });
    if (it == kValidAudioModes.end()) {
        LOG(ERROR) << __func__ << " invalid mode " << xsdcModeCriterionType;
        return unexpected(BAD_VALUE);
    }
    return *it;
}

ConversionResult<AudioDeviceAddress> convertDeviceAddressToAidl(const std::string& xsdcAddress) {
    return AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>(xsdcAddress);
}

ConversionResult<eng_xsd::CriterionTypeType> getCriterionTypeByName(
        const std::string& name,
        const std::vector<eng_xsd::CriterionTypesType>& xsdcCriterionTypesVec) {
    for (const auto& xsdCriterionTypes : xsdcCriterionTypesVec) {
        for (const auto& xsdcCriterionType : xsdCriterionTypes.getCriterion_type()) {
            if (xsdcCriterionType.getName() == name) {
                return xsdcCriterionType;
            }
        }
    }
    LOG(ERROR) << __func__ << " failed to find criterion type " << name;
    return unexpected(BAD_VALUE);
}

ConversionResult<std::vector<std::optional<AudioHalCapCriterionV2>>>
convertCapCriteriaCollectionToAidl(
        const std::vector<eng_xsd::CriteriaType>& xsdcCriteriaVec,
        const std::vector<eng_xsd::CriterionTypesType>& xsdcCriterionTypesVec) {
    std::vector<std::optional<AudioHalCapCriterionV2>> resultAidlCriterionVec;
    if (xsdcCriteriaVec.empty() || xsdcCriterionTypesVec.empty()) {
        LOG(ERROR) << __func__ << " empty criteria/criterionTypes";
        return unexpected(BAD_VALUE);
    }
    for (const auto& xsdCriteria : xsdcCriteriaVec) {
        for (const auto& xsdcCriterion : xsdCriteria.getCriterion()) {
            resultAidlCriterionVec.push_back(
                    std::optional<AudioHalCapCriterionV2>(VALUE_OR_FATAL(
                            convertCapCriterionV2ToAidl(xsdcCriterion, xsdcCriterionTypesVec))));
        }
    }
    return resultAidlCriterionVec;
}

ConversionResult<std::vector<AudioDeviceDescription>> convertDevicesToAidl(
        const eng_xsd::CriterionTypeType& xsdcDeviceCriterionType) {
    if (xsdcDeviceCriterionType.getValues().empty()) {
        LOG(ERROR) << __func__ << " no values provided";
        return unexpected(BAD_VALUE);
    }
    std::vector<AudioDeviceDescription> aidlDevices;
    for (eng_xsd::ValuesType xsdcValues : xsdcDeviceCriterionType.getValues()) {
        aidlDevices.reserve(xsdcValues.getValue().size());
        for (const eng_xsd::ValueType& xsdcValue : xsdcValues.getValue()) {
            if (!xsdcValue.hasAndroid_type()) {
                LOG(ERROR) << __func__ << " empty android type";
                return unexpected(BAD_VALUE);
            }
            uint32_t integerValue;
            if (!convertTo(xsdcValue.getAndroid_type(), integerValue)) {
                LOG(ERROR) << __func__ << " failed to convert android type "
                           << xsdcValue.getAndroid_type();
                return unexpected(BAD_VALUE);
            }
            aidlDevices.push_back(
                    VALUE_OR_RETURN(legacy2aidl_audio_devices_t_AudioDeviceDescription(
                            static_cast<audio_devices_t>(integerValue))));
        }
    }
    return aidlDevices;
}

ConversionResult<std::vector<AudioDeviceAddress>> convertDeviceAddressesToAidl(
        const eng_xsd::CriterionTypeType& xsdcDeviceAddressesCriterionType) {
    if (xsdcDeviceAddressesCriterionType.getValues().empty()) {
        LOG(ERROR) << __func__ << " no values provided";
        return unexpected(BAD_VALUE);
    }
    std::vector<AudioDeviceAddress> aidlDeviceAddresses;
    for (eng_xsd::ValuesType xsdcValues : xsdcDeviceAddressesCriterionType.getValues()) {
        aidlDeviceAddresses.reserve(xsdcValues.getValue().size());
        for (const eng_xsd::ValueType& xsdcValue : xsdcValues.getValue()) {
            aidlDeviceAddresses.push_back(
                    AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>(xsdcValue.getLiteral()));
        }
    }
    return aidlDeviceAddresses;
}

ConversionResult<std::vector<AudioMode>> convertTelephonyModesToAidl(
        const eng_xsd::CriterionTypeType& xsdcTelephonyModeCriterionType) {
    if (xsdcTelephonyModeCriterionType.getValues().empty()) {
        LOG(ERROR) << __func__ << " no values provided";
        return unexpected(BAD_VALUE);
    }
    std::vector<AudioMode> aidlAudioModes;
    for (eng_xsd::ValuesType xsdcValues : xsdcTelephonyModeCriterionType.getValues()) {
        aidlAudioModes.reserve(xsdcValues.getValue().size());
        for (const eng_xsd::ValueType& xsdcValue : xsdcValues.getValue()) {
            int integerValue = xsdcValue.getNumerical();
            if (!isValidAudioMode(AudioMode(integerValue))) {
                LOG(ERROR) << __func__ << " invalid audio mode " << integerValue;
                return unexpected(BAD_VALUE);
            }
            aidlAudioModes.push_back(AudioMode(integerValue));
        }
    }
    return aidlAudioModes;
}

ConversionResult<std::vector<AudioPolicyForcedConfig>> convertForcedConfigsToAidl(
        const eng_xsd::CriterionTypeType& xsdcForcedConfigCriterionType) {
    if (xsdcForcedConfigCriterionType.getValues().empty()) {
        LOG(ERROR) << __func__ << " no values provided";
        return unexpected(BAD_VALUE);
    }
    std::vector<AudioPolicyForcedConfig> aidlForcedConfigs;
    for (eng_xsd::ValuesType xsdcValues : xsdcForcedConfigCriterionType.getValues()) {
        aidlForcedConfigs.reserve(xsdcValues.getValue().size());
        for (const eng_xsd::ValueType& xsdcValue : xsdcValues.getValue()) {
            int integerValue = xsdcValue.getNumerical();
            if (!isValidAudioPolicyForcedConfig(AudioPolicyForcedConfig(integerValue))) {
                LOG(ERROR) << __func__ << " invalid forced config mode " << integerValue;
                return unexpected(BAD_VALUE);
            }
            aidlForcedConfigs.push_back(AudioPolicyForcedConfig(integerValue));
        }
    }
    return aidlForcedConfigs;
}

ConversionResult<AudioPolicyForceUse> convertForceUseCriterionToAidl(
        const std::string& xsdcCriterionName) {
    if (!fastcmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForCommunication,
            strlen(kXsdcForceConfigForCommunication))) {
        return AudioPolicyForceUse::COMMUNICATION;
    }
    if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForMedia,
            strlen(kXsdcForceConfigForMedia))) {
        return AudioPolicyForceUse::MEDIA;
    }
    if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForRecord,
            strlen(kXsdcForceConfigForRecord))) {
        return AudioPolicyForceUse::RECORD;
    }
    if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForDock,
            strlen(kXsdcForceConfigForDock))) {
        return AudioPolicyForceUse::DOCK;
    }
    if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForSystem,
            strlen(kXsdcForceConfigForSystem))) {
        return AudioPolicyForceUse::SYSTEM;
    }
    if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForHdmiSystemAudio,
            strlen(kXsdcForceConfigForHdmiSystemAudio))) {
        return AudioPolicyForceUse::HDMI_SYSTEM_AUDIO;
    }
    if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForEncodedSurround,
            strlen(kXsdcForceConfigForEncodedSurround))) {
        return AudioPolicyForceUse::ENCODED_SURROUND;
    }
    if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForVibrateRinging,
            strlen(kXsdcForceConfigForVibrateRinging))) {
        return AudioPolicyForceUse::VIBRATE_RINGING;
    }
    LOG(ERROR) << __func__ << " unrecognized force use " << xsdcCriterionName;
    return unexpected(BAD_VALUE);
}

ConversionResult<AudioHalCapCriterionV2> convertCapCriterionV2ToAidl(
        const eng_xsd::CriterionType& xsdcCriterion,
        const std::vector<eng_xsd::CriterionTypesType>& xsdcCriterionTypesVec) {
    eng_xsd::CriterionTypeType xsdcCriterionType =
            VALUE_OR_RETURN(getCriterionTypeByName(xsdcCriterion.getType(), xsdcCriterionTypesVec));
    std::string defaultLiteralValue =
            xsdcCriterion.has_default() ? xsdcCriterion.get_default() : "";
    using Tag = AudioHalCapCriterionV2::Tag;
    if (iequals(xsdcCriterion.getName(), toString(Tag::availableInputDevices))) {
        return AudioHalCapCriterionV2::make<Tag::availableInputDevices>(
                VALUE_OR_RETURN(convertDevicesToAidl(xsdcCriterionType)));
    }
    if (iequals(xsdcCriterion.getName(), toString(Tag::availableOutputDevices))) {
        return AudioHalCapCriterionV2::make<Tag::availableOutputDevices>(
                VALUE_OR_RETURN(convertDevicesToAidl(xsdcCriterionType)));
    }
    if (iequals(xsdcCriterion.getName(), toString(Tag::availableInputDevicesAddresses))) {
        return AudioHalCapCriterionV2::make<Tag::availableInputDevicesAddresses>(
                VALUE_OR_RETURN(convertDeviceAddressesToAidl(xsdcCriterionType)));
    }
    if (iequals(xsdcCriterion.getName(), toString(Tag::availableOutputDevicesAddresses))) {
        return AudioHalCapCriterionV2::make<Tag::availableOutputDevicesAddresses>(
                VALUE_OR_RETURN(convertDeviceAddressesToAidl(xsdcCriterionType)));
    }
    if (iequals(xsdcCriterion.getName(), toString(Tag::telephonyMode))) {
        return AudioHalCapCriterionV2::make<Tag::telephonyMode>(
                VALUE_OR_RETURN(convertTelephonyModesToAidl(xsdcCriterionType)));
    }
    if (!fastcmp<strncmp>(xsdcCriterion.getName().c_str(), kXsdcForceConfigForUse,
            strlen(kXsdcForceConfigForUse))) {
        return AudioHalCapCriterionV2::make<Tag::forceConfigForUse>(
                VALUE_OR_RETURN(convertForceUseCriterionToAidl(xsdcCriterion.getName())),
                VALUE_OR_RETURN(convertForcedConfigsToAidl(xsdcCriterionType)));
    }
    LOG(ERROR) << __func__ << " unrecognized criterion " << xsdcCriterion.getName();
    return unexpected(BAD_VALUE);
}

ConversionResult<AudioHalCapCriterion> convertCapCriterionToAidl(
        const eng_xsd::CriterionType& xsdcCriterion) {
    AudioHalCapCriterion aidlCapCriterion;
    aidlCapCriterion.name = xsdcCriterion.getName();
    aidlCapCriterion.criterionTypeName = xsdcCriterion.getType();
    aidlCapCriterion.defaultLiteralValue =
            xsdcCriterion.has_default() ? xsdcCriterion.get_default() : "";
    return aidlCapCriterion;
}

ConversionResult<AudioHalVolumeCurve::CurvePoint> convertCurvePointToAidl(
        const std::string& xsdcCurvePoint) {
    AudioHalVolumeCurve::CurvePoint aidlCurvePoint{};
    if ((sscanf(xsdcCurvePoint.c_str(), "%" SCNd8 ",%d", &aidlCurvePoint.index,
                &aidlCurvePoint.attenuationMb) != 2) ||
        (aidlCurvePoint.index < AudioHalVolumeCurve::CurvePoint::MIN_INDEX) ||
        (aidlCurvePoint.index > AudioHalVolumeCurve::CurvePoint::MAX_INDEX)) {
        LOG(ERROR) << __func__ << " Review Audio Policy config: volume curve point:"
                   << "\"" << xsdcCurvePoint << "\" is invalid";
        return unexpected(BAD_VALUE);
    }
    return aidlCurvePoint;
}
}  // namespace aidl::android::hardware::audio::core::internal
