/* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #define LOG_TAG "AHAL_ApmXmlConverter" #include #include #include #include #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; using aidl::android::media::audio::common::AudioHalVolumeCurve; using aidl::android::media::audio::common::AudioHalVolumeGroup; using aidl::android::media::audio::common::AudioStreamType; 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; ConversionResult AudioPolicyConfigXmlConverter::convertVolumeCurveToAidl( const ap_xsd::Volume& xsdcVolumeCurve) { AudioHalVolumeCurve aidlVolumeCurve; aidlVolumeCurve.deviceCategory = static_cast(xsdcVolumeCurve.getDeviceCategory()); if (xsdcVolumeCurve.hasRef()) { if (mVolumesReferenceMap.empty()) { mVolumesReferenceMap = generateReferenceMap( getXsdcConfig()->getVolumes()); } aidlVolumeCurve.curvePoints = VALUE_OR_FATAL( (convertCollectionToAidl( mVolumesReferenceMap.at(xsdcVolumeCurve.getRef()).getPoint(), &convertCurvePointToAidl))); } else { aidlVolumeCurve.curvePoints = VALUE_OR_FATAL( (convertCollectionToAidl( xsdcVolumeCurve.getPoint(), &convertCurvePointToAidl))); } return aidlVolumeCurve; } void AudioPolicyConfigXmlConverter::mapStreamToVolumeCurve(const ap_xsd::Volume& xsdcVolumeCurve) { mStreamToVolumeCurvesMap[xsdcVolumeCurve.getStream()].push_back( VALUE_OR_FATAL(convertVolumeCurveToAidl(xsdcVolumeCurve))); } const SurroundSoundConfig& AudioPolicyConfigXmlConverter::getSurroundSoundConfig() { static const SurroundSoundConfig aidlSurroundSoundConfig = [this]() { if (auto xsdcConfig = getXsdcConfig(); xsdcConfig && xsdcConfig->hasSurroundSound()) { auto configConv = xsdc2aidl_SurroundSoundConfig(*xsdcConfig->getFirstSurroundSound()); if (configConv.ok()) { return configConv.value(); } LOG(ERROR) << "There was an error converting surround formats to AIDL: " << configConv.error(); } LOG(WARNING) << "Audio policy config does not have section, using default"; return getDefaultSurroundSoundConfig(); }(); return aidlSurroundSoundConfig; } std::unique_ptr AudioPolicyConfigXmlConverter::releaseModuleConfigs() { return std::move(mModuleConfigurations); } const AudioHalEngineConfig& AudioPolicyConfigXmlConverter::getAidlEngineConfig() { if (mAidlEngineConfig.volumeGroups.empty() && getXsdcConfig() && getXsdcConfig()->hasVolumes()) { parseVolumes(); } return mAidlEngineConfig; } // static const SurroundSoundConfig& AudioPolicyConfigXmlConverter::getDefaultSurroundSoundConfig() { // Provide a config similar to the one used by the framework by default // (see AudioPolicyConfig::setDefaultSurroundFormats). #define ENCODED_FORMAT(format) \ AudioFormatDescription { \ .encoding = ::android::format \ } #define SIMPLE_FORMAT(format) \ SurroundSoundConfig::SurroundFormatFamily { \ .primaryFormat = ENCODED_FORMAT(format) \ } static const SurroundSoundConfig defaultConfig = { .formatFamilies = { SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_AC3), SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_EAC3), SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_DTS), SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_DTS_HD), SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_DTS_HD_MA), SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_DTS_UHD_P1), SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_DTS_UHD_P2), SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_DOLBY_TRUEHD), SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_EAC3_JOC), SurroundSoundConfig::SurroundFormatFamily{ .primaryFormat = ENCODED_FORMAT(MEDIA_MIMETYPE_AUDIO_AAC_LC), .subFormats = { ENCODED_FORMAT(MEDIA_MIMETYPE_AUDIO_AAC_HE_V1), ENCODED_FORMAT(MEDIA_MIMETYPE_AUDIO_AAC_HE_V2), ENCODED_FORMAT(MEDIA_MIMETYPE_AUDIO_AAC_ELD), ENCODED_FORMAT(MEDIA_MIMETYPE_AUDIO_AAC_XHE), }}, SIMPLE_FORMAT(MEDIA_MIMETYPE_AUDIO_AC4), }}; #undef SIMPLE_FORMAT #undef ENCODED_FORMAT return defaultConfig; } void AudioPolicyConfigXmlConverter::mapStreamsToVolumeCurves() { if (getXsdcConfig()->hasVolumes()) { for (const ap_xsd::Volumes& xsdcWrapperType : getXsdcConfig()->getVolumes()) { for (const ap_xsd::Volume& xsdcVolume : xsdcWrapperType.getVolume()) { mapStreamToVolumeCurve(xsdcVolume); } } } } void AudioPolicyConfigXmlConverter::addVolumeGroupstoEngineConfig() { for (const auto& [xsdcStream, volumeCurves] : mStreamToVolumeCurvesMap) { AudioHalVolumeGroup volumeGroup; volumeGroup.name = ap_xsd::toString(xsdcStream); if (static_cast(xsdcStream) >= AUDIO_STREAM_PUBLIC_CNT) { volumeGroup.minIndex = kDefaultVolumeIndexMin; volumeGroup.maxIndex = kDefaultVolumeIndexMax; } else { volumeGroup.minIndex = KVolumeIndexDeferredToAudioService; volumeGroup.maxIndex = KVolumeIndexDeferredToAudioService; } volumeGroup.volumeCurves = volumeCurves; mAidlEngineConfig.volumeGroups.push_back(std::move(volumeGroup)); } } void AudioPolicyConfigXmlConverter::parseVolumes() { if (mStreamToVolumeCurvesMap.empty() && getXsdcConfig()->hasVolumes()) { mapStreamsToVolumeCurves(); 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"; if (name != "r_submix") { mModuleConfigurations->emplace_back( name, VALUE_OR_FATAL(convertModuleConfigToAidl(xsdcModule))); } else { // See the note on the 'getRSubmixConfiguration' function. mModuleConfigurations->emplace_back(name, nullptr); } } } } } // namespace aidl::android::hardware::audio::core::internal