APM: Implementing configuration loading from AIDL HAL
The main change is to utilize 'getAudioPolicyConfig'
to receive the HAL-provided configuration from
the AudioFlinger and initialize runtime structures
from it.
Accompanying changes:
- made `libaudiopolicycomponents` a shared library;
- added or moved around necessary conversion functions;
Bug: 205884982
Test: run CF with AIDL HAL and compare APM dump A/B
Test: m audiopolicy_fuzzer
Test: atest audio_health_tests
Test: atest audio_aidl_ndk_conversion_tests
Change-Id: I7d0f48bf4d9d4bdaa46246aa4dfbcc49e835c6b6
diff --git a/services/audiopolicy/common/managerdefinitions/Android.bp b/services/audiopolicy/common/managerdefinitions/Android.bp
index 3df23f1..972de02 100644
--- a/services/audiopolicy/common/managerdefinitions/Android.bp
+++ b/services/audiopolicy/common/managerdefinitions/Android.bp
@@ -7,9 +7,13 @@
default_applicable_licenses: ["frameworks_av_license"],
}
-cc_library_static {
+cc_library {
name: "libaudiopolicycomponents",
+ defaults: [
+ "latest_android_media_audio_common_types_cpp_shared",
+ ],
+
srcs: [
"src/AudioCollections.cpp",
"src/AudioInputDescriptor.cpp",
@@ -30,7 +34,11 @@
"src/TypeConverter.cpp",
],
shared_libs: [
+ "audioclient-types-aidl-cpp",
+ "audiopolicy-types-aidl-cpp",
+ "libaudioclient_aidl_conversion",
"libaudiofoundation",
+ "libaudiopolicy",
"libbase",
"libcutils",
"libhidlbase",
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
index 32c78a1..1f6002f 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
@@ -23,6 +23,7 @@
#include <DeviceDescriptor.h>
#include <HwModule.h>
+#include <android/media/AudioPolicyConfig.h>
#include <error/Result.h>
#include <utils/StrongPointer.h>
#include <utils/RefBase.h>
@@ -42,6 +43,8 @@
// Surround formats, with an optional list of subformats that are equivalent from users' POV.
using SurroundFormats = std::unordered_map<audio_format_t, std::unordered_set<audio_format_t>>;
+ // The source used to indicate the configuration from the AIDL HAL.
+ static const constexpr char* const kAidlConfigSource = "AIDL HAL";
// The source used to indicate the default fallback configuration.
static const constexpr char* const kDefaultConfigSource = "AudioPolicyConfig::setDefault";
// The suffix of the "engine default" implementation shared library name.
@@ -49,6 +52,9 @@
// Creates the default (fallback) configuration.
static sp<const AudioPolicyConfig> createDefault();
+ // Attempts to load the configuration from the AIDL config falls back to default on failure.
+ static sp<const AudioPolicyConfig> loadFromApmAidlConfigWithFallback(
+ const media::AudioPolicyConfig& aidl);
// Attempts to load the configuration from the XML file, falls back to default on failure.
// If the XML file path is not provided, uses `audio_get_audio_policy_config_file` function.
static sp<const AudioPolicyConfig> loadFromApmXmlConfigWithFallback(
@@ -140,6 +146,7 @@
AudioPolicyConfig() = default;
void augmentData();
+ status_t loadFromAidl(const media::AudioPolicyConfig& aidl);
status_t loadFromXml(const std::string& xmlFilePath, bool forVts);
std::string mSource; // Not kDefaultConfigSource. Empty source means an empty config.
diff --git a/services/audiopolicy/common/managerdefinitions/include/HwModule.h b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
index 436fcc1..e994758 100644
--- a/services/audiopolicy/common/managerdefinitions/include/HwModule.h
+++ b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
@@ -39,7 +39,8 @@
class HwModule : public RefBase
{
public:
- explicit HwModule(const char *name, uint32_t halVersionMajor = 0, uint32_t halVersionMinor = 0);
+ explicit HwModule(const char *name, uint32_t halVersionMajor, uint32_t halVersionMinor);
+ HwModule(const char *name, uint32_t halVersion = 0);
~HwModule();
const char *getName() const { return mName.string(); }
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp
index 42c76e2..38e2cc7 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp
@@ -19,6 +19,9 @@
#include <AudioPolicyConfig.h>
#include <IOProfile.h>
#include <Serializer.h>
+#include <hardware/audio.h>
+#include <media/AidlConversion.h>
+#include <media/AidlConversionUtil.h>
#include <media/AudioProfile.h>
#include <system/audio.h>
#include <system/audio_config.h>
@@ -26,6 +29,142 @@
namespace android {
+using media::audio::common::AudioIoFlags;
+using media::audio::common::AudioPortDeviceExt;
+using media::audio::common::AudioPortExt;
+
+namespace {
+
+ConversionResult<sp<PolicyAudioPort>>
+aidl2legacy_portId_PolicyAudioPort(int32_t portId,
+ const std::unordered_map<int32_t, sp<PolicyAudioPort>>& ports) {
+ if (auto it = ports.find(portId); it != ports.end()) {
+ return it->second;
+ }
+ return base::unexpected(BAD_VALUE);
+}
+
+ConversionResult<sp<AudioRoute>>
+aidl2legacy_AudioRoute(const media::AudioRoute& aidl,
+ const std::unordered_map<int32_t, sp<PolicyAudioPort>>& ports) {
+ auto legacy = sp<AudioRoute>::make(aidl.isExclusive ? AUDIO_ROUTE_MUX : AUDIO_ROUTE_MIX);
+ auto legacySink = VALUE_OR_RETURN(aidl2legacy_portId_PolicyAudioPort(aidl.sinkPortId, ports));
+ legacy->setSink(legacySink);
+ PolicyAudioPortVector legacySources;
+ for (int32_t portId : aidl.sourcePortIds) {
+ sp<PolicyAudioPort> legacyPort = VALUE_OR_RETURN(
+ aidl2legacy_portId_PolicyAudioPort(portId, ports));
+ legacySources.add(legacyPort);
+ }
+ legacy->setSources(legacySources);
+ legacySink->addRoute(legacy);
+ for (const auto& legacySource : legacySources) {
+ legacySource->addRoute(legacy);
+ }
+ return legacy;
+}
+
+status_t aidl2legacy_AudioHwModule_HwModule(const media::AudioHwModule& aidl,
+ sp<HwModule>* legacy,
+ DeviceVector* attachedInputDevices, DeviceVector* attachedOutputDevices,
+ sp<DeviceDescriptor>* defaultOutputDevice) {
+ *legacy = sp<HwModule>::make(aidl.name.c_str(), AUDIO_DEVICE_API_VERSION_CURRENT);
+ audio_module_handle_t legacyHandle = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_int32_t_audio_module_handle_t(aidl.handle));
+ (*legacy)->setHandle(legacyHandle);
+ IOProfileCollection mixPorts;
+ DeviceVector devicePorts;
+ const int defaultDeviceFlag = 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE;
+ std::unordered_map<int32_t, sp<PolicyAudioPort>> ports;
+ for (const auto& aidlPort : aidl.ports) {
+ const bool isInput = aidlPort.flags.getTag() == AudioIoFlags::input;
+ audio_port_v7 legacyPort = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_AudioPort_audio_port_v7(aidlPort, isInput));
+ // This conversion fills out both 'hal' and 'sys' parts.
+ media::AudioPortFw fwPort = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_port_v7_AudioPortFw(legacyPort));
+ // Since audio_port_v7 lacks some fields, for example, 'maxOpen/ActiveCount',
+ // replace the converted data with the actual data from the HAL.
+ fwPort.hal = aidlPort;
+ if (aidlPort.ext.getTag() == AudioPortExt::mix) {
+ auto mixPort = sp<IOProfile>::make("", AUDIO_PORT_ROLE_NONE);
+ RETURN_STATUS_IF_ERROR(mixPort->readFromParcelable(fwPort));
+ sortAudioProfiles(mixPort->getAudioProfiles());
+ mixPorts.add(mixPort);
+ ports.emplace(aidlPort.id, mixPort);
+ } else if (aidlPort.ext.getTag() == AudioPortExt::device) {
+ // In the legacy XML, device ports use 'tagName' instead of 'AudioPort.name'.
+ auto devicePort =
+ sp<DeviceDescriptor>::make(AUDIO_DEVICE_NONE, aidlPort.name);
+ RETURN_STATUS_IF_ERROR(devicePort->readFromParcelable(fwPort));
+ devicePort->setName("");
+ auto& profiles = devicePort->getAudioProfiles();
+ if (profiles.empty()) {
+ profiles.add(AudioProfile::createFullDynamic(gDynamicFormat));
+ } else {
+ sortAudioProfiles(profiles);
+ }
+ devicePorts.add(devicePort);
+ ports.emplace(aidlPort.id, devicePort);
+
+ if (const auto& deviceExt = aidlPort.ext.get<AudioPortExt::device>();
+ deviceExt.device.type.connection.empty()) { // Attached device
+ if (isInput) {
+ attachedInputDevices->add(devicePort);
+ } else {
+ attachedOutputDevices->add(devicePort);
+ if ((deviceExt.flags & defaultDeviceFlag) != 0) {
+ *defaultOutputDevice = devicePort;
+ }
+ }
+ }
+ } else {
+ return BAD_VALUE;
+ }
+ }
+ (*legacy)->setProfiles(mixPorts);
+ (*legacy)->setDeclaredDevices(devicePorts);
+ AudioRouteVector routes;
+ for (const auto& aidlRoute : aidl.routes) {
+ sp<AudioRoute> legacy = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioRoute(aidlRoute, ports));
+ routes.add(legacy);
+ }
+ (*legacy)->setRoutes(routes);
+ return OK;
+}
+
+status_t aidl2legacy_AudioHwModules_HwModuleCollection(
+ const std::vector<media::AudioHwModule>& aidl,
+ HwModuleCollection* legacyModules, DeviceVector* attachedInputDevices,
+ DeviceVector* attachedOutputDevices, sp<DeviceDescriptor>* defaultOutputDevice) {
+ for (const auto& aidlModule : aidl) {
+ sp<HwModule> legacy;
+ RETURN_STATUS_IF_ERROR(aidl2legacy_AudioHwModule_HwModule(aidlModule, &legacy,
+ attachedInputDevices, attachedOutputDevices, defaultOutputDevice));
+ legacyModules->add(legacy);
+ }
+ return OK;
+}
+
+using SurroundFormatFamily = AudioPolicyConfig::SurroundFormats::value_type;
+ConversionResult<SurroundFormatFamily>
+aidl2legacy_SurroundFormatFamily(const media::SurroundSoundConfig::SurroundFormatFamily& aidl) {
+ audio_format_t legacyPrimary = VALUE_OR_RETURN(
+ aidl2legacy_AudioFormatDescription_audio_format_t(aidl.primaryFormat));
+ std::unordered_set<audio_format_t> legacySubs = VALUE_OR_RETURN(
+ convertContainer<std::unordered_set<audio_format_t>>(
+ aidl.subFormats, aidl2legacy_AudioFormatDescription_audio_format_t));
+ return std::make_pair(legacyPrimary, legacySubs);
+}
+
+ConversionResult<AudioPolicyConfig::SurroundFormats>
+aidl2legacy_SurroundSoundConfig_SurroundFormats(const media::SurroundSoundConfig& aidl) {
+ return convertContainer<AudioPolicyConfig::SurroundFormats>(aidl.formatFamilies,
+ aidl2legacy_SurroundFormatFamily);
+};
+
+} // namespace
+
// static
sp<const AudioPolicyConfig> AudioPolicyConfig::createDefault() {
auto config = sp<AudioPolicyConfig>::make();
@@ -34,6 +173,16 @@
}
// static
+sp<const AudioPolicyConfig> AudioPolicyConfig::loadFromApmAidlConfigWithFallback(
+ const media::AudioPolicyConfig& aidl) {
+ auto config = sp<AudioPolicyConfig>::make();
+ if (status_t status = config->loadFromAidl(aidl); status == NO_ERROR) {
+ return config;
+ }
+ return createDefault();
+}
+
+// static
sp<const AudioPolicyConfig> AudioPolicyConfig::loadFromApmXmlConfigWithFallback(
const std::string& xmlFilePath) {
const std::string filePath =
@@ -100,6 +249,22 @@
}
}
+status_t AudioPolicyConfig::loadFromAidl(const media::AudioPolicyConfig& aidl) {
+ RETURN_STATUS_IF_ERROR(aidl2legacy_AudioHwModules_HwModuleCollection(aidl.modules,
+ &mHwModules, &mInputDevices, &mOutputDevices, &mDefaultOutputDevice));
+ mIsCallScreenModeSupported = std::find(aidl.supportedModes.begin(), aidl.supportedModes.end(),
+ media::audio::common::AudioMode::CALL_SCREEN) != aidl.supportedModes.end();
+ mSurroundFormats = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_SurroundSoundConfig_SurroundFormats(aidl.surroundSoundConfig));
+ // TODO(b/205884982): Remove after landing aosp/2353423.
+ if (mSurroundFormats.empty()) {
+ setDefaultSurroundFormats();
+ }
+ mSource = kAidlConfigSource;
+ // No need to augmentData() as AIDL HAL must provide correct mic addresses.
+ return NO_ERROR;
+}
+
status_t AudioPolicyConfig::loadFromXml(const std::string& xmlFilePath, bool forVts) {
if (xmlFilePath.empty()) {
ALOGE("Audio policy configuration file name is empty");
@@ -131,7 +296,8 @@
mOutputDevices.add(mDefaultOutputDevice);
mInputDevices.add(defaultInputDevice);
- sp<HwModule> module = new HwModule(AUDIO_HARDWARE_MODULE_ID_PRIMARY, 2 /*halVersionMajor*/);
+ sp<HwModule> module = new HwModule(
+ AUDIO_HARDWARE_MODULE_ID_PRIMARY, AUDIO_DEVICE_API_VERSION_2_0);
mHwModules.add(module);
sp<OutputProfile> outProfile = new OutputProfile("primary");
diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
index 418b7eb..5f14ee4 100644
--- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
@@ -33,6 +33,13 @@
setHalVersion(halVersionMajor, halVersionMinor);
}
+HwModule::HwModule(const char *name, uint32_t halVersion)
+ : mName(String8(name)),
+ mHandle(AUDIO_MODULE_HANDLE_NONE),
+ mHalVersion(halVersion)
+{
+}
+
HwModule::~HwModule()
{
for (size_t i = 0; i < mOutputProfiles.size(); i++) {
diff --git a/services/audiopolicy/engine/common/Android.bp b/services/audiopolicy/engine/common/Android.bp
index 50c5eab..6c46c54 100644
--- a/services/audiopolicy/engine/common/Android.bp
+++ b/services/audiopolicy/engine/common/Android.bp
@@ -51,10 +51,10 @@
"libaudiopolicyengine_common_headers",
],
static_libs: [
- "libaudiopolicycomponents",
"libaudiopolicyengine_config",
],
shared_libs: [
"libaudiofoundation",
+ "libaudiopolicycomponents",
],
}
diff --git a/services/audiopolicy/engine/common/include/EngineBase.h b/services/audiopolicy/engine/common/include/EngineBase.h
index abacd3c..5f4080e 100644
--- a/services/audiopolicy/engine/common/include/EngineBase.h
+++ b/services/audiopolicy/engine/common/include/EngineBase.h
@@ -16,6 +16,9 @@
#pragma once
+#include <functional>
+
+#include <android/media/audio/common/AudioHalEngineConfig.h>
#include <EngineConfig.h>
#include <EngineInterface.h>
#include <ProductStrategy.h>
@@ -110,6 +113,9 @@
status_t getDevicesForRoleAndStrategy(product_strategy_t strategy, device_role_t role,
AudioDeviceTypeAddrVector &devices) const override;
+ engineConfig::ParsingResult loadAudioPolicyEngineConfig(
+ const media::audio::common::AudioHalEngineConfig& aidlConfig);
+
engineConfig::ParsingResult loadAudioPolicyEngineConfig(const std::string& xmlFilePath = "");
const ProductStrategyMap &getProductStrategies() const { return mProductStrategies; }
@@ -167,6 +173,8 @@
void updateDeviceSelectionCache() override;
private:
+ engineConfig::ParsingResult processParsingResult(engineConfig::ParsingResult&& rawResult);
+
/**
* Get media devices as the given role
*
diff --git a/services/audiopolicy/engine/common/src/EngineBase.cpp b/services/audiopolicy/engine/common/src/EngineBase.cpp
index fe5cd9f..dcdf693 100644
--- a/services/audiopolicy/engine/common/src/EngineBase.cpp
+++ b/services/audiopolicy/engine/common/src/EngineBase.cpp
@@ -115,10 +115,53 @@
return PRODUCT_STRATEGY_NONE;
}
+engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig(
+ const media::audio::common::AudioHalEngineConfig& aidlConfig)
+{
+ engineConfig::ParsingResult result = engineConfig::convert(aidlConfig);
+ if (result.parsedConfig == nullptr) {
+ ALOGE("%s: There was an error parsing AIDL data", __func__);
+ result = {std::make_unique<engineConfig::Config>(gDefaultEngineConfig), 1};
+ } else {
+ // It is allowed for the HAL to return an empty list of strategies.
+ if (result.parsedConfig->productStrategies.empty()) {
+ result.parsedConfig->productStrategies = gDefaultEngineConfig.productStrategies;
+ }
+ }
+ return processParsingResult(std::move(result));
+}
+
engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig(const std::string& xmlFilePath)
{
+ auto fileExists = [](const char* path) {
+ struct stat fileStat;
+ return stat(path, &fileStat) == 0 && S_ISREG(fileStat.st_mode);
+ };
+ const std::string filePath = xmlFilePath.empty() ? engineConfig::DEFAULT_PATH : xmlFilePath;
+ engineConfig::ParsingResult result =
+ fileExists(filePath.c_str()) ?
+ engineConfig::parse(filePath.c_str()) : engineConfig::ParsingResult{};
+ if (result.parsedConfig == nullptr) {
+ ALOGD("%s: No configuration found, using default matching phone experience.", __FUNCTION__);
+ engineConfig::Config config = gDefaultEngineConfig;
+ android::status_t ret = engineConfig::parseLegacyVolumes(config.volumeGroups);
+ result = {std::make_unique<engineConfig::Config>(config),
+ static_cast<size_t>(ret == NO_ERROR ? 0 : 1)};
+ } else {
+ // Append for internal use only volume groups (e.g. rerouting/patch)
+ result.parsedConfig->volumeGroups.insert(
+ std::end(result.parsedConfig->volumeGroups),
+ std::begin(gSystemVolumeGroups), std::end(gSystemVolumeGroups));
+ }
+ ALOGE_IF(result.nbSkippedElement != 0, "skipped %zu elements", result.nbSkippedElement);
+ return processParsingResult(std::move(result));
+}
+
+engineConfig::ParsingResult EngineBase::processParsingResult(
+ engineConfig::ParsingResult&& rawResult)
+{
auto loadVolumeConfig = [](auto &volumeGroups, auto &volumeConfig) {
- // Ensure name unicity to prevent duplicate
+ // Ensure volume group name uniqueness.
LOG_ALWAYS_FATAL_IF(std::any_of(std::begin(volumeGroups), std::end(volumeGroups),
[&volumeConfig](const auto &volumeGroup) {
return volumeConfig.name == volumeGroup.second->getName(); }),
@@ -158,42 +201,21 @@
});
return iter != end(volumeGroups);
};
- auto fileExists = [](const char* path) {
- struct stat fileStat;
- return stat(path, &fileStat) == 0 && S_ISREG(fileStat.st_mode);
- };
- const std::string filePath = xmlFilePath.empty() ? engineConfig::DEFAULT_PATH : xmlFilePath;
- auto result = fileExists(filePath.c_str()) ?
- engineConfig::parse(filePath.c_str()) : engineConfig::ParsingResult{};
- if (result.parsedConfig == nullptr) {
- ALOGD("%s: No configuration found, using default matching phone experience.", __FUNCTION__);
- engineConfig::Config config = gDefaultEngineConfig;
- android::status_t ret = engineConfig::parseLegacyVolumes(config.volumeGroups);
- result = {std::make_unique<engineConfig::Config>(config),
- static_cast<size_t>(ret == NO_ERROR ? 0 : 1)};
- } else {
- // Append for internal use only volume groups (e.g. rerouting/patch)
- result.parsedConfig->volumeGroups.insert(
- std::end(result.parsedConfig->volumeGroups),
- std::begin(gSystemVolumeGroups), std::end(gSystemVolumeGroups));
- }
+ auto result = std::move(rawResult);
// Append for internal use only strategies (e.g. rerouting/patch)
result.parsedConfig->productStrategies.insert(
std::end(result.parsedConfig->productStrategies),
std::begin(gOrderedSystemStrategies), std::end(gOrderedSystemStrategies));
-
- ALOGE_IF(result.nbSkippedElement != 0, "skipped %zu elements", result.nbSkippedElement);
-
engineConfig::VolumeGroup defaultVolumeConfig;
engineConfig::VolumeGroup defaultSystemVolumeConfig;
for (auto &volumeConfig : result.parsedConfig->volumeGroups) {
// save default volume config for streams not defined in configuration
- if (volumeConfig.name.compare("AUDIO_STREAM_MUSIC") == 0) {
+ if (volumeConfig.name.compare(audio_stream_type_to_string(AUDIO_STREAM_MUSIC)) == 0) {
defaultVolumeConfig = volumeConfig;
}
- if (volumeConfig.name.compare("AUDIO_STREAM_PATCH") == 0) {
+ if (volumeConfig.name.compare(audio_stream_type_to_string(AUDIO_STREAM_PATCH)) == 0) {
defaultSystemVolumeConfig = volumeConfig;
}
loadVolumeConfig(mVolumeGroups, volumeConfig);
diff --git a/services/audiopolicy/engine/config/Android.bp b/services/audiopolicy/engine/config/Android.bp
index 459cc78..12597de 100644
--- a/services/audiopolicy/engine/config/Android.bp
+++ b/services/audiopolicy/engine/config/Android.bp
@@ -22,11 +22,13 @@
"-Wextra",
],
shared_libs: [
- "libmedia_helper",
- "libxml2",
- "libutils",
- "liblog",
+ "libaudio_aidl_conversion_common_cpp",
+ "libaudiopolicycomponents",
"libcutils",
+ "liblog",
+ "libmedia_helper",
+ "libutils",
+ "libxml2",
],
header_libs: [
"libaudio_system_headers",
diff --git a/services/audiopolicy/engine/config/include/EngineConfig.h b/services/audiopolicy/engine/config/include/EngineConfig.h
index 8036eea..d3f701a 100644
--- a/services/audiopolicy/engine/config/include/EngineConfig.h
+++ b/services/audiopolicy/engine/config/include/EngineConfig.h
@@ -16,10 +16,11 @@
#pragma once
-#include <system/audio.h>
-
#include <string>
#include <vector>
+
+#include <android/media/audio/common/AudioHalEngineConfig.h>
+#include <system/audio.h>
#include <utils/Errors.h>
struct _xmlNode;
@@ -110,6 +111,7 @@
*/
ParsingResult parse(const char* path = DEFAULT_PATH);
android::status_t parseLegacyVolumes(VolumeGroups &volumeGroups);
+ParsingResult convert(const ::android::media::audio::common::AudioHalEngineConfig& aidlConfig);
// Exposed for testing.
android::status_t parseLegacyVolumeFile(const char* path, VolumeGroups &volumeGroups);
diff --git a/services/audiopolicy/engine/config/src/EngineConfig.cpp b/services/audiopolicy/engine/config/src/EngineConfig.cpp
index ac117f0..ca78ce7 100644
--- a/services/audiopolicy/engine/config/src/EngineConfig.cpp
+++ b/services/audiopolicy/engine/config/src/EngineConfig.cpp
@@ -14,26 +14,30 @@
* limitations under the License.
*/
+#include <cstdint>
+#include <istream>
+#include <map>
+#include <sstream>
+#include <stdarg.h>
+#include <string>
+#include <string>
+#include <vector>
+
#define LOG_TAG "APM::AudioPolicyEngine/Config"
//#define LOG_NDEBUG 0
#include "EngineConfig.h"
+#include <TypeConverter.h>
+#include <Volume.h>
#include <cutils/properties.h>
+#include <libxml/parser.h>
+#include <libxml/xinclude.h>
+#include <media/AidlConversion.h>
+#include <media/AidlConversionUtil.h>
#include <media/TypeConverter.h>
#include <media/convert.h>
#include <system/audio_config.h>
#include <utils/Log.h>
-#include <libxml/parser.h>
-#include <libxml/xinclude.h>
-#include <string>
-#include <vector>
-#include <map>
-#include <sstream>
-#include <istream>
-
-#include <cstdint>
-#include <stdarg.h>
-#include <string>
namespace android {
@@ -45,6 +49,85 @@
static const char *const gReferenceElementName = "reference";
static const char *const gReferenceAttributeName = "name";
+namespace {
+
+ConversionResult<AttributesGroup> aidl2legacy_AudioHalAttributeGroup_AttributesGroup(
+ const media::audio::common::AudioHalAttributesGroup& aidl) {
+ AttributesGroup legacy;
+ legacy.stream = VALUE_OR_RETURN(
+ aidl2legacy_AudioStreamType_audio_stream_type_t(aidl.streamType));
+ legacy.volumeGroup = aidl.volumeGroupName;
+ legacy.attributesVect = VALUE_OR_RETURN(convertContainer<AttributesVector>(
+ aidl.attributes, aidl2legacy_AudioAttributes_audio_attributes_t));
+ return legacy;
+}
+
+ConversionResult<ProductStrategy> aidl2legacy_AudioHalProductStrategy_ProductStrategy(
+ const media::audio::common::AudioHalProductStrategy& aidl) {
+ ProductStrategy legacy;
+ legacy.name = "strategy_" + std::to_string(aidl.id);
+ legacy.attributesGroups = VALUE_OR_RETURN(convertContainer<AttributesGroups>(
+ aidl.attributesGroups,
+ aidl2legacy_AudioHalAttributeGroup_AttributesGroup));
+ return legacy;
+}
+
+ConversionResult<std::string> legacy_device_category_to_string(device_category legacy) {
+ std::string s;
+ if (DeviceCategoryConverter::toString(legacy, s)) {
+ return s;
+ }
+ return base::unexpected(BAD_VALUE);
+}
+
+ConversionResult<std::string> aidl2legacy_DeviceCategory(
+ const media::audio::common::AudioHalVolumeCurve::DeviceCategory aidl) {
+ using DeviceCategory = media::audio::common::AudioHalVolumeCurve::DeviceCategory;
+ switch (aidl) {
+ case DeviceCategory::HEADSET:
+ return legacy_device_category_to_string(DEVICE_CATEGORY_HEADSET);
+ case DeviceCategory::SPEAKER:
+ return legacy_device_category_to_string(DEVICE_CATEGORY_SPEAKER);
+ case DeviceCategory::EARPIECE:
+ return legacy_device_category_to_string(DEVICE_CATEGORY_EARPIECE);
+ case DeviceCategory::EXT_MEDIA:
+ return legacy_device_category_to_string(DEVICE_CATEGORY_EXT_MEDIA);
+ case DeviceCategory::HEARING_AID:
+ return legacy_device_category_to_string(DEVICE_CATEGORY_HEARING_AID);
+ }
+ return base::unexpected(BAD_VALUE);
+}
+
+ConversionResult<CurvePoint> aidl2legacy_AudioHalCurvePoint_CurvePoint(
+ const media::audio::common::AudioHalVolumeCurve::CurvePoint& aidl) {
+ CurvePoint legacy;
+ legacy.index = VALUE_OR_RETURN(convertIntegral<int>(aidl.index));
+ legacy.attenuationInMb = aidl.attenuationMb;
+ return legacy;
+}
+
+ConversionResult<VolumeCurve> aidl2legacy_AudioHalVolumeCurve_VolumeCurve(
+ const media::audio::common::AudioHalVolumeCurve& aidl) {
+ VolumeCurve legacy;
+ legacy.deviceCategory = VALUE_OR_RETURN(aidl2legacy_DeviceCategory(aidl.deviceCategory));
+ legacy.curvePoints = VALUE_OR_RETURN(convertContainer<CurvePoints>(
+ aidl.curvePoints, aidl2legacy_AudioHalCurvePoint_CurvePoint));
+ return legacy;
+}
+
+ConversionResult<VolumeGroup> aidl2legacy_AudioHalVolumeGroup_VolumeGroup(
+ const media::audio::common::AudioHalVolumeGroup& aidl) {
+ VolumeGroup legacy;
+ legacy.name = aidl.name;
+ legacy.indexMin = aidl.minIndex;
+ legacy.indexMax = aidl.maxIndex;
+ legacy.volumeCurves = VALUE_OR_RETURN(convertContainer<VolumeCurves>(
+ aidl.volumeCurves, aidl2legacy_AudioHalVolumeCurve_VolumeCurve));
+ return legacy;
+}
+
+} // namespace
+
template<typename E, typename C>
struct BaseSerializerTraits {
typedef E Element;
@@ -724,5 +807,25 @@
}
}
+ParsingResult convert(const ::android::media::audio::common::AudioHalEngineConfig& aidlConfig) {
+ auto config = std::make_unique<engineConfig::Config>();
+ config->version = 1.0f;
+ if (auto conv = convertContainer<engineConfig::ProductStrategies>(
+ aidlConfig.productStrategies,
+ aidl2legacy_AudioHalProductStrategy_ProductStrategy); conv.ok()) {
+ config->productStrategies = std::move(conv.value());
+ } else {
+ return ParsingResult{};
+ }
+ if (auto conv = convertContainer<engineConfig::VolumeGroups>(
+ aidlConfig.volumeGroups,
+ aidl2legacy_AudioHalVolumeGroup_VolumeGroup); conv.ok()) {
+ config->volumeGroups = std::move(conv.value());
+ } else {
+ return ParsingResult{};
+ }
+ return {.parsedConfig=std::move(config), .nbSkippedElement=0};
+ }
+
} // namespace engineConfig
} // namespace android
diff --git a/services/audiopolicy/engine/config/tests/Android.bp b/services/audiopolicy/engine/config/tests/Android.bp
index 5791f17..5d1aa16 100644
--- a/services/audiopolicy/engine/config/tests/Android.bp
+++ b/services/audiopolicy/engine/config/tests/Android.bp
@@ -11,6 +11,7 @@
name: "audiopolicy_engineconfig_tests",
shared_libs: [
+ "libaudiopolicycomponents",
"libbase",
"liblog",
"libmedia_helper",
diff --git a/services/audiopolicy/engine/interface/EngineInterface.h b/services/audiopolicy/engine/interface/EngineInterface.h
index 9c156ab..5c37409 100644
--- a/services/audiopolicy/engine/interface/EngineInterface.h
+++ b/services/audiopolicy/engine/interface/EngineInterface.h
@@ -20,6 +20,7 @@
#include <utility>
#include <AudioPolicyManagerObserver.h>
+#include <android/media/audio/common/AudioHalEngineConfig.h>
#include <media/AudioProductStrategy.h>
#include <media/AudioVolumeGroup.h>
#include <IVolumeCurves.h>
@@ -47,6 +48,14 @@
{
public:
/**
+ * Loads the engine configuration from AIDL configuration data.
+ * If loading failed, tries to fall back to some default configuration. If fallback
+ * is impossible, returns an error.
+ */
+ virtual status_t loadFromHalConfigWithFallback(
+ const media::audio::common::AudioHalEngineConfig& config) = 0;
+
+ /**
* Loads the engine configuration from the specified or the default config file.
* If loading failed, tries to fall back to some default configuration. If fallback
* is impossible, returns an error.
diff --git a/services/audiopolicy/engineconfigurable/Android.bp b/services/audiopolicy/engineconfigurable/Android.bp
index dc8d9cf..eb2e2f4 100644
--- a/services/audiopolicy/engineconfigurable/Android.bp
+++ b/services/audiopolicy/engineconfigurable/Android.bp
@@ -35,14 +35,15 @@
"libaudiopolicyengineconfigurable_interface_headers",
],
static_libs: [
- "libaudiopolicycomponents",
"libaudiopolicyengine_common",
"libaudiopolicyengine_config",
"libaudiopolicyengineconfigurable_pfwwrapper",
],
shared_libs: [
+ "libaudio_aidl_conversion_common_cpp",
"libaudiofoundation",
+ "libaudiopolicycomponents",
"libbase",
"liblog",
"libcutils",
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.bp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.bp
index 0398fc7..f7159c5 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.bp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.bp
@@ -31,11 +31,11 @@
"libaudiopolicyengineconfigurable_interface_headers",
],
static_libs: [
- "libaudiopolicycomponents",
"libaudiopolicyengine_common",
"libpfw_utility",
],
shared_libs: [
+ "libaudiopolicycomponents",
"libaudiopolicyengineconfigurable",
"liblog",
"libutils",
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.cpp b/services/audiopolicy/engineconfigurable/src/Engine.cpp
index 44f1d7c..f07ce82 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Engine.cpp
@@ -70,6 +70,12 @@
{
}
+status_t Engine::loadFromHalConfigWithFallback(
+ const media::audio::common::AudioHalEngineConfig& config __unused) {
+ // b/242678729. Need to implement for the configurable engine.
+ return INVALID_OPERATION;
+}
+
status_t Engine::loadFromXmlConfigWithFallback(const std::string& xmlFilePath)
{
status_t loadResult = loadAudioPolicyEngineConfig(xmlFilePath);
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.h b/services/audiopolicy/engineconfigurable/src/Engine.h
index d5083f0..903ab34 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.h
+++ b/services/audiopolicy/engineconfigurable/src/Engine.h
@@ -41,12 +41,15 @@
///
/// from EngineInterface
///
- android::status_t loadFromXmlConfigWithFallback(const std::string& xmlFilePath = "") override;
+ status_t loadFromHalConfigWithFallback(
+ const media::audio::common::AudioHalEngineConfig& config) override;
+
+ status_t loadFromXmlConfigWithFallback(const std::string& xmlFilePath = "") override;
///
/// from EngineBase
///
- android::status_t initCheck() override;
+ status_t initCheck() override;
status_t setPhoneState(audio_mode_t mode) override;
@@ -56,8 +59,8 @@
audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage) const override;
- android::status_t setDeviceConnectionState(const sp<DeviceDescriptor> devDesc,
- audio_policy_dev_state_t state) override;
+ status_t setDeviceConnectionState(const sp<DeviceDescriptor> devDesc,
+ audio_policy_dev_state_t state) override;
DeviceVector getOutputDevicesForAttributes(const audio_attributes_t &attr,
const sp<DeviceDescriptor> &preferedDevice = nullptr,
diff --git a/services/audiopolicy/enginedefault/Android.bp b/services/audiopolicy/enginedefault/Android.bp
index 4671fe9..7d4ccab 100644
--- a/services/audiopolicy/enginedefault/Android.bp
+++ b/services/audiopolicy/enginedefault/Android.bp
@@ -25,12 +25,13 @@
"libaudiopolicyengine_interface_headers",
],
static_libs: [
- "libaudiopolicycomponents",
"libaudiopolicyengine_common",
"libaudiopolicyengine_config",
],
shared_libs: [
+ "libaudio_aidl_conversion_common_cpp",
"libaudiofoundation",
+ "libaudiopolicycomponents",
"libbase",
"liblog",
"libcutils",
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index 0fa0e0e..e2f42da 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -35,10 +35,7 @@
#include <utils/String8.h>
#include <utils/Log.h>
-namespace android
-{
-namespace audio_policy
-{
+namespace android::audio_policy {
struct legacy_strategy_map { const char *name; legacy_strategy id; };
static const std::vector<legacy_strategy_map>& getLegacyStrategy() {
@@ -59,8 +56,18 @@
return legacyStrategy;
}
+status_t Engine::loadFromHalConfigWithFallback(
+ const media::audio::common::AudioHalEngineConfig& aidlConfig) {
+ return loadWithFallback(aidlConfig);
+}
+
status_t Engine::loadFromXmlConfigWithFallback(const std::string& xmlFilePath) {
- auto result = EngineBase::loadAudioPolicyEngineConfig(xmlFilePath);
+ return loadWithFallback(xmlFilePath);
+}
+
+template<typename T>
+status_t Engine::loadWithFallback(const T& configSource) {
+ auto result = EngineBase::loadAudioPolicyEngineConfig(configSource);
ALOGE_IF(result.nbSkippedElement != 0,
"Policy Engine configuration is partially invalid, skipped %zu elements",
result.nbSkippedElement);
@@ -73,6 +80,7 @@
return OK;
}
+
status_t Engine::setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config)
{
switch(usage) {
@@ -794,5 +802,4 @@
AUDIO_FORMAT_DEFAULT);
}
-} // namespace audio_policy
-} // namespace android
+} // namespace android::audio_policy
diff --git a/services/audiopolicy/enginedefault/src/Engine.h b/services/audiopolicy/enginedefault/src/Engine.h
index fde9802..66225a1 100644
--- a/services/audiopolicy/enginedefault/src/Engine.h
+++ b/services/audiopolicy/enginedefault/src/Engine.h
@@ -47,10 +47,14 @@
public:
Engine() = default;
virtual ~Engine() = default;
+ Engine(const Engine &object) = delete;
+ Engine &operator=(const Engine &object) = delete;
///
/// from EngineInterface
///
+ status_t loadFromHalConfigWithFallback(
+ const media::audio::common::AudioHalEngineConfig& config) override;
status_t loadFromXmlConfigWithFallback(const std::string& xmlFilePath = "") override;
private:
@@ -78,9 +82,8 @@
DeviceVector getDevicesForProductStrategy(product_strategy_t strategy) const override;
private:
- /* Copy facilities are put private to disable copy. */
- Engine(const Engine &object);
- Engine &operator=(const Engine &object);
+ template<typename T>
+ status_t loadWithFallback(const T& configSource);
status_t setDefaultDevice(audio_devices_t device);
diff --git a/services/audiopolicy/fuzzer/Android.bp b/services/audiopolicy/fuzzer/Android.bp
index 621f643..c4b3751 100644
--- a/services/audiopolicy/fuzzer/Android.bp
+++ b/services/audiopolicy/fuzzer/Android.bp
@@ -38,6 +38,7 @@
"capture_state_listener-aidl-cpp",
"libaudioclient",
"libaudiofoundation",
+ "libaudiopolicycomponents",
"libbase",
"libcutils",
"libhidlbase",
@@ -54,7 +55,6 @@
],
static_libs: [
"android.hardware.audio.common@7.0-enums",
- "libaudiopolicycomponents",
],
header_libs: [
"libaudiopolicycommon",
diff --git a/services/audiopolicy/managerdefault/Android.bp b/services/audiopolicy/managerdefault/Android.bp
index 6e34eb0..a1785da 100644
--- a/services/audiopolicy/managerdefault/Android.bp
+++ b/services/audiopolicy/managerdefault/Android.bp
@@ -23,6 +23,7 @@
shared_libs: [
"libaudiofoundation",
+ "libaudiopolicycomponents",
"libcutils",
"libdl",
"libutils",
@@ -49,8 +50,6 @@
"libaudiopolicymanager_interface_headers",
],
- static_libs: ["libaudiopolicycomponents"],
-
cflags: [
"-Wall",
"-Werror",
diff --git a/services/audiopolicy/managerdefault/EngineLibrary.cpp b/services/audiopolicy/managerdefault/EngineLibrary.cpp
index 939fbc5..ab77941 100644
--- a/services/audiopolicy/managerdefault/EngineLibrary.cpp
+++ b/services/audiopolicy/managerdefault/EngineLibrary.cpp
@@ -40,6 +40,23 @@
return engine;
}
+EngineInstance loadApmEngineLibraryAndCreateEngine(const std::string& librarySuffix,
+ const media::audio::common::AudioHalEngineConfig& config)
+{
+ auto engLib = EngineLibrary::load(librarySuffix);
+ if (!engLib) {
+ ALOGE("%s: Failed to load the engine library, suffix \"%s\"",
+ __func__, librarySuffix.c_str());
+ return nullptr;
+ }
+ auto engine = engLib->createEngineUsingHalConfig(config);
+ if (engine == nullptr) {
+ ALOGE("%s: Failed to instantiate the APM engine", __func__);
+ return nullptr;
+ }
+ return engine;
+}
+
// static
std::shared_ptr<EngineLibrary> EngineLibrary::load(const std::string& librarySuffix)
{
@@ -53,7 +70,8 @@
close();
}
-EngineInstance EngineLibrary::createEngineUsingXmlConfig(const std::string& xmlFilePath) {
+EngineInstance EngineLibrary::createEngineUsingXmlConfig(const std::string& xmlFilePath)
+{
auto instance = createEngine();
if (instance != nullptr) {
if (status_t status = instance->loadFromXmlConfigWithFallback(xmlFilePath);
@@ -67,6 +85,21 @@
return nullptr;
}
+EngineInstance EngineLibrary::createEngineUsingHalConfig(
+ const media::audio::common::AudioHalEngineConfig& config)
+{
+ auto instance = createEngine();
+ if (instance != nullptr) {
+ if (status_t status = instance->loadFromHalConfigWithFallback(config); status == OK) {
+ return instance;
+ } else {
+ ALOGE("%s: loading of the engine config with HAL configuration \"%s\" failed: %d",
+ __func__, config.toString().c_str(), status);
+ }
+ }
+ return nullptr;
+}
+
bool EngineLibrary::init(std::string libraryPath)
{
mLibraryHandle = dlopen(libraryPath.c_str(), 0);
diff --git a/services/audiopolicy/managerdefault/EngineLibrary.h b/services/audiopolicy/managerdefault/EngineLibrary.h
index dc138a1..4710e34 100644
--- a/services/audiopolicy/managerdefault/EngineLibrary.h
+++ b/services/audiopolicy/managerdefault/EngineLibrary.h
@@ -21,6 +21,7 @@
#include <string>
#include <EngineInterface.h>
+#include <android/media/audio/common/AudioHalEngineConfig.h>
namespace android {
@@ -28,6 +29,8 @@
EngineInstance loadApmEngineLibraryAndCreateEngine(const std::string& librarySuffix,
const std::string& configXmlFilePath = "");
+EngineInstance loadApmEngineLibraryAndCreateEngine(const std::string& librarySuffix,
+ const media::audio::common::AudioHalEngineConfig& config);
class EngineLibrary : public std::enable_shared_from_this<EngineLibrary> {
public:
@@ -40,6 +43,8 @@
EngineLibrary& operator=(EngineLibrary&&) = delete;
EngineInstance createEngineUsingXmlConfig(const std::string& xmlFilePath);
+ EngineInstance createEngineUsingHalConfig(
+ const media::audio::common::AudioHalEngineConfig& config);
private:
EngineLibrary() = default;
diff --git a/services/audiopolicy/service/Android.bp b/services/audiopolicy/service/Android.bp
index 8c541f6..734bf9e 100644
--- a/services/audiopolicy/service/Android.bp
+++ b/services/audiopolicy/service/Android.bp
@@ -35,6 +35,7 @@
"libaudiofoundation",
"libaudiohal",
"libaudiopolicy",
+ "libaudiopolicycomponents",
"libaudiopolicymanagerdefault",
"libaudioutils",
"libbinder",
@@ -65,7 +66,6 @@
],
static_libs: [
- "libaudiopolicycomponents",
"framework-permission-aidl-cpp",
],
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 930631a..50c2c46 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -180,10 +180,23 @@
static AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
{
- auto config = AudioPolicyConfig::loadFromApmXmlConfigWithFallback(); // This can't fail.
- AudioPolicyManager *apm = new AudioPolicyManager(
- config, loadApmEngineLibraryAndCreateEngine(config->getEngineLibraryNameSuffix()),
- clientInterface);
+ AudioPolicyManager *apm = nullptr;
+ media::AudioPolicyConfig apmConfig;
+ if (status_t status = clientInterface->getAudioPolicyConfig(&apmConfig); status == OK) {
+ auto config = AudioPolicyConfig::loadFromApmAidlConfigWithFallback(apmConfig);
+ LOG_ALWAYS_FATAL_IF(config->getEngineLibraryNameSuffix() !=
+ AudioPolicyConfig::kDefaultEngineLibraryNameSuffix,
+ "Only default engine is currently supported with the AIDL HAL");
+ apm = new AudioPolicyManager(config,
+ loadApmEngineLibraryAndCreateEngine(
+ config->getEngineLibraryNameSuffix(), apmConfig.engineConfig),
+ clientInterface);
+ } else {
+ auto config = AudioPolicyConfig::loadFromApmXmlConfigWithFallback(); // This can't fail.
+ apm = new AudioPolicyManager(config,
+ loadApmEngineLibraryAndCreateEngine(config->getEngineLibraryNameSuffix()),
+ clientInterface);
+ }
status_t status = apm->initialize();
if (status != NO_ERROR) {
delete apm;
diff --git a/services/audiopolicy/tests/Android.bp b/services/audiopolicy/tests/Android.bp
index 8499c1c..b9ee8dd 100644
--- a/services/audiopolicy/tests/Android.bp
+++ b/services/audiopolicy/tests/Android.bp
@@ -74,6 +74,7 @@
"libaudioclient",
"libaudioclient_aidl_conversion",
"libaudiofoundation",
+ "libaudiopolicycomponents",
"libaudiopolicymanagerdefault",
"libcutils",
"liblog",
@@ -85,8 +86,6 @@
"libxml2",
],
- static_libs: ["libaudiopolicycomponents"],
-
header_libs: [
"libaudiopolicyengine_interface_headers",
"libaudiopolicymanager_interface_headers",