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 Diff line number Diff line
@@ -12,6 +12,7 @@ cc_defaults {
    vendor: true,
    shared_libs: [
        "libalsautilsv2",
        "libaudio_aidl_conversion_common_ndk",
        "libaudioaidlcommon",
        "libaudioutils",
        "libbase",
@@ -19,6 +20,8 @@ cc_defaults {
        "libcutils",
        "libfmq",
        "libnbaio_mono",
        "liblog",
        "libmedia_helper",
        "libstagefright_foundation",
        "libtinyalsav2",
        "libutils",
@@ -31,6 +34,9 @@ cc_defaults {
        "libaudioaidl_headers",
        "libxsdc-utils",
    ],
    cflags: [
        "-DBACKEND_NDK",
    ],
}

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

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

using aidl::android::media::audio::common::AudioFormatDescription;
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::AudioStreamType;

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

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

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

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

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

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

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

void AudioPolicyConfigXmlConverter::mapStreamsToVolumeCurves() {
    if (getXsdcConfig()->hasVolumes()) {
        for (const xsd::Volumes& xsdcWrapperType : getXsdcConfig()->getVolumes()) {
            for (const xsd::Volume& xsdcVolume : xsdcWrapperType.getVolume()) {
        for (const ap_xsd::Volumes& xsdcWrapperType : getXsdcConfig()->getVolumes()) {
            for (const ap_xsd::Volume& xsdcVolume : xsdcWrapperType.getVolume()) {
                mapStreamToVolumeCurve(xsdcVolume);
            }
        }
@@ -171,7 +156,7 @@ void AudioPolicyConfigXmlConverter::mapStreamsToVolumeCurves() {
void AudioPolicyConfigXmlConverter::addVolumeGroupstoEngineConfig() {
    for (const auto& [xsdcStream, volumeCurves] : mStreamToVolumeCurvesMap) {
        AudioHalVolumeGroup volumeGroup;
        volumeGroup.name = xsd::toString(xsdcStream);
        volumeGroup.name = ap_xsd::toString(xsdcStream);
        if (static_cast<int>(xsdcStream) >= AUDIO_STREAM_PUBLIC_CNT) {
            volumeGroup.minIndex = kDefaultVolumeIndexMin;
            volumeGroup.maxIndex = kDefaultVolumeIndexMax;
@@ -190,4 +175,18 @@ void AudioPolicyConfigXmlConverter::parseVolumes() {
        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
+16 −0
Original line number 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::MicrophoneInfo;
using aidl::android::media::audio::common::PcmType;
using Configuration = aidl::android::hardware::audio::core::Module::Configuration;

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

@@ -677,4 +678,19 @@ std::unique_ptr<Configuration> getBluetoothConfiguration() {
    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
+74 −114

File changed.

Preview size limit exceeded, changes collapsed.

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

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

// static
std::shared_ptr<Module> Module::createInstance(Type type) {
std::shared_ptr<Module> Module::createInstance(Type type, std::unique_ptr<Configuration>&& config) {
    switch (type) {
        case Type::DEFAULT:
            return ndk::SharedRefBase::make<ModulePrimary>();
            return ndk::SharedRefBase::make<ModulePrimary>(std::move(config));
        case Type::R_SUBMIX:
            return ndk::SharedRefBase::make<ModuleRemoteSubmix>();
            return ndk::SharedRefBase::make<ModuleRemoteSubmix>(std::move(config));
        case Type::STUB:
            return ndk::SharedRefBase::make<ModuleStub>();
            return ndk::SharedRefBase::make<ModuleStub>(std::move(config));
        case Type::USB:
            return ndk::SharedRefBase::make<ModuleUsb>();
            return ndk::SharedRefBase::make<ModuleUsb>(std::move(config));
        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) {
    switch (t) {
        case Module::Type::DEFAULT:
@@ -316,26 +332,8 @@ std::set<int32_t> Module::portIdsFromPortConfigIds(C portConfigIds) {
    return result;
}

std::unique_ptr<internal::Configuration> Module::initializeConfig() {
    std::unique_ptr<internal::Configuration> config;
    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::unique_ptr<Module::Configuration> Module::initializeConfig() {
    return internal::getConfiguration(getType());
}

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

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