Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 00a73078 authored by Lorena Torres-Huerta's avatar Lorena Torres-Huerta Committed by Mikhail Naganov
Browse files

audio: Parse module configurations from the APM XML files

The default implementation now loads the HAL configuration
from the legacy XML configuration file which was previously
consumed by the framework directly.

Note that errors in the config file will lead to crash
of the XML parser, pointing out to the source of the problem.

IMPORTANT NOTES:
  - Never use untested legacy config files with production
    devices.
  - Make sure that all possible configurations (for example,
    BT offload on/off) are tested.

Bug: 205884982
Test: atest VtsHalAudioCoreTargetTest
Change-Id: I01e4cd77a284d7df64ecb0c0b21cb16abfa0f6c5
parent 816e644a
Loading
Loading
Loading
Loading
+10 −0
Original line number Original line Diff line number Diff line
@@ -12,6 +12,7 @@ cc_defaults {
    vendor: true,
    vendor: true,
    shared_libs: [
    shared_libs: [
        "libalsautilsv2",
        "libalsautilsv2",
        "libaudio_aidl_conversion_common_ndk",
        "libaudioaidlcommon",
        "libaudioaidlcommon",
        "libaudioutils",
        "libaudioutils",
        "libbase",
        "libbase",
@@ -19,6 +20,8 @@ cc_defaults {
        "libcutils",
        "libcutils",
        "libfmq",
        "libfmq",
        "libnbaio_mono",
        "libnbaio_mono",
        "liblog",
        "libmedia_helper",
        "libstagefright_foundation",
        "libstagefright_foundation",
        "libtinyalsav2",
        "libtinyalsav2",
        "libutils",
        "libutils",
@@ -31,6 +34,9 @@ cc_defaults {
        "libaudioaidl_headers",
        "libaudioaidl_headers",
        "libxsdc-utils",
        "libxsdc-utils",
    ],
    ],
    cflags: [
        "-DBACKEND_NDK",
    ],
}
}


cc_library {
cc_library {
@@ -78,6 +84,7 @@ cc_library {
        "Stream.cpp",
        "Stream.cpp",
        "StreamSwitcher.cpp",
        "StreamSwitcher.cpp",
        "Telephony.cpp",
        "Telephony.cpp",
        "XsdcConversion.cpp",
        "alsa/Mixer.cpp",
        "alsa/Mixer.cpp",
        "alsa/ModuleAlsa.cpp",
        "alsa/ModuleAlsa.cpp",
        "alsa/StreamAlsa.cpp",
        "alsa/StreamAlsa.cpp",
@@ -172,6 +179,7 @@ cc_test {
        "libbase",
        "libbase",
        "libbinder_ndk",
        "libbinder_ndk",
        "libcutils",
        "libcutils",
        "libfmq",
        "libmedia_helper",
        "libmedia_helper",
        "libstagefright_foundation",
        "libstagefright_foundation",
        "libutils",
        "libutils",
@@ -184,9 +192,11 @@ cc_test {
    ],
    ],
    generated_sources: [
    generated_sources: [
        "audio_policy_configuration_aidl_default",
        "audio_policy_configuration_aidl_default",
        "audio_policy_engine_configuration_aidl_default",
    ],
    ],
    generated_headers: [
    generated_headers: [
        "audio_policy_configuration_aidl_default",
        "audio_policy_configuration_aidl_default",
        "audio_policy_engine_configuration_aidl_default",
    ],
    ],
    srcs: [
    srcs: [
        "AudioPolicyConfigXmlConverter.cpp",
        "AudioPolicyConfigXmlConverter.cpp",
+35 −36
Original line number Original line Diff line number Diff line
@@ -30,6 +30,7 @@


#include "core-impl/AidlConversionXsdc.h"
#include "core-impl/AidlConversionXsdc.h"
#include "core-impl/AudioPolicyConfigXmlConverter.h"
#include "core-impl/AudioPolicyConfigXmlConverter.h"
#include "core-impl/XsdcConversion.h"


using aidl::android::media::audio::common::AudioFormatDescription;
using aidl::android::media::audio::common::AudioFormatDescription;
using aidl::android::media::audio::common::AudioHalEngineConfig;
using aidl::android::media::audio::common::AudioHalEngineConfig;
@@ -37,60 +38,39 @@ using aidl::android::media::audio::common::AudioHalVolumeCurve;
using aidl::android::media::audio::common::AudioHalVolumeGroup;
using aidl::android::media::audio::common::AudioHalVolumeGroup;
using aidl::android::media::audio::common::AudioStreamType;
using aidl::android::media::audio::common::AudioStreamType;


namespace xsd = android::audio::policy::configuration;
namespace ap_xsd = android::audio::policy::configuration;


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


static const int kDefaultVolumeIndexMin = 0;
static const int kDefaultVolumeIndexMin = 0;
static const int kDefaultVolumeIndexMax = 100;
static const int kDefaultVolumeIndexMax = 100;
static const int KVolumeIndexDeferredToAudioService = -1;
static const int KVolumeIndexDeferredToAudioService = -1;
/**
 * Valid curve points take the form "<index>,<attenuationMb>", where the index
 * must be in the range [0,100]. kInvalidCurvePointIndex is used to indicate
 * that a point was formatted incorrectly (e.g. if a vendor accidentally typed a
 * '.' instead of a ',' in their XML) -- using such a curve point will result in
 * failed VTS tests.
 */
static const int8_t kInvalidCurvePointIndex = -1;


AudioHalVolumeCurve::CurvePoint AudioPolicyConfigXmlConverter::convertCurvePointToAidl(
ConversionResult<AudioHalVolumeCurve> AudioPolicyConfigXmlConverter::convertVolumeCurveToAidl(
        const std::string& xsdcCurvePoint) {
        const ap_xsd::Volume& xsdcVolumeCurve) {
    AudioHalVolumeCurve::CurvePoint aidlCurvePoint{};
    if (sscanf(xsdcCurvePoint.c_str(), "%" SCNd8 ",%d", &aidlCurvePoint.index,
               &aidlCurvePoint.attenuationMb) != 2) {
        aidlCurvePoint.index = kInvalidCurvePointIndex;
    }
    return aidlCurvePoint;
}

AudioHalVolumeCurve AudioPolicyConfigXmlConverter::convertVolumeCurveToAidl(
        const xsd::Volume& xsdcVolumeCurve) {
    AudioHalVolumeCurve aidlVolumeCurve;
    AudioHalVolumeCurve aidlVolumeCurve;
    aidlVolumeCurve.deviceCategory =
    aidlVolumeCurve.deviceCategory =
            static_cast<AudioHalVolumeCurve::DeviceCategory>(xsdcVolumeCurve.getDeviceCategory());
            static_cast<AudioHalVolumeCurve::DeviceCategory>(xsdcVolumeCurve.getDeviceCategory());
    if (xsdcVolumeCurve.hasRef()) {
    if (xsdcVolumeCurve.hasRef()) {
        if (mVolumesReferenceMap.empty()) {
        if (mVolumesReferenceMap.empty()) {
            mVolumesReferenceMap = generateReferenceMap<xsd::Volumes, xsd::Reference>(
            mVolumesReferenceMap = generateReferenceMap<ap_xsd::Volumes, ap_xsd::Reference>(
                    getXsdcConfig()->getVolumes());
                    getXsdcConfig()->getVolumes());
        }
        }
        aidlVolumeCurve.curvePoints =
        aidlVolumeCurve.curvePoints = VALUE_OR_FATAL(
                convertCollectionToAidlUnchecked<std::string, AudioHalVolumeCurve::CurvePoint>(
                (convertCollectionToAidl<std::string, AudioHalVolumeCurve::CurvePoint>(
                        mVolumesReferenceMap.at(xsdcVolumeCurve.getRef()).getPoint(),
                        mVolumesReferenceMap.at(xsdcVolumeCurve.getRef()).getPoint(),
                        std::bind(&AudioPolicyConfigXmlConverter::convertCurvePointToAidl, this,
                        &convertCurvePointToAidl)));
                                  std::placeholders::_1));
    } else {
    } else {
        aidlVolumeCurve.curvePoints =
        aidlVolumeCurve.curvePoints = VALUE_OR_FATAL(
                convertCollectionToAidlUnchecked<std::string, AudioHalVolumeCurve::CurvePoint>(
                (convertCollectionToAidl<std::string, AudioHalVolumeCurve::CurvePoint>(
                        xsdcVolumeCurve.getPoint(),
                        xsdcVolumeCurve.getPoint(), &convertCurvePointToAidl)));
                        std::bind(&AudioPolicyConfigXmlConverter::convertCurvePointToAidl, this,
                                  std::placeholders::_1));
    }
    }
    return aidlVolumeCurve;
    return aidlVolumeCurve;
}
}


void AudioPolicyConfigXmlConverter::mapStreamToVolumeCurve(const xsd::Volume& xsdcVolumeCurve) {
void AudioPolicyConfigXmlConverter::mapStreamToVolumeCurve(const ap_xsd::Volume& xsdcVolumeCurve) {
    mStreamToVolumeCurvesMap[xsdcVolumeCurve.getStream()].push_back(
    mStreamToVolumeCurvesMap[xsdcVolumeCurve.getStream()].push_back(
            convertVolumeCurveToAidl(xsdcVolumeCurve));
            VALUE_OR_FATAL(convertVolumeCurveToAidl(xsdcVolumeCurve)));
}
}


const SurroundSoundConfig& AudioPolicyConfigXmlConverter::getSurroundSoundConfig() {
const SurroundSoundConfig& AudioPolicyConfigXmlConverter::getSurroundSoundConfig() {
@@ -109,6 +89,11 @@ const SurroundSoundConfig& AudioPolicyConfigXmlConverter::getSurroundSoundConfig
    return aidlSurroundSoundConfig;
    return aidlSurroundSoundConfig;
}
}


std::unique_ptr<AudioPolicyConfigXmlConverter::ModuleConfigs>
AudioPolicyConfigXmlConverter::releaseModuleConfigs() {
    return std::move(mModuleConfigurations);
}

const AudioHalEngineConfig& AudioPolicyConfigXmlConverter::getAidlEngineConfig() {
const AudioHalEngineConfig& AudioPolicyConfigXmlConverter::getAidlEngineConfig() {
    if (mAidlEngineConfig.volumeGroups.empty() && getXsdcConfig() &&
    if (mAidlEngineConfig.volumeGroups.empty() && getXsdcConfig() &&
        getXsdcConfig()->hasVolumes()) {
        getXsdcConfig()->hasVolumes()) {
@@ -160,8 +145,8 @@ const SurroundSoundConfig& AudioPolicyConfigXmlConverter::getDefaultSurroundSoun


void AudioPolicyConfigXmlConverter::mapStreamsToVolumeCurves() {
void AudioPolicyConfigXmlConverter::mapStreamsToVolumeCurves() {
    if (getXsdcConfig()->hasVolumes()) {
    if (getXsdcConfig()->hasVolumes()) {
        for (const xsd::Volumes& xsdcWrapperType : getXsdcConfig()->getVolumes()) {
        for (const ap_xsd::Volumes& xsdcWrapperType : getXsdcConfig()->getVolumes()) {
            for (const xsd::Volume& xsdcVolume : xsdcWrapperType.getVolume()) {
            for (const ap_xsd::Volume& xsdcVolume : xsdcWrapperType.getVolume()) {
                mapStreamToVolumeCurve(xsdcVolume);
                mapStreamToVolumeCurve(xsdcVolume);
            }
            }
        }
        }
@@ -171,7 +156,7 @@ void AudioPolicyConfigXmlConverter::mapStreamsToVolumeCurves() {
void AudioPolicyConfigXmlConverter::addVolumeGroupstoEngineConfig() {
void AudioPolicyConfigXmlConverter::addVolumeGroupstoEngineConfig() {
    for (const auto& [xsdcStream, volumeCurves] : mStreamToVolumeCurvesMap) {
    for (const auto& [xsdcStream, volumeCurves] : mStreamToVolumeCurvesMap) {
        AudioHalVolumeGroup volumeGroup;
        AudioHalVolumeGroup volumeGroup;
        volumeGroup.name = xsd::toString(xsdcStream);
        volumeGroup.name = ap_xsd::toString(xsdcStream);
        if (static_cast<int>(xsdcStream) >= AUDIO_STREAM_PUBLIC_CNT) {
        if (static_cast<int>(xsdcStream) >= AUDIO_STREAM_PUBLIC_CNT) {
            volumeGroup.minIndex = kDefaultVolumeIndexMin;
            volumeGroup.minIndex = kDefaultVolumeIndexMin;
            volumeGroup.maxIndex = kDefaultVolumeIndexMax;
            volumeGroup.maxIndex = kDefaultVolumeIndexMax;
@@ -190,4 +175,18 @@ void AudioPolicyConfigXmlConverter::parseVolumes() {
        addVolumeGroupstoEngineConfig();
        addVolumeGroupstoEngineConfig();
    }
    }
}
}

void AudioPolicyConfigXmlConverter::init() {
    if (!getXsdcConfig()->hasModules()) return;
    for (const ap_xsd::Modules& xsdcModulesType : getXsdcConfig()->getModules()) {
        if (!xsdcModulesType.has_module()) continue;
        for (const ap_xsd::Modules::Module& xsdcModule : xsdcModulesType.get_module()) {
            // 'primary' in the XML schema used by HIDL is equivalent to 'default' module.
            const std::string name =
                    xsdcModule.getName() != "primary" ? xsdcModule.getName() : "default";
            mModuleConfigurations->emplace_back(
                    name, VALUE_OR_FATAL(convertModuleConfigToAidl(xsdcModule)));
        }
    }
}
}  // namespace aidl::android::hardware::audio::core::internal
}  // namespace aidl::android::hardware::audio::core::internal
+16 −0
Original line number Original line Diff line number Diff line
@@ -43,6 +43,7 @@ using aidl::android::media::audio::common::AudioProfile;
using aidl::android::media::audio::common::Int;
using aidl::android::media::audio::common::Int;
using aidl::android::media::audio::common::MicrophoneInfo;
using aidl::android::media::audio::common::MicrophoneInfo;
using aidl::android::media::audio::common::PcmType;
using aidl::android::media::audio::common::PcmType;
using Configuration = aidl::android::hardware::audio::core::Module::Configuration;


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


@@ -677,4 +678,19 @@ std::unique_ptr<Configuration> getBluetoothConfiguration() {
    return std::make_unique<Configuration>(configuration);
    return std::make_unique<Configuration>(configuration);
}
}


std::unique_ptr<Module::Configuration> getConfiguration(Module::Type moduleType) {
    switch (moduleType) {
        case Module::Type::DEFAULT:
            return getPrimaryConfiguration();
        case Module::Type::R_SUBMIX:
            return getRSubmixConfiguration();
        case Module::Type::STUB:
            return getStubConfiguration();
        case Module::Type::USB:
            return getUsbConfiguration();
        case Module::Type::BLUETOOTH:
            return getBluetoothConfiguration();
    }
}

}  // namespace aidl::android::hardware::audio::core::internal
}  // namespace aidl::android::hardware::audio::core::internal
+74 −114

File changed.

Preview size limit exceeded, changes collapsed.

+26 −28
Original line number Original line Diff line number Diff line
@@ -25,6 +25,7 @@
#include <android/binder_ibinder_platform.h>
#include <android/binder_ibinder_platform.h>
#include <error/expected_utils.h>
#include <error/expected_utils.h>


#include "core-impl/Configuration.h"
#include "core-impl/Module.h"
#include "core-impl/Module.h"
#include "core-impl/ModuleBluetooth.h"
#include "core-impl/ModuleBluetooth.h"
#include "core-impl/ModulePrimary.h"
#include "core-impl/ModulePrimary.h"
@@ -132,21 +133,36 @@ bool findAudioProfile(const AudioPort& port, const AudioFormatDescription& forma
}  // namespace
}  // namespace


// static
// static
std::shared_ptr<Module> Module::createInstance(Type type) {
std::shared_ptr<Module> Module::createInstance(Type type, std::unique_ptr<Configuration>&& config) {
    switch (type) {
    switch (type) {
        case Type::DEFAULT:
        case Type::DEFAULT:
            return ndk::SharedRefBase::make<ModulePrimary>();
            return ndk::SharedRefBase::make<ModulePrimary>(std::move(config));
        case Type::R_SUBMIX:
        case Type::R_SUBMIX:
            return ndk::SharedRefBase::make<ModuleRemoteSubmix>();
            return ndk::SharedRefBase::make<ModuleRemoteSubmix>(std::move(config));
        case Type::STUB:
        case Type::STUB:
            return ndk::SharedRefBase::make<ModuleStub>();
            return ndk::SharedRefBase::make<ModuleStub>(std::move(config));
        case Type::USB:
        case Type::USB:
            return ndk::SharedRefBase::make<ModuleUsb>();
            return ndk::SharedRefBase::make<ModuleUsb>(std::move(config));
        case Type::BLUETOOTH:
        case Type::BLUETOOTH:
            return ndk::SharedRefBase::make<ModuleBluetooth>();
            return ndk::SharedRefBase::make<ModuleBluetooth>(std::move(config));
    }
    }
}
}


// static
std::optional<Module::Type> Module::typeFromString(const std::string& type) {
    if (type == "default")
        return Module::Type::DEFAULT;
    else if (type == "r_submix")
        return Module::Type::R_SUBMIX;
    else if (type == "stub")
        return Module::Type::STUB;
    else if (type == "usb")
        return Module::Type::USB;
    else if (type == "bluetooth")
        return Module::Type::BLUETOOTH;
    return {};
}

std::ostream& operator<<(std::ostream& os, Module::Type t) {
std::ostream& operator<<(std::ostream& os, Module::Type t) {
    switch (t) {
    switch (t) {
        case Module::Type::DEFAULT:
        case Module::Type::DEFAULT:
@@ -316,26 +332,8 @@ std::set<int32_t> Module::portIdsFromPortConfigIds(C portConfigIds) {
    return result;
    return result;
}
}


std::unique_ptr<internal::Configuration> Module::initializeConfig() {
std::unique_ptr<Module::Configuration> Module::initializeConfig() {
    std::unique_ptr<internal::Configuration> config;
    return internal::getConfiguration(getType());
    switch (getType()) {
        case Type::DEFAULT:
            config = std::move(internal::getPrimaryConfiguration());
            break;
        case Type::R_SUBMIX:
            config = std::move(internal::getRSubmixConfiguration());
            break;
        case Type::STUB:
            config = std::move(internal::getStubConfiguration());
            break;
        case Type::USB:
            config = std::move(internal::getUsbConfiguration());
            break;
        case Type::BLUETOOTH:
            config = std::move(internal::getBluetoothConfiguration());
            break;
    }
    return config;
}
}


std::vector<AudioRoute*> Module::getAudioRoutesForAudioPortImpl(int32_t portId) {
std::vector<AudioRoute*> Module::getAudioRoutesForAudioPortImpl(int32_t portId) {
@@ -350,7 +348,7 @@ std::vector<AudioRoute*> Module::getAudioRoutesForAudioPortImpl(int32_t portId)
    return result;
    return result;
}
}


internal::Configuration& Module::getConfig() {
Module::Configuration& Module::getConfig() {
    if (!mConfig) {
    if (!mConfig) {
        mConfig = std::move(initializeConfig());
        mConfig = std::move(initializeConfig());
    }
    }
@@ -797,7 +795,7 @@ ndk::ScopedAStatus Module::openInputStream(const OpenInputStreamArguments& in_ar
    context.fillDescriptor(&_aidl_return->desc);
    context.fillDescriptor(&_aidl_return->desc);
    std::shared_ptr<StreamIn> stream;
    std::shared_ptr<StreamIn> stream;
    RETURN_STATUS_IF_ERROR(createInputStream(std::move(context), in_args.sinkMetadata,
    RETURN_STATUS_IF_ERROR(createInputStream(std::move(context), in_args.sinkMetadata,
                                             mConfig->microphones, &stream));
                                             getConfig().microphones, &stream));
    StreamWrapper streamWrapper(stream);
    StreamWrapper streamWrapper(stream);
    if (auto patchIt = mPatches.find(in_args.portConfigId); patchIt != mPatches.end()) {
    if (auto patchIt = mPatches.find(in_args.portConfigId); patchIt != mPatches.end()) {
        RETURN_STATUS_IF_ERROR(
        RETURN_STATUS_IF_ERROR(
Loading