From 00a7307862f709651f3df7a763dbe2d421d200e8 Mon Sep 17 00:00:00 2001 From: Lorena Torres-Huerta Date: Tue, 20 Dec 2022 02:21:41 +0000 Subject: [PATCH] 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 --- audio/aidl/default/Android.bp | 10 + .../default/AudioPolicyConfigXmlConverter.cpp | 71 ++- audio/aidl/default/Configuration.cpp | 16 + .../aidl/default/EngineConfigXmlConverter.cpp | 188 +++----- audio/aidl/default/Module.cpp | 54 +-- audio/aidl/default/Telephony.cpp | 2 +- audio/aidl/default/XsdcConversion.cpp | 444 ++++++++++++++++++ .../android.hardware.audio.service-aidl.xml | 22 +- .../config/audioPolicy/api/current.txt | 48 -- .../audio_policy_configuration.xsd | 74 --- .../core-impl/AudioPolicyConfigXmlConverter.h | 24 +- .../include/core-impl/ChildInterface.h | 6 +- audio/aidl/default/include/core-impl/Config.h | 9 +- .../default/include/core-impl/Configuration.h | 29 +- .../core-impl/EngineConfigXmlConverter.h | 34 +- audio/aidl/default/include/core-impl/Module.h | 42 +- .../default/include/core-impl/ModuleAlsa.h | 3 +- .../include/core-impl/ModuleBluetooth.h | 3 +- .../default/include/core-impl/ModulePrimary.h | 3 +- .../include/core-impl/ModuleRemoteSubmix.h | 3 +- .../default/include/core-impl/ModuleStub.h | 2 +- .../default/include/core-impl/ModuleUsb.h | 2 +- .../default/include/core-impl/XmlConverter.h | 21 +- .../include/core-impl/XsdcConversion.h | 29 ++ audio/aidl/default/main.cpp | 68 ++- 25 files changed, 795 insertions(+), 412 deletions(-) create mode 100644 audio/aidl/default/XsdcConversion.cpp create mode 100644 audio/aidl/default/include/core-impl/XsdcConversion.h diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp index bb8d76f8fc..9aa86b58c3 100644 --- a/audio/aidl/default/Android.bp +++ b/audio/aidl/default/Android.bp @@ -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", diff --git a/audio/aidl/default/AudioPolicyConfigXmlConverter.cpp b/audio/aidl/default/AudioPolicyConfigXmlConverter.cpp index 7452c8ec7a..5d06cb607c 100644 --- a/audio/aidl/default/AudioPolicyConfigXmlConverter.cpp +++ b/audio/aidl/default/AudioPolicyConfigXmlConverter.cpp @@ -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 ",", 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 AudioPolicyConfigXmlConverter::convertVolumeCurveToAidl( + const ap_xsd::Volume& xsdcVolumeCurve) { AudioHalVolumeCurve aidlVolumeCurve; aidlVolumeCurve.deviceCategory = static_cast(xsdcVolumeCurve.getDeviceCategory()); if (xsdcVolumeCurve.hasRef()) { if (mVolumesReferenceMap.empty()) { - mVolumesReferenceMap = generateReferenceMap( + mVolumesReferenceMap = generateReferenceMap( getXsdcConfig()->getVolumes()); } - aidlVolumeCurve.curvePoints = - convertCollectionToAidlUnchecked( + aidlVolumeCurve.curvePoints = VALUE_OR_FATAL( + (convertCollectionToAidl( mVolumesReferenceMap.at(xsdcVolumeCurve.getRef()).getPoint(), - std::bind(&AudioPolicyConfigXmlConverter::convertCurvePointToAidl, this, - std::placeholders::_1)); + &convertCurvePointToAidl))); } else { - aidlVolumeCurve.curvePoints = - convertCollectionToAidlUnchecked( - xsdcVolumeCurve.getPoint(), - std::bind(&AudioPolicyConfigXmlConverter::convertCurvePointToAidl, this, - std::placeholders::_1)); + aidlVolumeCurve.curvePoints = VALUE_OR_FATAL( + (convertCollectionToAidl( + 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::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(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 diff --git a/audio/aidl/default/Configuration.cpp b/audio/aidl/default/Configuration.cpp index 3c3dadb112..a20bb54ea8 100644 --- a/audio/aidl/default/Configuration.cpp +++ b/audio/aidl/default/Configuration.cpp @@ -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 getBluetoothConfiguration() { return std::make_unique(configuration); } +std::unique_ptr 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 diff --git a/audio/aidl/default/EngineConfigXmlConverter.cpp b/audio/aidl/default/EngineConfigXmlConverter.cpp index 96b555c640..631cdce1a0 100644 --- a/audio/aidl/default/EngineConfigXmlConverter.cpp +++ b/audio/aidl/default/EngineConfigXmlConverter.cpp @@ -20,11 +20,14 @@ #include #include +#define LOG_TAG "AHAL_Config" #include #include #include +#include #include "core-impl/EngineConfigXmlConverter.h" +#include "core-impl/XsdcConversion.h" using aidl::android::media::audio::common::AudioAttributes; using aidl::android::media::audio::common::AudioContentType; @@ -40,20 +43,13 @@ using aidl::android::media::audio::common::AudioProductStrategyType; 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; -namespace xsd = android::audio::policy::engine::configuration; +namespace eng_xsd = android::audio::policy::engine::configuration; namespace aidl::android::hardware::audio::core::internal { -/** - * Valid curve points take the form ",", 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; - void EngineConfigXmlConverter::initProductStrategyMap() { #define STRATEGY_ENTRY(name) {"STRATEGY_" #name, static_cast(AudioProductStrategyType::name)} @@ -68,7 +64,7 @@ void EngineConfigXmlConverter::initProductStrategyMap() { #undef STRATEGY_ENTRY } -int EngineConfigXmlConverter::convertProductStrategyNameToAidl( +ConversionResult EngineConfigXmlConverter::convertProductStrategyNameToAidl( const std::string& xsdcProductStrategyName) { const auto [it, success] = mProductStrategyMap.insert( std::make_pair(xsdcProductStrategyName, mNextVendorStrategy)); @@ -85,12 +81,12 @@ bool isDefaultAudioAttributes(const AudioAttributes& attributes) { (attributes.tags.empty())); } -AudioAttributes EngineConfigXmlConverter::convertAudioAttributesToAidl( - const xsd::AttributesType& xsdcAudioAttributes) { +ConversionResult EngineConfigXmlConverter::convertAudioAttributesToAidl( + const eng_xsd::AttributesType& xsdcAudioAttributes) { if (xsdcAudioAttributes.hasAttributesRef()) { if (mAttributesReferenceMap.empty()) { mAttributesReferenceMap = - generateReferenceMap( + generateReferenceMap( getXsdcConfig()->getAttributesRef()); } return convertAudioAttributesToAidl( @@ -111,16 +107,16 @@ AudioAttributes EngineConfigXmlConverter::convertAudioAttributesToAidl( static_cast(xsdcAudioAttributes.getFirstSource()->getValue()); } if (xsdcAudioAttributes.hasFlags()) { - std::vector xsdcFlagTypeVec = + std::vector xsdcFlagTypeVec = xsdcAudioAttributes.getFirstFlags()->getValue(); - for (const xsd::FlagType& xsdcFlagType : xsdcFlagTypeVec) { - if (xsdcFlagType != xsd::FlagType::AUDIO_FLAG_NONE) { + for (const eng_xsd::FlagType& xsdcFlagType : xsdcFlagTypeVec) { + if (xsdcFlagType != eng_xsd::FlagType::AUDIO_FLAG_NONE) { aidlAudioAttributes.flags |= 1 << (static_cast(xsdcFlagType) - 1); } } } if (xsdcAudioAttributes.hasBundle()) { - const xsd::BundleType* xsdcBundle = xsdcAudioAttributes.getFirstBundle(); + const eng_xsd::BundleType* xsdcBundle = xsdcAudioAttributes.getFirstBundle(); aidlAudioAttributes.tags[0] = xsdcBundle->getKey() + "=" + xsdcBundle->getValue(); } if (isDefaultAudioAttributes(aidlAudioAttributes)) { @@ -129,53 +125,54 @@ AudioAttributes EngineConfigXmlConverter::convertAudioAttributesToAidl( return aidlAudioAttributes; } -AudioHalAttributesGroup EngineConfigXmlConverter::convertAttributesGroupToAidl( - const xsd::AttributesGroup& xsdcAttributesGroup) { +ConversionResult EngineConfigXmlConverter::convertAttributesGroupToAidl( + const eng_xsd::AttributesGroup& xsdcAttributesGroup) { AudioHalAttributesGroup aidlAttributesGroup; static const int kStreamTypeEnumOffset = - static_cast(xsd::Stream::AUDIO_STREAM_VOICE_CALL) - + static_cast(eng_xsd::Stream::AUDIO_STREAM_VOICE_CALL) - static_cast(AudioStreamType::VOICE_CALL); aidlAttributesGroup.streamType = static_cast( static_cast(xsdcAttributesGroup.getStreamType()) - kStreamTypeEnumOffset); aidlAttributesGroup.volumeGroupName = xsdcAttributesGroup.getVolumeGroup(); if (xsdcAttributesGroup.hasAttributes_optional()) { aidlAttributesGroup.attributes = - convertCollectionToAidlUnchecked( + VALUE_OR_FATAL((convertCollectionToAidl( xsdcAttributesGroup.getAttributes_optional(), std::bind(&EngineConfigXmlConverter::convertAudioAttributesToAidl, this, - std::placeholders::_1)); + std::placeholders::_1)))); } else if (xsdcAttributesGroup.hasContentType_optional() || xsdcAttributesGroup.hasUsage_optional() || xsdcAttributesGroup.hasSource_optional() || xsdcAttributesGroup.hasFlags_optional() || xsdcAttributesGroup.hasBundle_optional()) { - aidlAttributesGroup.attributes.push_back(convertAudioAttributesToAidl(xsd::AttributesType( - xsdcAttributesGroup.getContentType_optional(), - xsdcAttributesGroup.getUsage_optional(), xsdcAttributesGroup.getSource_optional(), - xsdcAttributesGroup.getFlags_optional(), xsdcAttributesGroup.getBundle_optional(), - std::nullopt))); + aidlAttributesGroup.attributes.push_back(VALUE_OR_FATAL(convertAudioAttributesToAidl( + eng_xsd::AttributesType(xsdcAttributesGroup.getContentType_optional(), + xsdcAttributesGroup.getUsage_optional(), + xsdcAttributesGroup.getSource_optional(), + xsdcAttributesGroup.getFlags_optional(), + xsdcAttributesGroup.getBundle_optional(), std::nullopt)))); } else { - // do nothing; - // TODO: check if this is valid or if we should treat as an error. - // Currently, attributes are not mandatory in schema, but an AttributesGroup - // without attributes does not make much sense. + LOG(ERROR) << __func__ << " Review Audio Policy config: no audio attributes provided for " + << aidlAttributesGroup.toString(); + return unexpected(BAD_VALUE); } return aidlAttributesGroup; } -AudioHalProductStrategy EngineConfigXmlConverter::convertProductStrategyToAidl( - const xsd::ProductStrategies::ProductStrategy& xsdcProductStrategy) { +ConversionResult EngineConfigXmlConverter::convertProductStrategyToAidl( + const eng_xsd::ProductStrategies::ProductStrategy& xsdcProductStrategy) { AudioHalProductStrategy aidlProductStrategy; - aidlProductStrategy.id = convertProductStrategyNameToAidl(xsdcProductStrategy.getName()); + aidlProductStrategy.id = + VALUE_OR_FATAL(convertProductStrategyNameToAidl(xsdcProductStrategy.getName())); if (xsdcProductStrategy.hasAttributesGroup()) { - aidlProductStrategy.attributesGroups = - convertCollectionToAidlUnchecked( + aidlProductStrategy.attributesGroups = VALUE_OR_FATAL( + (convertCollectionToAidl( xsdcProductStrategy.getAttributesGroup(), std::bind(&EngineConfigXmlConverter::convertAttributesGroupToAidl, this, - std::placeholders::_1)); + std::placeholders::_1)))); } if ((mDefaultProductStrategyId != std::nullopt) && (mDefaultProductStrategyId.value() == -1)) { mDefaultProductStrategyId = aidlProductStrategy.id; @@ -183,82 +180,42 @@ AudioHalProductStrategy EngineConfigXmlConverter::convertProductStrategyToAidl( return aidlProductStrategy; } -AudioHalVolumeCurve::CurvePoint EngineConfigXmlConverter::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 EngineConfigXmlConverter::convertVolumeCurveToAidl( - const xsd::Volume& xsdcVolumeCurve) { +ConversionResult EngineConfigXmlConverter::convertVolumeCurveToAidl( + const eng_xsd::Volume& xsdcVolumeCurve) { AudioHalVolumeCurve aidlVolumeCurve; aidlVolumeCurve.deviceCategory = static_cast(xsdcVolumeCurve.getDeviceCategory()); if (xsdcVolumeCurve.hasRef()) { if (mVolumesReferenceMap.empty()) { - mVolumesReferenceMap = generateReferenceMap( + mVolumesReferenceMap = generateReferenceMap( getXsdcConfig()->getVolumes()); } - aidlVolumeCurve.curvePoints = - convertCollectionToAidlUnchecked( + aidlVolumeCurve.curvePoints = VALUE_OR_FATAL( + (convertCollectionToAidl( mVolumesReferenceMap.at(xsdcVolumeCurve.getRef()).getPoint(), - std::bind(&EngineConfigXmlConverter::convertCurvePointToAidl, this, - std::placeholders::_1)); + &convertCurvePointToAidl))); } else { - aidlVolumeCurve.curvePoints = - convertCollectionToAidlUnchecked( - xsdcVolumeCurve.getPoint(), - std::bind(&EngineConfigXmlConverter::convertCurvePointToAidl, this, - std::placeholders::_1)); + aidlVolumeCurve.curvePoints = VALUE_OR_FATAL( + (convertCollectionToAidl( + xsdcVolumeCurve.getPoint(), &convertCurvePointToAidl))); } return aidlVolumeCurve; } -AudioHalVolumeGroup EngineConfigXmlConverter::convertVolumeGroupToAidl( - const xsd::VolumeGroupsType::VolumeGroup& xsdcVolumeGroup) { +ConversionResult EngineConfigXmlConverter::convertVolumeGroupToAidl( + const eng_xsd::VolumeGroupsType::VolumeGroup& xsdcVolumeGroup) { AudioHalVolumeGroup aidlVolumeGroup; aidlVolumeGroup.name = xsdcVolumeGroup.getName(); aidlVolumeGroup.minIndex = xsdcVolumeGroup.getIndexMin(); aidlVolumeGroup.maxIndex = xsdcVolumeGroup.getIndexMax(); aidlVolumeGroup.volumeCurves = - convertCollectionToAidlUnchecked( + VALUE_OR_FATAL((convertCollectionToAidl( xsdcVolumeGroup.getVolume(), std::bind(&EngineConfigXmlConverter::convertVolumeCurveToAidl, this, - std::placeholders::_1)); + std::placeholders::_1)))); return aidlVolumeGroup; } -AudioHalCapCriterion EngineConfigXmlConverter::convertCapCriterionToAidl( - const xsd::CriterionType& xsdcCriterion) { - AudioHalCapCriterion aidlCapCriterion; - aidlCapCriterion.name = xsdcCriterion.getName(); - aidlCapCriterion.criterionTypeName = xsdcCriterion.getType(); - aidlCapCriterion.defaultLiteralValue = xsdcCriterion.get_default(); - return aidlCapCriterion; -} - -std::string EngineConfigXmlConverter::convertCriterionTypeValueToAidl( - const xsd::ValueType& xsdcCriterionTypeValue) { - return xsdcCriterionTypeValue.getLiteral(); -} - -AudioHalCapCriterionType EngineConfigXmlConverter::convertCapCriterionTypeToAidl( - const xsd::CriterionTypeType& xsdcCriterionType) { - AudioHalCapCriterionType aidlCapCriterionType; - aidlCapCriterionType.name = xsdcCriterionType.getName(); - aidlCapCriterionType.isInclusive = !(static_cast(xsdcCriterionType.getType())); - aidlCapCriterionType.values = - convertWrappedCollectionToAidlUnchecked( - xsdcCriterionType.getValues(), &xsd::ValuesType::getValue, - std::bind(&EngineConfigXmlConverter::convertCriterionTypeValueToAidl, this, - std::placeholders::_1)); - return aidlCapCriterionType; -} - AudioHalEngineConfig& EngineConfigXmlConverter::getAidlEngineConfig() { return mAidlEngineConfig; } @@ -266,39 +223,42 @@ AudioHalEngineConfig& EngineConfigXmlConverter::getAidlEngineConfig() { void EngineConfigXmlConverter::init() { initProductStrategyMap(); if (getXsdcConfig()->hasProductStrategies()) { - mAidlEngineConfig.productStrategies = - convertWrappedCollectionToAidlUnchecked( + mAidlEngineConfig.productStrategies = VALUE_OR_FATAL( + (convertWrappedCollectionToAidl( getXsdcConfig()->getProductStrategies(), - &xsd::ProductStrategies::getProductStrategy, + &eng_xsd::ProductStrategies::getProductStrategy, std::bind(&EngineConfigXmlConverter::convertProductStrategyToAidl, this, - std::placeholders::_1)); + std::placeholders::_1)))); if (mDefaultProductStrategyId) { mAidlEngineConfig.defaultProductStrategyId = mDefaultProductStrategyId.value(); } } if (getXsdcConfig()->hasVolumeGroups()) { - mAidlEngineConfig.volumeGroups = convertWrappedCollectionToAidlUnchecked< - xsd::VolumeGroupsType, xsd::VolumeGroupsType::VolumeGroup, AudioHalVolumeGroup>( - getXsdcConfig()->getVolumeGroups(), &xsd::VolumeGroupsType::getVolumeGroup, - std::bind(&EngineConfigXmlConverter::convertVolumeGroupToAidl, this, - std::placeholders::_1)); + mAidlEngineConfig.volumeGroups = VALUE_OR_FATAL( + (convertWrappedCollectionToAidl( + getXsdcConfig()->getVolumeGroups(), + &eng_xsd::VolumeGroupsType::getVolumeGroup, + std::bind(&EngineConfigXmlConverter::convertVolumeGroupToAidl, this, + std::placeholders::_1)))); } if (getXsdcConfig()->hasCriteria() && getXsdcConfig()->hasCriterion_types()) { AudioHalEngineConfig::CapSpecificConfig capSpecificConfig; - capSpecificConfig.criteria = - convertWrappedCollectionToAidlUnchecked( - getXsdcConfig()->getCriteria(), &xsd::CriteriaType::getCriterion, - std::bind(&EngineConfigXmlConverter::convertCapCriterionToAidl, this, - std::placeholders::_1)); - capSpecificConfig.criterionTypes = convertWrappedCollectionToAidlUnchecked< - xsd::CriterionTypesType, xsd::CriterionTypeType, AudioHalCapCriterionType>( - getXsdcConfig()->getCriterion_types(), &xsd::CriterionTypesType::getCriterion_type, - std::bind(&EngineConfigXmlConverter::convertCapCriterionTypeToAidl, this, - std::placeholders::_1)); - mAidlEngineConfig.capSpecificConfig = capSpecificConfig; + capSpecificConfig.criteria = VALUE_OR_FATAL( + (convertWrappedCollectionToAidl( + getXsdcConfig()->getCriteria(), &eng_xsd::CriteriaType::getCriterion, + &convertCapCriterionToAidl))); + capSpecificConfig.criterionTypes = + VALUE_OR_FATAL((convertWrappedCollectionToAidl( + getXsdcConfig()->getCriterion_types(), + &eng_xsd::CriterionTypesType::getCriterion_type, + &convertCapCriterionTypeToAidl))); } } } // namespace aidl::android::hardware::audio::core::internal diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp index d721b32d83..0cda3bd8f5 100644 --- a/audio/aidl/default/Module.cpp +++ b/audio/aidl/default/Module.cpp @@ -25,6 +25,7 @@ #include #include +#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::createInstance(Type type) { +std::shared_ptr Module::createInstance(Type type, std::unique_ptr&& config) { switch (type) { case Type::DEFAULT: - return ndk::SharedRefBase::make(); + return ndk::SharedRefBase::make(std::move(config)); case Type::R_SUBMIX: - return ndk::SharedRefBase::make(); + return ndk::SharedRefBase::make(std::move(config)); case Type::STUB: - return ndk::SharedRefBase::make(); + return ndk::SharedRefBase::make(std::move(config)); case Type::USB: - return ndk::SharedRefBase::make(); + return ndk::SharedRefBase::make(std::move(config)); case Type::BLUETOOTH: - return ndk::SharedRefBase::make(); + return ndk::SharedRefBase::make(std::move(config)); } } +// static +std::optional 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 Module::portIdsFromPortConfigIds(C portConfigIds) { return result; } -std::unique_ptr Module::initializeConfig() { - std::unique_ptr 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::initializeConfig() { + return internal::getConfiguration(getType()); } std::vector Module::getAudioRoutesForAudioPortImpl(int32_t portId) { @@ -350,7 +348,7 @@ std::vector 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 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( diff --git a/audio/aidl/default/Telephony.cpp b/audio/aidl/default/Telephony.cpp index bf05a8da98..d9da39f0a8 100644 --- a/audio/aidl/default/Telephony.cpp +++ b/audio/aidl/default/Telephony.cpp @@ -16,9 +16,9 @@ #define LOG_TAG "AHAL_Telephony" #include +#include #include -#include #include "core-impl/Telephony.h" diff --git a/audio/aidl/default/XsdcConversion.cpp b/audio/aidl/default/XsdcConversion.cpp new file mode 100644 index 0000000000..2feb0c3b8c --- /dev/null +++ b/audio/aidl/default/XsdcConversion.cpp @@ -0,0 +1,444 @@ +#include + +#include + +#define LOG_TAG "AHAL_Config" +#include +#include + +#include +#include +#include +#include + +#include "core-impl/XmlConverter.h" +#include "core-impl/XsdcConversion.h" + +using aidl::android::media::audio::common::AudioChannelLayout; +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::AudioHalVolumeCurve; +using aidl::android::media::audio::common::AudioIoFlags; +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 ::android::BAD_VALUE; +using ::android::base::unexpected; + +namespace ap_xsd = android::audio::policy::configuration; +namespace eng_xsd = android::audio::policy::engine::configuration; + +namespace aidl::android::hardware::audio::core::internal { + +inline ConversionResult 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 convertAudioFormatToAidl(const std::string& xsdcFormat) { + audio_format_t legacyFormat = ::android::formatFromString(xsdcFormat, AUDIO_FORMAT_DEFAULT); + ConversionResult 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 getAttachedDevices(const ap_xsd::Modules::Module& moduleConfig) { + std::unordered_set 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 convertDeviceTypeToAidl(const std::string& xType) { + audio_devices_t legacyDeviceType = AUDIO_DEVICE_NONE; + ::android::DeviceConverter::fromString(xType, legacyDeviceType); + ConversionResult 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 createAudioDevice( + const ap_xsd::DevicePorts::DevicePort& xDevicePort) { + AudioDevice device = { + .type = VALUE_OR_FATAL(convertDeviceTypeToAidl(xDevicePort.getType())), + .address = xDevicePort.hasAddress() + ? AudioDeviceAddress::make( + 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 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( + xDevicePort.getEncodedFormats(), + &convertAudioFormatToAidl))) + : std::vector{}, + }; + return AudioPortExt::make(deviceExt); +} + +ConversionResult createAudioPortExt(const ap_xsd::MixPorts::MixPort& xMixPort) { + AudioPortMixExt mixExt = { + .maxOpenStreamCount = + xMixPort.hasMaxOpenCount() ? static_cast(xMixPort.getMaxOpenCount()) : 0, + .maxActiveStreamCount = xMixPort.hasMaxActiveCount() + ? static_cast(xMixPort.getMaxActiveCount()) + : 1, + .recommendedMuteDurationMs = + xMixPort.hasRecommendedMuteDurationMs() + ? static_cast(xMixPort.getRecommendedMuteDurationMs()) + : 0}; + return AudioPortExt::make(mixExt); +} + +ConversionResult convertGainModeToAidl(const std::vector& gainModeVec) { + static const char gainModeSeparator = ' '; + int gainModeMask = 0; + for (const ap_xsd::AudioGainMode& gainMode : gainModeVec) { + gainModeMask |= static_cast(::android::GainModeConverter::maskFromString( + ap_xsd::toString(gainMode), &gainModeSeparator)); + } + return gainModeMask; +} + +ConversionResult convertChannelMaskToAidl( + const ap_xsd::AudioChannelMask& xChannelMask) { + std::string xChannelMaskLiteral = ap_xsd::toString(xChannelMask); + audio_channel_mask_t legacyChannelMask = ::android::channelMaskFromString(xChannelMaskLiteral); + ConversionResult 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 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 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( + xProfile.getChannelMasks(), &convertChannelMaskToAidl))) + : std::vector{}, + .sampleRates = xProfile.hasSamplingRates() + ? VALUE_OR_FATAL((convertCollectionToAidl( + xProfile.getSamplingRates(), + [](const int64_t x) -> int { return x; }))) + : std::vector{}}; +} + +ConversionResult convertIoFlagsToAidl( + const std::vector& flags, const ap_xsd::Role role, + bool flagsForMixPort) { + static const char flagSeparator = ' '; + int flagMask = 0; + if ((role == ap_xsd::Role::sink && flagsForMixPort) || + (role == ap_xsd::Role::source && !flagsForMixPort)) { + for (const ap_xsd::AudioInOutFlag& flag : flags) { + flagMask |= static_cast(::android::InputFlagConverter::maskFromString( + ap_xsd::toString(flag), &flagSeparator)); + } + return AudioIoFlags::make(flagMask); + } else { + for (const ap_xsd::AudioInOutFlag& flag : flags) { + flagMask |= static_cast(::android::OutputFlagConverter::maskFromString( + ap_xsd::toString(flag), &flagSeparator)); + } + } + return AudioIoFlags::make(flagMask); +} + +ConversionResult 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( + xDevicePort.getProfile(), convertAudioProfileToAidl))), + .flags = VALUE_OR_FATAL(convertIoFlagsToAidl({}, xDevicePort.getRole(), false)), + .gains = VALUE_OR_FATAL( + (convertWrappedCollectionToAidl( + xDevicePort.getGains(), &ap_xsd::Gains::getGain, convertGainToAidl))), + + .ext = VALUE_OR_FATAL(createAudioPortExt(xDevicePort, xDefaultOutputDevice))}; +} + +ConversionResult> convertDevicePortsInModuleToAidl( + const ap_xsd::Modules::Module& xModuleConfig, int32_t& nextPortId) { + std::vector audioPortVec; + std::vector xDevicePortsVec = xModuleConfig.getDevicePorts(); + if (xDevicePortsVec.size() > 1) { + LOG(ERROR) << __func__ << "Having multiple '' 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 xAttachedDeviceSet = getAttachedDevices(xModuleConfig); + for (const auto& port : audioPortVec) { + const auto& devicePort = port.ext.get(); + if (xAttachedDeviceSet.count(port.name) != devicePort.device.type.connection.empty()) { + LOG(ERROR) << __func__ << ": Review Audio Policy config: " + << "list is incorrect or devicePort \"" << port.name + << "\" type= " << devicePort.device.type.toString() << " is incorrect."; + return unexpected(BAD_VALUE); + } + } + return audioPortVec; +} + +ConversionResult 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( + 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( + xMixPort.getGains(), &ap_xsd::Gains::getGain, &convertGainToAidl))), + .ext = VALUE_OR_FATAL(createAudioPortExt(xMixPort)), + }; +} + +ConversionResult> convertMixPortsInModuleToAidl( + const ap_xsd::Modules::Module& xModuleConfig, int32_t& nextPortId) { + std::vector audioPortVec; + std::vector xMixPortsVec = xModuleConfig.getMixPorts(); + if (xMixPortsVec.size() > 1) { + LOG(ERROR) << __func__ << "Having multiple '' 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 getSinkPortId(const ap_xsd::Routes::Route& xRoute, + const std::unordered_map& 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> getSourcePortIds( + const ap_xsd::Routes::Route& xRoute, + const std::unordered_map& portMap) { + std::vector 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 convertRouteToAidl(const ap_xsd::Routes::Route& xRoute, + const std::vector& aidlAudioPorts) { + std::unordered_map 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> convertRoutesInModuleToAidl( + const ap_xsd::Modules::Module& xModuleConfig, + const std::vector& aidlAudioPorts) { + std::vector audioRouteVec; + std::vector 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> convertModuleConfigToAidl( + const ap_xsd::Modules::Module& xModuleConfig) { + auto result = std::make_unique(); + auto& aidlModuleConfig = *result; + std::vector 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(); + if (!deviceExt.device.type.connection.empty()) continue; + deviceExt.flags |= 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE; + break; + } + + std::vector 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 convertCapCriterionToAidl( + const eng_xsd::CriterionType& xsdcCriterion) { + AudioHalCapCriterion aidlCapCriterion; + aidlCapCriterion.name = xsdcCriterion.getName(); + aidlCapCriterion.criterionTypeName = xsdcCriterion.getType(); + aidlCapCriterion.defaultLiteralValue = xsdcCriterion.get_default(); + return aidlCapCriterion; +} + +ConversionResult convertCriterionTypeValueToAidl( + const eng_xsd::ValueType& xsdcCriterionTypeValue) { + return xsdcCriterionTypeValue.getLiteral(); +} + +ConversionResult convertCapCriterionTypeToAidl( + const eng_xsd::CriterionTypeType& xsdcCriterionType) { + AudioHalCapCriterionType aidlCapCriterionType; + aidlCapCriterionType.name = xsdcCriterionType.getName(); + aidlCapCriterionType.isInclusive = !(static_cast(xsdcCriterionType.getType())); + aidlCapCriterionType.values = VALUE_OR_RETURN( + (convertWrappedCollectionToAidl( + xsdcCriterionType.getValues(), &eng_xsd::ValuesType::getValue, + &convertCriterionTypeValueToAidl))); + return aidlCapCriterionType; +} + +ConversionResult 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 diff --git a/audio/aidl/default/android.hardware.audio.service-aidl.xml b/audio/aidl/default/android.hardware.audio.service-aidl.xml index 9db606157a..57f61c9b2c 100644 --- a/audio/aidl/default/android.hardware.audio.service-aidl.xml +++ b/audio/aidl/default/android.hardware.audio.service-aidl.xml @@ -9,16 +9,6 @@ 1 IModule/r_submix - - android.hardware.audio.core - 1 - IModule/stub - - - android.hardware.audio.core - 1 - IModule/usb - android.hardware.audio.core 1 @@ -29,4 +19,16 @@ 1 IConfig/default + diff --git a/audio/aidl/default/config/audioPolicy/api/current.txt b/audio/aidl/default/config/audioPolicy/api/current.txt index e2bc833d43..3547f54d3b 100644 --- a/audio/aidl/default/config/audioPolicy/api/current.txt +++ b/audio/aidl/default/config/audioPolicy/api/current.txt @@ -85,16 +85,6 @@ package android.audio.policy.configuration { enum_constant public static final android.audio.policy.configuration.AudioChannelMask AUDIO_CHANNEL_OUT_TRI_BACK; } - public enum AudioContentType { - method @NonNull public String getRawName(); - enum_constant public static final android.audio.policy.configuration.AudioContentType AUDIO_CONTENT_TYPE_MOVIE; - enum_constant public static final android.audio.policy.configuration.AudioContentType AUDIO_CONTENT_TYPE_MUSIC; - enum_constant public static final android.audio.policy.configuration.AudioContentType AUDIO_CONTENT_TYPE_SONIFICATION; - enum_constant public static final android.audio.policy.configuration.AudioContentType AUDIO_CONTENT_TYPE_SPEECH; - enum_constant public static final android.audio.policy.configuration.AudioContentType AUDIO_CONTENT_TYPE_ULTRASOUND; - enum_constant public static final android.audio.policy.configuration.AudioContentType AUDIO_CONTENT_TYPE_UNKNOWN; - } - public enum AudioDevice { method @NonNull public String getRawName(); enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_IN_AMBIENT; @@ -168,13 +158,6 @@ package android.audio.policy.configuration { enum_constant public static final android.audio.policy.configuration.AudioDevice AUDIO_DEVICE_OUT_WIRED_HEADSET; } - public enum AudioEncapsulationType { - method @NonNull public String getRawName(); - enum_constant public static final android.audio.policy.configuration.AudioEncapsulationType AUDIO_ENCAPSULATION_TYPE_IEC61937; - enum_constant public static final android.audio.policy.configuration.AudioEncapsulationType AUDIO_ENCAPSULATION_TYPE_NONE; - enum_constant public static final android.audio.policy.configuration.AudioEncapsulationType AUDIO_ENCAPSULATION_TYPE_PCM; - } - public enum AudioFormat { method @NonNull public String getRawName(); enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AAC; @@ -359,29 +342,6 @@ package android.audio.policy.configuration { enum_constant public static final android.audio.policy.configuration.AudioStreamType AUDIO_STREAM_VOICE_CALL; } - public enum AudioUsage { - method @NonNull public String getRawName(); - enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_ALARM; - enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_ANNOUNCEMENT; - enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY; - enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE; - enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_ASSISTANCE_SONIFICATION; - enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_ASSISTANT; - enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_CALL_ASSISTANT; - enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_EMERGENCY; - enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_GAME; - enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_MEDIA; - enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_NOTIFICATION; - enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_NOTIFICATION_EVENT; - enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE; - enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_SAFETY; - enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_UNKNOWN; - enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_VEHICLE_STATUS; - enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_VIRTUAL_SOURCE; - enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_VOICE_COMMUNICATION; - enum_constant public static final android.audio.policy.configuration.AudioUsage AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING; - } - public enum DeviceCategory { method @NonNull public String getRawName(); enum_constant public static final android.audio.policy.configuration.DeviceCategory DEVICE_CATEGORY_EARPIECE; @@ -435,7 +395,6 @@ package android.audio.policy.configuration { method @Nullable public int getMinRampMs(); method @Nullable public int getMinValueMB(); method @Nullable public java.util.List getMode(); - method @Nullable public String getName(); method @Nullable public int getStepValueMB(); method @Nullable public boolean getUseForVolume(); method public void setChannel_mask(@Nullable android.audio.policy.configuration.AudioChannelMask); @@ -445,7 +404,6 @@ package android.audio.policy.configuration { method public void setMinRampMs(@Nullable int); method public void setMinValueMB(@Nullable int); method public void setMode(@Nullable java.util.List); - method public void setName(@Nullable String); method public void setStepValueMB(@Nullable int); method public void setUseForVolume(@Nullable boolean); } @@ -478,7 +436,6 @@ package android.audio.policy.configuration { method @Nullable public long getMaxActiveCount(); method @Nullable public long getMaxOpenCount(); method @Nullable public String getName(); - method @Nullable public java.util.List getPreferredUsage(); method @Nullable public java.util.List getProfile(); method @Nullable public long getRecommendedMuteDurationMs(); method @Nullable public android.audio.policy.configuration.Role getRole(); @@ -487,7 +444,6 @@ package android.audio.policy.configuration { method public void setMaxActiveCount(@Nullable long); method public void setMaxOpenCount(@Nullable long); method public void setName(@Nullable String); - method public void setPreferredUsage(@Nullable java.util.List); method public void setRecommendedMuteDurationMs(@Nullable long); method public void setRole(@Nullable android.audio.policy.configuration.Role); } @@ -524,14 +480,10 @@ package android.audio.policy.configuration { public class Profile { ctor public Profile(); method @Nullable public java.util.List getChannelMasks(); - method @Nullable public android.audio.policy.configuration.AudioEncapsulationType getEncapsulationType(); method @Nullable public String getFormat(); - method @Nullable public String getName(); method @Nullable public java.util.List getSamplingRates(); method public void setChannelMasks(@Nullable java.util.List); - method public void setEncapsulationType(@Nullable android.audio.policy.configuration.AudioEncapsulationType); method public void setFormat(@Nullable String); - method public void setName(@Nullable String); method public void setSamplingRates(@Nullable java.util.List); } diff --git a/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd b/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd index 9a3a447b5f..d93f6972e1 100644 --- a/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd +++ b/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd @@ -217,20 +217,6 @@ - - - - When choosing the mixPort of an audio track, the audioPolicy - first considers the mixPorts with a preferredUsage including - the track AudioUsage preferred . - If non support the track format, the other mixPorts are considered. - Eg: a will receive - the audio of all apps playing with a MEDIA usage. - It may receive audio from ALARM if there are no audio compatible - . - - - @@ -434,56 +420,6 @@ - - - - Audio usage specifies the intended use case for the sound being played. - Please consult frameworks/base/media/java/android/media/AudioAttributes.java - for the description of each value. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Audio content type expresses the general category of the content. - Please consult frameworks/base/media/java/android/media/AudioAttributes.java - for the description of each value. - - - - - - - - - - - @@ -579,19 +515,10 @@ - - - - - - - - - @@ -612,7 +539,6 @@ - diff --git a/audio/aidl/default/include/core-impl/AudioPolicyConfigXmlConverter.h b/audio/aidl/default/include/core-impl/AudioPolicyConfigXmlConverter.h index 090d58585f..bff4b4a5d4 100644 --- a/audio/aidl/default/include/core-impl/AudioPolicyConfigXmlConverter.h +++ b/audio/aidl/default/include/core-impl/AudioPolicyConfigXmlConverter.h @@ -16,27 +16,42 @@ #pragma once +#include +#include #include +#include +#include +#include #include #include #include #include +#include +#include "core-impl/Module.h" #include "core-impl/XmlConverter.h" namespace aidl::android::hardware::audio::core::internal { class AudioPolicyConfigXmlConverter { public: + using ModuleConfiguration = std::pair>; + using ModuleConfigs = std::vector; + explicit AudioPolicyConfigXmlConverter(const std::string& configFilePath) - : mConverter(configFilePath, &::android::audio::policy::configuration::read) {} + : mConverter(configFilePath, &::android::audio::policy::configuration::read) { + if (mConverter.getXsdcConfig()) { + init(); + } + } std::string getError() const { return mConverter.getError(); } ::android::status_t getStatus() const { return mConverter.getStatus(); } const ::aidl::android::media::audio::common::AudioHalEngineConfig& getAidlEngineConfig(); const SurroundSoundConfig& getSurroundSoundConfig(); + std::unique_ptr releaseModuleConfigs(); // Public for testing purposes. static const SurroundSoundConfig& getDefaultSurroundSoundConfig(); @@ -47,13 +62,13 @@ class AudioPolicyConfigXmlConverter { return mConverter.getXsdcConfig(); } void addVolumeGroupstoEngineConfig(); + void init(); void mapStreamToVolumeCurve( const ::android::audio::policy::configuration::Volume& xsdcVolumeCurve); void mapStreamsToVolumeCurves(); void parseVolumes(); - ::aidl::android::media::audio::common::AudioHalVolumeCurve::CurvePoint convertCurvePointToAidl( - const std::string& xsdcCurvePoint); - ::aidl::android::media::audio::common::AudioHalVolumeCurve convertVolumeCurveToAidl( + ConversionResult<::aidl::android::media::audio::common::AudioHalVolumeCurve> + convertVolumeCurveToAidl( const ::android::audio::policy::configuration::Volume& xsdcVolumeCurve); ::aidl::android::media::audio::common::AudioHalEngineConfig mAidlEngineConfig; @@ -63,6 +78,7 @@ class AudioPolicyConfigXmlConverter { std::unordered_map<::android::audio::policy::configuration::AudioStreamType, std::vector<::aidl::android::media::audio::common::AudioHalVolumeCurve>> mStreamToVolumeCurvesMap; + std::unique_ptr mModuleConfigurations = std::make_unique(); }; } // namespace aidl::android::hardware::audio::core::internal diff --git a/audio/aidl/default/include/core-impl/ChildInterface.h b/audio/aidl/default/include/core-impl/ChildInterface.h index 2421b59a1a..3b74c5e4d7 100644 --- a/audio/aidl/default/include/core-impl/ChildInterface.h +++ b/audio/aidl/default/include/core-impl/ChildInterface.h @@ -42,12 +42,16 @@ struct ChildInterface : private std::pair, ndk::SpAIBinder> { C* operator->() const { return this->first; } // Use 'getInstance' when returning the interface instance. std::shared_ptr getInstance() { + (void)getBinder(); + return this->first; + } + AIBinder* getBinder() { if (this->second.get() == nullptr) { this->second = this->first->asBinder(); AIBinder_setMinSchedulerPolicy(this->second.get(), SCHED_NORMAL, ANDROID_PRIORITY_AUDIO); } - return this->first; + return this->second.get(); } }; diff --git a/audio/aidl/default/include/core-impl/Config.h b/audio/aidl/default/include/core-impl/Config.h index 96a6cb9e8e..63d4b3d0c2 100644 --- a/audio/aidl/default/include/core-impl/Config.h +++ b/audio/aidl/default/include/core-impl/Config.h @@ -26,11 +26,16 @@ namespace aidl::android::hardware::audio::core { static const std::string kEngineConfigFileName = "audio_policy_engine_configuration.xml"; class Config : public BnConfig { + public: + explicit Config(internal::AudioPolicyConfigXmlConverter& apConverter) + : mAudioPolicyConverter(apConverter) {} + + private: ndk::ScopedAStatus getSurroundSoundConfig(SurroundSoundConfig* _aidl_return) override; ndk::ScopedAStatus getEngineConfig( aidl::android::media::audio::common::AudioHalEngineConfig* _aidl_return) override; - internal::AudioPolicyConfigXmlConverter mAudioPolicyConverter{ - ::android::audio_get_audio_policy_config_file()}; + + internal::AudioPolicyConfigXmlConverter& mAudioPolicyConverter; internal::EngineConfigXmlConverter mEngConfigConverter{ ::android::audio_find_readable_configuration_file(kEngineConfigFileName.c_str())}; }; diff --git a/audio/aidl/default/include/core-impl/Configuration.h b/audio/aidl/default/include/core-impl/Configuration.h index 6277c38db2..aa7b9fff97 100644 --- a/audio/aidl/default/include/core-impl/Configuration.h +++ b/audio/aidl/default/include/core-impl/Configuration.h @@ -16,37 +16,12 @@ #pragma once -#include #include -#include -#include -#include -#include -#include -#include +#include "Module.h" namespace aidl::android::hardware::audio::core::internal { -struct Configuration { - std::vector<::aidl::android::media::audio::common::MicrophoneInfo> microphones; - std::vector<::aidl::android::media::audio::common::AudioPort> ports; - std::vector<::aidl::android::media::audio::common::AudioPortConfig> portConfigs; - std::vector<::aidl::android::media::audio::common::AudioPortConfig> initialConfigs; - // Port id -> List of profiles to use when the device port state is set to 'connected' - // in connection simulation mode. - std::map> - connectedProfiles; - std::vector routes; - std::vector patches; - int32_t nextPortId = 1; - int32_t nextPatchId = 1; -}; - -std::unique_ptr getPrimaryConfiguration(); -std::unique_ptr getRSubmixConfiguration(); -std::unique_ptr getStubConfiguration(); -std::unique_ptr getUsbConfiguration(); -std::unique_ptr getBluetoothConfiguration(); +std::unique_ptr getConfiguration(Module::Type moduleType); } // namespace aidl::android::hardware::audio::core::internal diff --git a/audio/aidl/default/include/core-impl/EngineConfigXmlConverter.h b/audio/aidl/default/include/core-impl/EngineConfigXmlConverter.h index b34441d9ac..22ac8cb42c 100644 --- a/audio/aidl/default/include/core-impl/EngineConfigXmlConverter.h +++ b/audio/aidl/default/include/core-impl/EngineConfigXmlConverter.h @@ -19,10 +19,9 @@ #include #include -#include - #include #include +#include #include "core-impl/XmlConverter.h" @@ -49,29 +48,24 @@ class EngineConfigXmlConverter { } void init(); void initProductStrategyMap(); - ::aidl::android::media::audio::common::AudioAttributes convertAudioAttributesToAidl( + ConversionResult<::aidl::android::media::audio::common::AudioAttributes> + convertAudioAttributesToAidl( const ::android::audio::policy::engine::configuration::AttributesType& xsdcAudioAttributes); - ::aidl::android::media::audio::common::AudioHalAttributesGroup convertAttributesGroupToAidl( + ConversionResult<::aidl::android::media::audio::common::AudioHalAttributesGroup> + convertAttributesGroupToAidl( const ::android::audio::policy::engine::configuration::AttributesGroup& xsdcAttributesGroup); - ::aidl::android::media::audio::common::AudioHalCapCriterion convertCapCriterionToAidl( - const ::android::audio::policy::engine::configuration::CriterionType& xsdcCriterion); - ::aidl::android::media::audio::common::AudioHalCapCriterionType convertCapCriterionTypeToAidl( - const ::android::audio::policy::engine::configuration::CriterionTypeType& - xsdcCriterionType); - std::string convertCriterionTypeValueToAidl( - const ::android::audio::policy::engine::configuration::ValueType& - xsdcCriterionTypeValue); - ::aidl::android::media::audio::common::AudioHalVolumeCurve::CurvePoint convertCurvePointToAidl( - const std::string& xsdcCurvePoint); - ::aidl::android::media::audio::common::AudioHalProductStrategy convertProductStrategyToAidl( - const ::android::audio::policy::engine::configuration::ProductStrategies:: - ProductStrategy& xsdcProductStrategy); - int convertProductStrategyNameToAidl(const std::string& xsdcProductStrategyName); - ::aidl::android::media::audio::common::AudioHalVolumeCurve convertVolumeCurveToAidl( + ConversionResult<::aidl::android::media::audio::common::AudioHalProductStrategy> + convertProductStrategyToAidl(const ::android::audio::policy::engine::configuration:: + ProductStrategies::ProductStrategy& xsdcProductStrategy); + ConversionResult convertProductStrategyNameToAidl( + const std::string& xsdcProductStrategyName); + ConversionResult<::aidl::android::media::audio::common::AudioHalVolumeCurve> + convertVolumeCurveToAidl( const ::android::audio::policy::engine::configuration::Volume& xsdcVolumeCurve); - ::aidl::android::media::audio::common::AudioHalVolumeGroup convertVolumeGroupToAidl( + ConversionResult<::aidl::android::media::audio::common::AudioHalVolumeGroup> + convertVolumeGroupToAidl( const ::android::audio::policy::engine::configuration::VolumeGroupsType::VolumeGroup& xsdcVolumeGroup); diff --git a/audio/aidl/default/include/core-impl/Module.h b/audio/aidl/default/include/core-impl/Module.h index da94815722..c39aa36361 100644 --- a/audio/aidl/default/include/core-impl/Module.h +++ b/audio/aidl/default/include/core-impl/Module.h @@ -19,31 +19,51 @@ #include #include #include +#include #include #include #include "core-impl/ChildInterface.h" -#include "core-impl/Configuration.h" #include "core-impl/Stream.h" namespace aidl::android::hardware::audio::core { class Module : public BnModule { public: - // This value is used for all AudioPatches and reported by all streams. - static constexpr int32_t kLatencyMs = 10; + struct Configuration { + std::vector<::aidl::android::media::audio::common::MicrophoneInfo> microphones; + std::vector<::aidl::android::media::audio::common::AudioPort> ports; + std::vector<::aidl::android::media::audio::common::AudioPortConfig> portConfigs; + std::vector<::aidl::android::media::audio::common::AudioPortConfig> initialConfigs; + // Port id -> List of profiles to use when the device port state is set to 'connected' + // in connection simulation mode. + std::map> + connectedProfiles; + std::vector routes; + std::vector patches; + int32_t nextPortId = 1; + int32_t nextPatchId = 1; + }; enum Type : int { DEFAULT, R_SUBMIX, STUB, USB, BLUETOOTH }; enum BtInterface : int { BTCONF, BTA2DP, BTLE }; - - static std::shared_ptr createInstance(Type type); - - explicit Module(Type type) : mType(type) {} - typedef std::tuple, std::weak_ptr, std::weak_ptr> BtProfileHandles; + // This value is used by default for all AudioPatches and reported by all streams. + static constexpr int32_t kLatencyMs = 10; + + static std::shared_ptr createInstance(Type type) { + return createInstance(type, std::make_unique()); + } + static std::shared_ptr createInstance(Type type, + std::unique_ptr&& config); + static std::optional typeFromString(const std::string& type); + + Module(Type type, std::unique_ptr&& config) + : mType(type), mConfig(std::move(config)) {} + protected: // The vendor extension done via inheritance can override interface methods and augment // a call to the base implementation. @@ -148,7 +168,7 @@ class Module : public BnModule { using Patches = std::multimap; const Type mType; - std::unique_ptr mConfig; + std::unique_ptr mConfig; ModuleDebug mDebug; VendorDebug mVendorDebug; ConnectedDevicePorts mConnectedDevicePorts; @@ -187,7 +207,7 @@ class Module : public BnModule { const ::aidl::android::media::audio::common::AudioPort& audioPort, bool connected); virtual ndk::ScopedAStatus onMasterMuteChanged(bool mute); virtual ndk::ScopedAStatus onMasterVolumeChanged(float volume); - virtual std::unique_ptr initializeConfig(); + virtual std::unique_ptr initializeConfig(); // Utility and helper functions accessible to subclasses. ndk::ScopedAStatus bluetoothParametersUpdated(); @@ -204,7 +224,7 @@ class Module : public BnModule { int32_t in_portConfigId, ::aidl::android::media::audio::common::AudioPort** port); std::vector getAudioRoutesForAudioPortImpl(int32_t portId); virtual BtProfileHandles getBtProfileManagerHandles(); - internal::Configuration& getConfig(); + Configuration& getConfig(); const ConnectedDevicePorts& getConnectedDevicePorts() const { return mConnectedDevicePorts; } bool getMasterMute() const { return mMasterMute; } bool getMasterVolume() const { return mMasterVolume; } diff --git a/audio/aidl/default/include/core-impl/ModuleAlsa.h b/audio/aidl/default/include/core-impl/ModuleAlsa.h index 5815961f7c..2774fe5b9e 100644 --- a/audio/aidl/default/include/core-impl/ModuleAlsa.h +++ b/audio/aidl/default/include/core-impl/ModuleAlsa.h @@ -27,7 +27,8 @@ namespace aidl::android::hardware::audio::core { // provide necessary overrides for all interface methods omitted here. class ModuleAlsa : public Module { public: - explicit ModuleAlsa(Module::Type type) : Module(type) {} + ModuleAlsa(Type type, std::unique_ptr&& config) + : Module(type, std::move(config)) {} protected: // Extension methods of 'Module'. diff --git a/audio/aidl/default/include/core-impl/ModuleBluetooth.h b/audio/aidl/default/include/core-impl/ModuleBluetooth.h index 526a809fdf..7ac2d34d42 100644 --- a/audio/aidl/default/include/core-impl/ModuleBluetooth.h +++ b/audio/aidl/default/include/core-impl/ModuleBluetooth.h @@ -23,7 +23,8 @@ namespace aidl::android::hardware::audio::core { class ModuleBluetooth final : public Module { public: - ModuleBluetooth() : Module(Type::BLUETOOTH) {} + ModuleBluetooth(std::unique_ptr&& config) + : Module(Type::BLUETOOTH, std::move(config)) {} private: BtProfileHandles getBtProfileManagerHandles() override; diff --git a/audio/aidl/default/include/core-impl/ModulePrimary.h b/audio/aidl/default/include/core-impl/ModulePrimary.h index 6264237fe3..ee86d644c4 100644 --- a/audio/aidl/default/include/core-impl/ModulePrimary.h +++ b/audio/aidl/default/include/core-impl/ModulePrimary.h @@ -22,7 +22,8 @@ namespace aidl::android::hardware::audio::core { class ModulePrimary final : public Module { public: - ModulePrimary() : Module(Type::DEFAULT) {} + ModulePrimary(std::unique_ptr&& config) + : Module(Type::DEFAULT, std::move(config)) {} protected: ndk::ScopedAStatus getTelephony(std::shared_ptr* _aidl_return) override; diff --git a/audio/aidl/default/include/core-impl/ModuleRemoteSubmix.h b/audio/aidl/default/include/core-impl/ModuleRemoteSubmix.h index c4bf7b99c2..ebf4558763 100644 --- a/audio/aidl/default/include/core-impl/ModuleRemoteSubmix.h +++ b/audio/aidl/default/include/core-impl/ModuleRemoteSubmix.h @@ -22,7 +22,8 @@ namespace aidl::android::hardware::audio::core { class ModuleRemoteSubmix : public Module { public: - ModuleRemoteSubmix() : Module(Type::R_SUBMIX) {} + ModuleRemoteSubmix(std::unique_ptr&& config) + : Module(Type::R_SUBMIX, std::move(config)) {} private: // IModule interfaces diff --git a/audio/aidl/default/include/core-impl/ModuleStub.h b/audio/aidl/default/include/core-impl/ModuleStub.h index 4f771611ab..e9b7db4286 100644 --- a/audio/aidl/default/include/core-impl/ModuleStub.h +++ b/audio/aidl/default/include/core-impl/ModuleStub.h @@ -22,7 +22,7 @@ namespace aidl::android::hardware::audio::core { class ModuleStub final : public Module { public: - ModuleStub() : Module(Type::STUB) {} + ModuleStub(std::unique_ptr&& config) : Module(Type::STUB, std::move(config)) {} protected: ndk::ScopedAStatus getBluetooth(std::shared_ptr* _aidl_return) override; diff --git a/audio/aidl/default/include/core-impl/ModuleUsb.h b/audio/aidl/default/include/core-impl/ModuleUsb.h index a296b8c042..6ee8f8a691 100644 --- a/audio/aidl/default/include/core-impl/ModuleUsb.h +++ b/audio/aidl/default/include/core-impl/ModuleUsb.h @@ -22,7 +22,7 @@ namespace aidl::android::hardware::audio::core { class ModuleUsb final : public ModuleAlsa { public: - ModuleUsb() : ModuleAlsa(Type::USB) {} + ModuleUsb(std::unique_ptr&& config) : ModuleAlsa(Type::USB, std::move(config)) {} private: // IModule interfaces diff --git a/audio/aidl/default/include/core-impl/XmlConverter.h b/audio/aidl/default/include/core-impl/XmlConverter.h index 383ea24836..68e6b8e3a3 100644 --- a/audio/aidl/default/include/core-impl/XmlConverter.h +++ b/audio/aidl/default/include/core-impl/XmlConverter.h @@ -22,7 +22,6 @@ #include #include -#include namespace aidl::android::hardware::audio::core::internal { @@ -85,10 +84,10 @@ class XmlConverter { * */ template -std::vector convertWrappedCollectionToAidlUnchecked( +static ConversionResult> convertWrappedCollectionToAidl( const std::vector& xsdcWrapperTypeVec, std::function&(const W&)> getInnerTypeVec, - std::function convertToAidl) { + std::function(const X&)> convertToAidl) { std::vector resultAidlTypeVec; if (!xsdcWrapperTypeVec.empty()) { /* @@ -98,21 +97,23 @@ std::vector convertWrappedCollectionToAidlUnchecked( */ resultAidlTypeVec.reserve(getInnerTypeVec(xsdcWrapperTypeVec[0]).size()); for (const W& xsdcWrapperType : xsdcWrapperTypeVec) { - std::transform(getInnerTypeVec(xsdcWrapperType).begin(), - getInnerTypeVec(xsdcWrapperType).end(), - std::back_inserter(resultAidlTypeVec), convertToAidl); + for (const X& xsdcType : getInnerTypeVec(xsdcWrapperType)) { + resultAidlTypeVec.push_back(VALUE_OR_FATAL(convertToAidl(xsdcType))); + } } } return resultAidlTypeVec; } template -std::vector convertCollectionToAidlUnchecked(const std::vector& xsdcTypeVec, - std::function itemConversion) { +static ConversionResult> convertCollectionToAidl( + const std::vector& xsdcTypeVec, + std::function(const X&)> convertToAidl) { std::vector resultAidlTypeVec; resultAidlTypeVec.reserve(xsdcTypeVec.size()); - std::transform(xsdcTypeVec.begin(), xsdcTypeVec.end(), std::back_inserter(resultAidlTypeVec), - itemConversion); + for (const X& xsdcType : xsdcTypeVec) { + resultAidlTypeVec.push_back(VALUE_OR_FATAL(convertToAidl(xsdcType))); + } return resultAidlTypeVec; } diff --git a/audio/aidl/default/include/core-impl/XsdcConversion.h b/audio/aidl/default/include/core-impl/XsdcConversion.h new file mode 100644 index 0000000000..30dc8b635b --- /dev/null +++ b/audio/aidl/default/include/core-impl/XsdcConversion.h @@ -0,0 +1,29 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "core-impl/Module.h" + +namespace aidl::android::hardware::audio::core::internal { + +ConversionResult<::aidl::android::media::audio::common::AudioHalCapCriterion> +convertCapCriterionToAidl( + const ::android::audio::policy::engine::configuration::CriterionType& xsdcCriterion); +ConversionResult<::aidl::android::media::audio::common::AudioHalCapCriterionType> +convertCapCriterionTypeToAidl( + const ::android::audio::policy::engine::configuration::CriterionTypeType& + xsdcCriterionType); +ConversionResult<::aidl::android::media::audio::common::AudioHalVolumeCurve::CurvePoint> +convertCurvePointToAidl(const std::string& xsdcCurvePoint); +ConversionResult> convertModuleConfigToAidl( + const ::android::audio::policy::configuration::Modules::Module& moduleConfig); +} // namespace aidl::android::hardware::audio::core::internal diff --git a/audio/aidl/default/main.cpp b/audio/aidl/default/main.cpp index a0c0fab40a..6ab747db32 100644 --- a/audio/aidl/default/main.cpp +++ b/audio/aidl/default/main.cpp @@ -16,21 +16,51 @@ #include #include -#include #include #include +#define LOG_TAG "AHAL_Main" #include #include #include #include #include +#include "core-impl/AudioPolicyConfigXmlConverter.h" +#include "core-impl/ChildInterface.h" #include "core-impl/Config.h" #include "core-impl/Module.h" +using aidl::android::hardware::audio::core::ChildInterface; using aidl::android::hardware::audio::core::Config; using aidl::android::hardware::audio::core::Module; +using aidl::android::hardware::audio::core::internal::AudioPolicyConfigXmlConverter; + +namespace { + +ChildInterface createModule(const std::string& name, + std::unique_ptr&& config) { + ChildInterface result; + { + auto moduleType = Module::typeFromString(name); + if (!moduleType.has_value()) { + LOG(ERROR) << __func__ << ": module type \"" << name << "\" is not supported"; + return result; + } + auto module = Module::createInstance(*moduleType, std::move(config)); + if (module == nullptr) return result; + result = std::move(module); + } + const std::string moduleFqn = std::string().append(Module::descriptor).append("/").append(name); + binder_status_t status = AServiceManager_addService(result.getBinder(), moduleFqn.c_str()); + if (status != STATUS_OK) { + LOG(ERROR) << __func__ << ": failed to register service for \"" << moduleFqn << "\""; + return ChildInterface(); + } + return result; +}; + +} // namespace int main() { // Random values are used in the implementation. @@ -45,29 +75,27 @@ int main() { // Guaranteed log for b/210919187 and logd_integration_test LOG(INFO) << "Init for Audio AIDL HAL"; + AudioPolicyConfigXmlConverter audioPolicyConverter{ + ::android::audio_get_audio_policy_config_file()}; + // Make the default config service - auto config = ndk::SharedRefBase::make(); - const std::string configName = std::string() + Config::descriptor + "/default"; + auto config = ndk::SharedRefBase::make(audioPolicyConverter); + const std::string configFqn = std::string().append(Config::descriptor).append("/default"); binder_status_t status = - AServiceManager_addService(config->asBinder().get(), configName.c_str()); - CHECK_EQ(STATUS_OK, status); + AServiceManager_addService(config->asBinder().get(), configFqn.c_str()); + if (status != STATUS_OK) { + LOG(ERROR) << "failed to register service for \"" << configFqn << "\""; + } // Make modules - auto createModule = [](Module::Type type) { - auto module = Module::createInstance(type); - ndk::SpAIBinder moduleBinder = module->asBinder(); - std::stringstream moduleName; - moduleName << Module::descriptor << "/" << type; - AIBinder_setMinSchedulerPolicy(moduleBinder.get(), SCHED_NORMAL, ANDROID_PRIORITY_AUDIO); - binder_status_t status = - AServiceManager_addService(moduleBinder.get(), moduleName.str().c_str()); - CHECK_EQ(STATUS_OK, status); - return std::make_pair(module, moduleBinder); - }; - auto modules = {createModule(Module::Type::DEFAULT), createModule(Module::Type::R_SUBMIX), - createModule(Module::Type::USB), createModule(Module::Type::STUB), - createModule(Module::Type::BLUETOOTH)}; - (void)modules; + std::vector> moduleInstances; + auto configs(audioPolicyConverter.releaseModuleConfigs()); + for (std::pair>& configPair : *configs) { + std::string name = configPair.first; + if (auto instance = createModule(name, std::move(configPair.second)); instance) { + moduleInstances.push_back(std::move(instance)); + } + } ABinderProcess_joinThreadPool(); return EXIT_FAILURE; // should not reach