Merge changes from topic "CAP_AIDL_AUDIO_HAL" into main

* changes:
  Add missing Cap Settings aidl support and helper
  Migrate forced config and for force use to android.media.audio.common.types
This commit is contained in:
Mikhail Naganov
2024-09-05 20:54:26 +00:00
committed by Gerrit Code Review
22 changed files with 2021 additions and 86 deletions

View File

@@ -32,10 +32,12 @@ cc_library {
header_libs: [
"libbase_headers",
"libsystem_headers",
"libutils_headers",
],
export_header_lib_headers: [
"libbase_headers",
"libsystem_headers",
"libutils_headers",
],
srcs: [
"StreamWorker.cpp",

View File

@@ -29,8 +29,10 @@
#include <aidl/android/media/audio/common/AudioIoFlags.h>
#include <aidl/android/media/audio/common/AudioMode.h>
#include <aidl/android/media/audio/common/AudioOutputFlags.h>
#include <aidl/android/media/audio/common/AudioPolicyForcedConfig.h>
#include <aidl/android/media/audio/common/PcmType.h>
#include <android/binder_auto_utils.h>
#include <utils/FastStrcmp.h>
namespace ndk {
@@ -58,6 +60,36 @@ constexpr std::array<::aidl::android::media::audio::common::AudioMode, 5> kValid
::aidl::android::media::audio::common::AudioMode::CALL_SCREEN,
};
constexpr std::array<::aidl::android::media::audio::common::AudioPolicyForcedConfig, 17>
kValidAudioPolicyForcedConfig = {
::aidl::android::media::audio::common::AudioPolicyForcedConfig::NONE,
::aidl::android::media::audio::common::AudioPolicyForcedConfig::SPEAKER,
::aidl::android::media::audio::common::AudioPolicyForcedConfig::HEADPHONES,
::aidl::android::media::audio::common::AudioPolicyForcedConfig::BT_SCO,
::aidl::android::media::audio::common::AudioPolicyForcedConfig::BT_A2DP,
::aidl::android::media::audio::common::AudioPolicyForcedConfig::WIRED_ACCESSORY,
::aidl::android::media::audio::common::AudioPolicyForcedConfig::BT_CAR_DOCK,
::aidl::android::media::audio::common::AudioPolicyForcedConfig::BT_DESK_DOCK,
::aidl::android::media::audio::common::AudioPolicyForcedConfig::ANALOG_DOCK,
::aidl::android::media::audio::common::AudioPolicyForcedConfig::DIGITAL_DOCK,
::aidl::android::media::audio::common::AudioPolicyForcedConfig::NO_BT_A2DP,
::aidl::android::media::audio::common::AudioPolicyForcedConfig::SYSTEM_ENFORCED,
::aidl::android::media::audio::common::AudioPolicyForcedConfig::
HDMI_SYSTEM_AUDIO_ENFORCED,
::aidl::android::media::audio::common::AudioPolicyForcedConfig::
ENCODED_SURROUND_NEVER,
::aidl::android::media::audio::common::AudioPolicyForcedConfig::
ENCODED_SURROUND_ALWAYS,
::aidl::android::media::audio::common::AudioPolicyForcedConfig::
ENCODED_SURROUND_MANUAL,
::aidl::android::media::audio::common::AudioPolicyForcedConfig::BT_BLE,
};
constexpr bool iequals(const std::string& str1, const std::string& str2) {
return str1.length() == str2.length() &&
!fasticmp<strncmp>(str1.c_str(), str2.c_str(), str1.length());
}
constexpr size_t getPcmSampleSizeInBytes(::aidl::android::media::audio::common::PcmType pcm) {
using ::aidl::android::media::audio::common::PcmType;
switch (pcm) {
@@ -133,6 +165,12 @@ constexpr bool isValidAudioMode(::aidl::android::media::audio::common::AudioMode
kValidAudioModes.end();
}
constexpr bool isValidAudioPolicyForcedConfig(
::aidl::android::media::audio::common::AudioPolicyForcedConfig config) {
return std::find(kValidAudioPolicyForcedConfig.begin(), kValidAudioPolicyForcedConfig.end(),
config) != kValidAudioPolicyForcedConfig.end();
}
static inline bool maybeVendorExtension(const std::string& s) {
// Only checks whether the string starts with the "vendor prefix".
static const std::string vendorPrefix = "VX_";

View File

@@ -54,6 +54,7 @@ cc_library {
"AidlConversionXsdc.cpp",
"AudioPolicyConfigXmlConverter.cpp",
"Bluetooth.cpp",
"CapEngineConfigXmlConverter.cpp",
"Config.cpp",
"Configuration.cpp",
"EngineConfigXmlConverter.cpp",
@@ -83,14 +84,17 @@ cc_library {
"usb/UsbAlsaMixerControl.cpp",
],
generated_sources: [
"audio_policy_capengine_configuration_aidl_default",
"audio_policy_configuration_aidl_default",
"audio_policy_engine_configuration_aidl_default",
],
generated_headers: [
"audio_policy_capengine_configuration_aidl_default",
"audio_policy_configuration_aidl_default",
"audio_policy_engine_configuration_aidl_default",
],
export_generated_headers: [
"audio_policy_capengine_configuration_aidl_default",
"audio_policy_configuration_aidl_default",
"audio_policy_engine_configuration_aidl_default",
],

View File

@@ -0,0 +1,386 @@
/*
* Copyright (C) 2024 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.
*/
#define LOG_TAG "AHAL_Config"
#include <aidl/android/media/audio/common/AudioProductStrategyType.h>
#include <android-base/logging.h>
#include <media/AidlConversionCppNdk.h>
#include <media/TypeConverter.h>
#include <media/convert.h>
#include <utils/FastStrcmp.h>
#include "core-impl/CapEngineConfigXmlConverter.h"
#include "core-impl/XsdcConversion.h"
using aidl::android::hardware::audio::common::iequals;
using aidl::android::media::audio::common::AudioDeviceAddress;
using aidl::android::media::audio::common::AudioDeviceDescription;
using aidl::android::media::audio::common::AudioHalCapConfiguration;
using aidl::android::media::audio::common::AudioHalCapCriterionV2;
using aidl::android::media::audio::common::AudioHalCapDomain;
using aidl::android::media::audio::common::AudioHalCapParameter;
using aidl::android::media::audio::common::AudioHalCapRule;
using aidl::android::media::audio::common::AudioPolicyForceUse;
using aidl::android::media::audio::common::AudioSource;
using aidl::android::media::audio::common::AudioStreamType;
using ::android::BAD_VALUE;
using ::android::base::unexpected;
using ::android::utilities::convertTo;
namespace eng_xsd = android::audio::policy::capengine::configuration;
namespace aidl::android::hardware::audio::core::internal {
static constexpr const char* gStrategiesParameter = "product_strategies";
static constexpr const char* gInputSourcesParameter = "input_sources";
static constexpr const char* gStreamsParameter = "streams";
static constexpr const char* gOutputDevicesParameter = "selected_output_devices";
static constexpr const char* gOutputDeviceAddressParameter = "device_address";
static constexpr const char* gStrategyPrefix = "vx_";
static constexpr const char* gLegacyOutputDevicePrefix = "AUDIO_DEVICE_OUT_";
static constexpr const char* gLegacyInputDevicePrefix = "AUDIO_DEVICE_IN_";
static constexpr const char* gLegacyStreamPrefix = "AUDIO_STREAM_";
static constexpr const char* gLegacySourcePrefix = "AUDIO_SOURCE_";
std::optional<std::vector<std::optional<AudioHalCapDomain>>>&
CapEngineConfigXmlConverter::getAidlCapEngineConfig() {
return mAidlCapDomains;
}
ConversionResult<AudioHalCapRule::CriterionRule> convertCriterionRuleToAidl(
const eng_xsd::SelectionCriterionRuleType& xsdcRule) {
using Tag = AudioHalCapCriterionV2::Tag;
AudioHalCapRule::CriterionRule rule{};
std::string criterionName = xsdcRule.getSelectionCriterion();
std::string criterionValue = xsdcRule.getValue();
if (iequals(criterionName, toString(Tag::availableInputDevices))) {
rule.criterion = AudioHalCapCriterionV2::make<Tag::availableInputDevices>();
rule.criterionTypeValue =
VALUE_OR_RETURN(convertDeviceTypeToAidl(gLegacyInputDevicePrefix + criterionValue));
} else if (iequals(criterionName, toString(Tag::availableOutputDevices))) {
rule.criterion = AudioHalCapCriterionV2::make<Tag::availableOutputDevices>();
rule.criterionTypeValue = VALUE_OR_RETURN(
convertDeviceTypeToAidl(gLegacyOutputDevicePrefix + criterionValue));
} else if (iequals(criterionName, toString(Tag::availableInputDevicesAddresses))) {
rule.criterion = AudioHalCapCriterionV2::make<Tag::availableInputDevicesAddresses>();
rule.criterionTypeValue =
AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>(criterionValue);
} else if (iequals(criterionName, toString(Tag::availableOutputDevicesAddresses))) {
rule.criterion = AudioHalCapCriterionV2::make<Tag::availableOutputDevicesAddresses>();
rule.criterionTypeValue =
AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>(criterionValue);
} else if (iequals(criterionName, toString(Tag::telephonyMode))) {
rule.criterion = AudioHalCapCriterionV2::make<Tag::telephonyMode>();
rule.criterionTypeValue = VALUE_OR_RETURN(convertTelephonyModeToAidl(criterionValue));
} else if (!fastcmp<strncmp>(criterionName.c_str(), kXsdcForceConfigForUse,
strlen(kXsdcForceConfigForUse))) {
rule.criterion = AudioHalCapCriterionV2::make<Tag::forceConfigForUse>(
VALUE_OR_RETURN(convertForceUseCriterionToAidl(criterionName)));
rule.criterionTypeValue = VALUE_OR_RETURN(convertForcedConfigToAidl(criterionValue));
} else {
LOG(ERROR) << __func__ << " unrecognized criterion " << criterionName;
return unexpected(BAD_VALUE);
}
if (xsdcRule.getMatchesWhen() == eng_xsd::MatchesWhenEnum::Excludes) {
rule.matchingRule = AudioHalCapRule::MatchingRule::EXCLUDES;
} else if (xsdcRule.getMatchesWhen() == eng_xsd::MatchesWhenEnum::Includes) {
rule.matchingRule = AudioHalCapRule::MatchingRule::INCLUDES;
} else if (xsdcRule.getMatchesWhen() == eng_xsd::MatchesWhenEnum::Is) {
rule.matchingRule = AudioHalCapRule::MatchingRule::IS;
} else if (xsdcRule.getMatchesWhen() == eng_xsd::MatchesWhenEnum::IsNot) {
rule.matchingRule = AudioHalCapRule::MatchingRule::IS_NOT;
} else {
LOG(ERROR) << "Unsupported match when rule.";
return unexpected(BAD_VALUE);
}
return rule;
}
ConversionResult<AudioHalCapRule> convertRule(const eng_xsd::CompoundRuleType& xsdcCompoundRule) {
AudioHalCapRule rule{};
bool isPreviousCompoundRule = true;
if (xsdcCompoundRule.getType() == eng_xsd::TypeEnum::Any) {
rule.compoundRule = AudioHalCapRule::CompoundRule::ANY;
} else if (xsdcCompoundRule.getType() == eng_xsd::TypeEnum::All) {
rule.compoundRule = AudioHalCapRule::CompoundRule::ALL;
} else {
LOG(ERROR) << "Unsupported compound rule type.";
return unexpected(BAD_VALUE);
}
for (const auto& childXsdcCoumpoundRule : xsdcCompoundRule.getCompoundRule_optional()) {
if (childXsdcCoumpoundRule.hasCompoundRule_optional()) {
rule.nestedRules.push_back(VALUE_OR_FATAL(convertRule(childXsdcCoumpoundRule)));
} else if (childXsdcCoumpoundRule.hasSelectionCriterionRule_optional()) {
rule.nestedRules.push_back(VALUE_OR_FATAL(convertRule(childXsdcCoumpoundRule)));
}
}
if (xsdcCompoundRule.hasSelectionCriterionRule_optional()) {
for (const auto& xsdcRule : xsdcCompoundRule.getSelectionCriterionRule_optional()) {
rule.criterionRules.push_back(VALUE_OR_FATAL(convertCriterionRuleToAidl(xsdcRule)));
}
}
return rule;
}
ConversionResult<int> getAudioProductStrategyId(const std::string& path) {
std::vector<std::string> strings;
std::istringstream pathStream(path);
std::string stringToken;
while (getline(pathStream, stringToken, '/')) {
std::size_t pos = stringToken.find(gStrategyPrefix);
if (pos != std::string::npos) {
std::string strategyIdLiteral = stringToken.substr(pos + std::strlen(gStrategyPrefix));
int strategyId;
if (!convertTo(strategyIdLiteral, strategyId)) {
LOG(ERROR) << "Invalid strategy " << stringToken << " from path " << path;
return unexpected(BAD_VALUE);
}
return strategyId;
}
}
return unexpected(BAD_VALUE);
}
ConversionResult<AudioSource> getAudioSource(const std::string& path) {
std::vector<std::string> strings;
std::istringstream pathStream(path);
std::string stringToken;
while (getline(pathStream, stringToken, '/')) {
if (stringToken.find(gInputSourcesParameter) != std::string::npos) {
getline(pathStream, stringToken, '/');
std::transform(stringToken.begin(), stringToken.end(), stringToken.begin(),
[](char c) { return std::toupper(c); });
std::string legacySourceLiteral = "AUDIO_SOURCE_" + stringToken;
audio_source_t legacySource;
if (!::android::SourceTypeConverter::fromString(legacySourceLiteral, legacySource)) {
LOG(ERROR) << "Invalid source " << stringToken << " from path " << path;
return unexpected(BAD_VALUE);
}
return legacy2aidl_audio_source_t_AudioSource(legacySource);
}
}
return unexpected(BAD_VALUE);
}
ConversionResult<AudioStreamType> getAudioStreamType(const std::string& path) {
std::vector<std::string> strings;
std::istringstream pathStream(path);
std::string stringToken;
while (getline(pathStream, stringToken, '/')) {
if (stringToken.find(gStreamsParameter) != std::string::npos) {
getline(pathStream, stringToken, '/');
std::transform(stringToken.begin(), stringToken.end(), stringToken.begin(),
[](char c) { return std::toupper(c); });
std::string legacyStreamLiteral = std::string(gLegacyStreamPrefix) + stringToken;
audio_stream_type_t legacyStream;
if (!::android::StreamTypeConverter::fromString(legacyStreamLiteral, legacyStream)) {
LOG(ERROR) << "Invalid stream " << stringToken << " from path " << path;
return unexpected(BAD_VALUE);
}
return legacy2aidl_audio_stream_type_t_AudioStreamType(legacyStream);
}
}
return unexpected(BAD_VALUE);
}
ConversionResult<std::string> toUpperAndAppendPrefix(const std::string& capName,
const std::string& legacyPrefix) {
std::string legacyName = capName;
std::transform(legacyName.begin(), legacyName.end(), legacyName.begin(),
[](char c) { return std::toupper(c); });
return legacyPrefix + legacyName;
}
ConversionResult<AudioHalCapParameter> CapEngineConfigXmlConverter::convertParamToAidl(
const eng_xsd::ConfigurableElementSettingsType& element) {
const auto& path = element.getPath();
AudioHalCapParameter parameterSetting;
if (path.find(gStrategiesParameter) != std::string::npos) {
int strategyId = VALUE_OR_FATAL(getAudioProductStrategyId(path));
if (path.find(gOutputDevicesParameter) != std::string::npos) {
// Value is 1 or 0
if (!element.hasBitParameter_optional()) {
LOG(ERROR) << "Invalid strategy value type";
return unexpected(BAD_VALUE);
}
// Convert name to output device type
const auto* xsdcParam = element.getFirstBitParameter_optional();
std::string outputDevice = VALUE_OR_FATAL(toUpperAndAppendPrefix(
eng_xsd::toString(xsdcParam->getName()), gLegacyOutputDevicePrefix));
audio_devices_t legacyType;
if (!::android::OutputDeviceConverter::fromString(outputDevice, legacyType)) {
LOG(ERROR) << "Invalid strategy device type " << outputDevice;
return unexpected(BAD_VALUE);
}
AudioDeviceDescription aidlDevice =
VALUE_OR_FATAL(legacy2aidl_audio_devices_t_AudioDeviceDescription(legacyType));
bool isSelected;
if (!convertTo(xsdcParam->getValue(), isSelected)) {
LOG(ERROR) << "Invalid strategy device selection value " << xsdcParam->getValue();
return unexpected(BAD_VALUE);
}
parameterSetting =
AudioHalCapParameter::StrategyDevice(aidlDevice, strategyId, isSelected);
} else if (path.find(gOutputDeviceAddressParameter) != std::string::npos) {
// Value is the address
if (!element.hasStringParameter_optional()) {
return unexpected(BAD_VALUE);
}
std::string address = element.getFirstStringParameter_optional()->getValue();
parameterSetting = AudioHalCapParameter::StrategyDeviceAddress(
AudioDeviceAddress(address), strategyId);
}
} else if (path.find(gInputSourcesParameter) != std::string::npos) {
// Value is 1 or 0
if (!element.hasBitParameter_optional()) {
LOG(ERROR) << "Invalid source value type";
return unexpected(BAD_VALUE);
}
AudioSource audioSourceAidl = VALUE_OR_FATAL(getAudioSource(path));
const auto* xsdcParam = element.getFirstBitParameter_optional();
std::string inputDeviceLiteral = VALUE_OR_FATAL(toUpperAndAppendPrefix(
eng_xsd::toString(xsdcParam->getName()), gLegacyInputDevicePrefix));
audio_devices_t inputDeviceType;
if (!::android::InputDeviceConverter::fromString(inputDeviceLiteral, inputDeviceType)) {
LOG(ERROR) << "Invalid source device type " << inputDeviceLiteral;
return unexpected(BAD_VALUE);
}
AudioDeviceDescription aidlDevice =
VALUE_OR_FATAL(legacy2aidl_audio_devices_t_AudioDeviceDescription(inputDeviceType));
bool isSelected;
if (!convertTo(xsdcParam->getValue(), isSelected)) {
LOG(ERROR) << "Invalid source value type " << xsdcParam->getValue();
return unexpected(BAD_VALUE);
}
parameterSetting =
AudioHalCapParameter::InputSourceDevice(aidlDevice, audioSourceAidl, isSelected);
} else if (path.find(gStreamsParameter) != std::string::npos) {
AudioStreamType audioStreamAidl = VALUE_OR_FATAL(getAudioStreamType(path));
if (!element.hasEnumParameter_optional()) {
LOG(ERROR) << "Invalid stream value type";
return unexpected(BAD_VALUE);
}
const auto* xsdcParam = element.getFirstEnumParameter_optional();
std::string profileLiteral =
VALUE_OR_FATAL(toUpperAndAppendPrefix(xsdcParam->getValue(), gLegacyStreamPrefix));
audio_stream_type_t profileLegacyStream;
if (!::android::StreamTypeConverter::fromString(profileLiteral, profileLegacyStream)) {
LOG(ERROR) << "Invalid stream value " << profileLiteral;
return unexpected(BAD_VALUE);
}
AudioStreamType profileStreamAidl = VALUE_OR_FATAL(
legacy2aidl_audio_stream_type_t_AudioStreamType(profileLegacyStream));
parameterSetting =
AudioHalCapParameter::StreamVolumeProfile(audioStreamAidl, profileStreamAidl);
}
return parameterSetting;
}
ConversionResult<std::vector<AudioHalCapParameter>>
CapEngineConfigXmlConverter::convertSettingToAidl(
const eng_xsd::SettingsType::Configuration& xsdcSetting) {
std::vector<AudioHalCapParameter> aidlCapParameterSettings;
for (const auto& element : xsdcSetting.getConfigurableElement()) {
aidlCapParameterSettings.push_back(VALUE_OR_FATAL(convertParamToAidl(element)));
}
return aidlCapParameterSettings;
}
ConversionResult<AudioHalCapConfiguration> CapEngineConfigXmlConverter::convertConfigurationToAidl(
const eng_xsd::ConfigurationsType::Configuration& xsdcConfiguration,
const eng_xsd::SettingsType::Configuration& xsdcSettingConfiguration) {
AudioHalCapConfiguration aidlCapConfiguration;
aidlCapConfiguration.name = xsdcConfiguration.getName();
if (xsdcConfiguration.hasCompoundRule()) {
if (xsdcConfiguration.getCompoundRule().size() != 1) {
return unexpected(BAD_VALUE);
}
aidlCapConfiguration.rule =
VALUE_OR_FATAL(convertRule(xsdcConfiguration.getCompoundRule()[0]));
aidlCapConfiguration.parameterSettings =
VALUE_OR_FATAL(convertSettingToAidl(xsdcSettingConfiguration));
}
return aidlCapConfiguration;
}
ConversionResult<eng_xsd::SettingsType::Configuration> getConfigurationByName(
const std::string& name, const std::vector<eng_xsd::SettingsType>& xsdcSettingsVec) {
for (const auto& xsdcSettings : xsdcSettingsVec) {
for (const auto& xsdcConfiguration : xsdcSettings.getConfiguration()) {
if (xsdcConfiguration.getName() == name) {
return xsdcConfiguration;
}
}
}
LOG(ERROR) << __func__ << " failed to find configuration " << name;
return unexpected(BAD_VALUE);
}
ConversionResult<std::vector<AudioHalCapConfiguration>>
CapEngineConfigXmlConverter::convertConfigurationsToAidl(
const std::vector<eng_xsd::ConfigurationsType>& xsdcConfigurationsVec,
const std::vector<eng_xsd::SettingsType>& xsdcSettingsVec) {
if (xsdcConfigurationsVec.empty() || xsdcSettingsVec.empty()) {
LOG(ERROR) << __func__ << " empty configurations/settings";
return unexpected(BAD_VALUE);
}
std::vector<AudioHalCapConfiguration> aidlConfigurations;
for (const auto& xsdcConfigurations : xsdcConfigurationsVec) {
for (const auto& xsdcConfiguration : xsdcConfigurations.getConfiguration()) {
auto xsdcSettingConfiguration = VALUE_OR_FATAL(
getConfigurationByName(xsdcConfiguration.getName(), xsdcSettingsVec));
aidlConfigurations.push_back(VALUE_OR_FATAL(
convertConfigurationToAidl(xsdcConfiguration, xsdcSettingConfiguration)));
}
}
return aidlConfigurations;
}
ConversionResult<AudioHalCapDomain> CapEngineConfigXmlConverter::convertConfigurableDomainToAidl(
const eng_xsd::ConfigurableDomainType& xsdcConfigurableDomain) {
AudioHalCapDomain aidlConfigurableDomain;
aidlConfigurableDomain.name = xsdcConfigurableDomain.getName();
if (xsdcConfigurableDomain.hasSequenceAware() && xsdcConfigurableDomain.getSequenceAware()) {
LOG(ERROR) << "sequence aware not supported.";
return unexpected(BAD_VALUE);
}
if (xsdcConfigurableDomain.hasConfigurations() && xsdcConfigurableDomain.hasSettings()) {
aidlConfigurableDomain.configurations = VALUE_OR_FATAL(convertConfigurationsToAidl(
xsdcConfigurableDomain.getConfigurations(), xsdcConfigurableDomain.getSettings()));
}
return aidlConfigurableDomain;
}
void CapEngineConfigXmlConverter::init() {
if (getXsdcConfig()->hasConfigurableDomain()) {
mAidlCapDomains = std::make_optional<>(VALUE_OR_FATAL(
(convertCollectionToAidlOptionalValues<eng_xsd::ConfigurableDomainType,
AudioHalCapDomain>(
getXsdcConfig()->getConfigurableDomain(),
std::bind(&CapEngineConfigXmlConverter::convertConfigurableDomainToAidl,
this, std::placeholders::_1)))));
} else {
mAidlCapDomains = std::nullopt;
}
}
} // namespace aidl::android::hardware::audio::core::internal

View File

@@ -26,15 +26,19 @@
#include <aidl/android/media/audio/common/AudioProductStrategyType.h>
#include <android-base/logging.h>
#include "core-impl/CapEngineConfigXmlConverter.h"
#include "core-impl/EngineConfigXmlConverter.h"
#include "core-impl/XsdcConversion.h"
using aidl::android::hardware::audio::core::internal::CapEngineConfigXmlConverter;
using aidl::android::hardware::audio::core::internal::convertAudioUsageToAidl;
using aidl::android::media::audio::common::AudioAttributes;
using aidl::android::media::audio::common::AudioContentType;
using aidl::android::media::audio::common::AudioFlag;
using aidl::android::media::audio::common::AudioHalAttributesGroup;
using aidl::android::media::audio::common::AudioHalCapCriterion;
using aidl::android::media::audio::common::AudioHalCapCriterionType;
using aidl::android::media::audio::common::AudioHalCapCriterionV2;
using aidl::android::media::audio::common::AudioHalEngineConfig;
using aidl::android::media::audio::common::AudioHalProductStrategy;
using aidl::android::media::audio::common::AudioHalVolumeCurve;
@@ -43,6 +47,7 @@ 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;
@@ -50,6 +55,10 @@ namespace eng_xsd = android::audio::policy::engine::configuration;
namespace aidl::android::hardware::audio::core::internal {
/** Default path of audio policy cap engine configuration file. */
static constexpr char kCapEngineConfigFileName[] =
"/parameter-framework/Settings/Policy/PolicyConfigurableDomains.xml";
void EngineConfigXmlConverter::initProductStrategyMap() {
#define STRATEGY_ENTRY(name) {"STRATEGY_" #name, static_cast<int>(AudioProductStrategyType::name)}
@@ -74,6 +83,13 @@ ConversionResult<int> EngineConfigXmlConverter::convertProductStrategyNameToAidl
return it->second;
}
ConversionResult<int> EngineConfigXmlConverter::convertProductStrategyIdToAidl(int xsdcId) {
if (xsdcId < AudioHalProductStrategy::VENDOR_STRATEGY_ID_START) {
return unexpected(BAD_VALUE);
}
return xsdcId;
}
bool isDefaultAudioAttributes(const AudioAttributes& attributes) {
return ((attributes.contentType == AudioContentType::UNKNOWN) &&
(attributes.usage == AudioUsage::UNKNOWN) &&
@@ -95,29 +111,26 @@ ConversionResult<AudioAttributes> EngineConfigXmlConverter::convertAudioAttribut
}
AudioAttributes aidlAudioAttributes;
if (xsdcAudioAttributes.hasContentType()) {
aidlAudioAttributes.contentType = static_cast<AudioContentType>(
xsdcAudioAttributes.getFirstContentType()->getValue());
aidlAudioAttributes.contentType = VALUE_OR_FATAL(convertAudioContentTypeToAidl(
xsdcAudioAttributes.getFirstContentType()->getValue()));
}
if (xsdcAudioAttributes.hasUsage()) {
aidlAudioAttributes.usage =
static_cast<AudioUsage>(xsdcAudioAttributes.getFirstUsage()->getValue());
aidlAudioAttributes.usage = VALUE_OR_FATAL(
convertAudioUsageToAidl(xsdcAudioAttributes.getFirstUsage()->getValue()));
}
if (xsdcAudioAttributes.hasSource()) {
aidlAudioAttributes.source =
static_cast<AudioSource>(xsdcAudioAttributes.getFirstSource()->getValue());
aidlAudioAttributes.source = VALUE_OR_FATAL(
convertAudioSourceToAidl(xsdcAudioAttributes.getFirstSource()->getValue()));
}
if (xsdcAudioAttributes.hasFlags()) {
std::vector<eng_xsd::FlagType> xsdcFlagTypeVec =
xsdcAudioAttributes.getFirstFlags()->getValue();
for (const eng_xsd::FlagType& xsdcFlagType : xsdcFlagTypeVec) {
if (xsdcFlagType != eng_xsd::FlagType::AUDIO_FLAG_NONE) {
aidlAudioAttributes.flags |= 1 << (static_cast<int>(xsdcFlagType) - 1);
}
}
aidlAudioAttributes.flags = VALUE_OR_FATAL(convertAudioFlagsToAidl(xsdcFlagTypeVec));
}
if (xsdcAudioAttributes.hasBundle()) {
const eng_xsd::BundleType* xsdcBundle = xsdcAudioAttributes.getFirstBundle();
aidlAudioAttributes.tags[0] = xsdcBundle->getKey() + "=" + xsdcBundle->getValue();
aidlAudioAttributes.tags.reserve(1);
aidlAudioAttributes.tags.push_back(xsdcBundle->getKey() + "_" + xsdcBundle->getValue());
}
if (isDefaultAudioAttributes(aidlAudioAttributes)) {
mDefaultProductStrategyId = std::optional<int>{-1};
@@ -131,8 +144,10 @@ ConversionResult<AudioHalAttributesGroup> EngineConfigXmlConverter::convertAttri
static const int kStreamTypeEnumOffset =
static_cast<int>(eng_xsd::Stream::AUDIO_STREAM_VOICE_CALL) -
static_cast<int>(AudioStreamType::VOICE_CALL);
aidlAttributesGroup.streamType = static_cast<AudioStreamType>(
static_cast<int>(xsdcAttributesGroup.getStreamType()) - kStreamTypeEnumOffset);
aidlAttributesGroup.streamType = xsdcAttributesGroup.hasStreamType()
? VALUE_OR_FATAL(convertAudioStreamTypeToAidl(
xsdcAttributesGroup.getStreamType()))
: AudioStreamType::INVALID;
aidlAttributesGroup.volumeGroupName = xsdcAttributesGroup.getVolumeGroup();
if (xsdcAttributesGroup.hasAttributes_optional()) {
aidlAttributesGroup.attributes =
@@ -165,7 +180,8 @@ ConversionResult<AudioHalProductStrategy> EngineConfigXmlConverter::convertProdu
AudioHalProductStrategy aidlProductStrategy;
aidlProductStrategy.id =
VALUE_OR_FATAL(convertProductStrategyNameToAidl(xsdcProductStrategy.getName()));
VALUE_OR_FATAL(convertProductStrategyIdToAidl(xsdcProductStrategy.getId()));
aidlProductStrategy.name = xsdcProductStrategy.getName();
if (xsdcProductStrategy.hasAttributesGroup()) {
aidlProductStrategy.attributesGroups = VALUE_OR_FATAL(
@@ -247,18 +263,15 @@ void EngineConfigXmlConverter::init() {
}
if (getXsdcConfig()->hasCriteria() && getXsdcConfig()->hasCriterion_types()) {
AudioHalEngineConfig::CapSpecificConfig capSpecificConfig;
capSpecificConfig.criteria = VALUE_OR_FATAL(
(convertWrappedCollectionToAidl<eng_xsd::CriteriaType, eng_xsd::CriterionType,
AudioHalCapCriterion>(
getXsdcConfig()->getCriteria(), &eng_xsd::CriteriaType::getCriterion,
&convertCapCriterionToAidl)));
capSpecificConfig.criterionTypes =
VALUE_OR_FATAL((convertWrappedCollectionToAidl<eng_xsd::CriterionTypesType,
eng_xsd::CriterionTypeType,
AudioHalCapCriterionType>(
getXsdcConfig()->getCriterion_types(),
&eng_xsd::CriterionTypesType::getCriterion_type,
&convertCapCriterionTypeToAidl)));
capSpecificConfig.criteriaV2 =
std::make_optional<>(VALUE_OR_FATAL((convertCapCriteriaCollectionToAidl(
getXsdcConfig()->getCriteria(), getXsdcConfig()->getCriterion_types()))));
internal::CapEngineConfigXmlConverter capEngConfigConverter{
::android::audio_find_readable_configuration_file(kCapEngineConfigFileName)};
if (capEngConfigConverter.getStatus() == ::android::OK) {
capSpecificConfig.domains = std::move(capEngConfigConverter.getAidlCapEngineConfig());
}
mAidlEngineConfig.capSpecificConfig = capSpecificConfig;
}
}
} // namespace aidl::android::hardware::audio::core::internal

View File

@@ -10,11 +10,21 @@
#include <aidl/android/media/audio/common/AudioPortConfig.h>
#include <media/AidlConversionCppNdk.h>
#include <media/TypeConverter.h>
#include <media/convert.h>
#include <utils/FastStrcmp.h>
#include <Utils.h>
#include "core-impl/XmlConverter.h"
#include "core-impl/XsdcConversion.h"
using aidl::android::hardware::audio::common::iequals;
using aidl::android::hardware::audio::common::isValidAudioMode;
using aidl::android::hardware::audio::common::isValidAudioPolicyForcedConfig;
using aidl::android::hardware::audio::common::kValidAudioModes;
using aidl::android::hardware::audio::common::kValidAudioPolicyForcedConfig;
using aidl::android::media::audio::common::AudioChannelLayout;
using aidl::android::media::audio::common::AudioContentType;
using aidl::android::media::audio::common::AudioDevice;
using aidl::android::media::audio::common::AudioDeviceAddress;
using aidl::android::media::audio::common::AudioDeviceDescription;
@@ -24,22 +34,39 @@ 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::AudioHalCapCriterionV2;
using aidl::android::media::audio::common::AudioHalVolumeCurve;
using aidl::android::media::audio::common::AudioIoFlags;
using aidl::android::media::audio::common::AudioMode;
using aidl::android::media::audio::common::AudioPolicyForcedConfig;
using aidl::android::media::audio::common::AudioPolicyForceUse;
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 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;
using ::android::utilities::convertTo;
namespace ap_xsd = android::audio::policy::configuration;
namespace eng_xsd = android::audio::policy::engine::configuration;
namespace aidl::android::hardware::audio::core::internal {
static constexpr const char kXsdcForceConfigForCommunication[] = "ForceUseForCommunication";
static constexpr const char kXsdcForceConfigForMedia[] = "ForceUseForMedia";
static constexpr const char kXsdcForceConfigForRecord[] = "ForceUseForRecord";
static constexpr const char kXsdcForceConfigForDock[] = "ForceUseForDock";
static constexpr const char kXsdcForceConfigForSystem[] = "ForceUseForSystem";
static constexpr const char kXsdcForceConfigForHdmiSystemAudio[] = "ForceUseForHdmiSystemAudio";
static constexpr const char kXsdcForceConfigForEncodedSurround[] = "ForceUseForEncodedSurround";
static constexpr const char kXsdcForceConfigForVibrateRinging[] = "ForceUseForVibrateRinging";
inline ConversionResult<std::string> assertNonEmpty(const std::string& s) {
if (s.empty()) {
LOG(ERROR) << __func__ << " Review Audio Policy config: "
@@ -51,6 +78,100 @@ inline ConversionResult<std::string> assertNonEmpty(const std::string& s) {
#define NON_EMPTY_STRING_OR_FATAL(s) VALUE_OR_FATAL(assertNonEmpty(s))
ConversionResult<int32_t> convertAudioFlagsToAidl(
const std::vector<eng_xsd::FlagType>& xsdcFlagTypeVec) {
int legacyFlagMask = 0;
for (const eng_xsd::FlagType& xsdcFlagType : xsdcFlagTypeVec) {
if (xsdcFlagType != eng_xsd::FlagType::AUDIO_FLAG_NONE) {
audio_flags_mask_t legacyFlag = AUDIO_FLAG_NONE;
if (!::android::AudioFlagConverter::fromString(eng_xsd::toString(xsdcFlagType),
legacyFlag)) {
LOG(ERROR) << __func__ << " Review Audio Policy config, "
<< eng_xsd::toString(xsdcFlagType) << " is not a valid flag.";
return unexpected(BAD_VALUE);
}
legacyFlagMask |= static_cast<int>(legacyFlag);
}
}
ConversionResult<int32_t> result = legacy2aidl_audio_flags_mask_t_int32_t_mask(
static_cast<audio_flags_mask_t>(legacyFlagMask));
if (!result.ok()) {
LOG(ERROR) << __func__ << " Review Audio Policy config, " << legacyFlagMask
<< " has invalid flag(s).";
return unexpected(BAD_VALUE);
}
return result;
}
ConversionResult<AudioStreamType> convertAudioStreamTypeToAidl(const eng_xsd::Stream& xsdcStream) {
audio_stream_type_t legacyStreamType;
if (!::android::StreamTypeConverter::fromString(eng_xsd::toString(xsdcStream),
legacyStreamType)) {
LOG(ERROR) << __func__ << " Review Audio Policy config, " << eng_xsd::toString(xsdcStream)
<< " is not a valid audio stream type.";
return unexpected(BAD_VALUE);
}
ConversionResult<AudioStreamType> result =
legacy2aidl_audio_stream_type_t_AudioStreamType(legacyStreamType);
if (!result.ok()) {
LOG(ERROR) << __func__ << " Review Audio Policy config, " << legacyStreamType
<< " is not a valid audio stream type.";
return unexpected(BAD_VALUE);
}
return result;
}
ConversionResult<AudioSource> convertAudioSourceToAidl(
const eng_xsd::SourceEnumType& xsdcSourceType) {
audio_source_t legacySourceType;
if (!::android::SourceTypeConverter::fromString(eng_xsd::toString(xsdcSourceType),
legacySourceType)) {
LOG(ERROR) << __func__ << " Review Audio Policy config, "
<< eng_xsd::toString(xsdcSourceType) << " is not a valid audio source.";
return unexpected(BAD_VALUE);
}
ConversionResult<AudioSource> result = legacy2aidl_audio_source_t_AudioSource(legacySourceType);
if (!result.ok()) {
LOG(ERROR) << __func__ << " Review Audio Policy config, " << legacySourceType
<< " is not a valid audio source.";
return unexpected(BAD_VALUE);
}
return result;
}
ConversionResult<AudioContentType> convertAudioContentTypeToAidl(
const eng_xsd::ContentType& xsdcContentType) {
audio_content_type_t legacyContentType;
if (!::android::AudioContentTypeConverter::fromString(eng_xsd::toString(xsdcContentType),
legacyContentType)) {
LOG(ERROR) << __func__ << " Review Audio Policy config, "
<< eng_xsd::toString(xsdcContentType) << " is not a valid audio content type.";
return unexpected(BAD_VALUE);
}
ConversionResult<AudioContentType> result =
legacy2aidl_audio_content_type_t_AudioContentType(legacyContentType);
if (!result.ok()) {
LOG(ERROR) << __func__ << " Review Audio Policy config, " << legacyContentType
<< " is not a valid audio content type.";
return unexpected(BAD_VALUE);
}
return result;
}
ConversionResult<AudioUsage> convertAudioUsageToAidl(const eng_xsd::UsageEnumType& xsdcUsage) {
audio_usage_t legacyUsage;
if (!::android::UsageTypeConverter::fromString(eng_xsd::toString(xsdcUsage), legacyUsage)) {
LOG(ERROR) << __func__ << " Review Audio Policy config, not a valid audio usage.";
return unexpected(BAD_VALUE);
}
ConversionResult<AudioUsage> result = legacy2aidl_audio_usage_t_AudioUsage(legacyUsage);
if (!result.ok()) {
LOG(ERROR) << __func__ << " Review Audio Policy config, not a valid audio usage.";
return unexpected(BAD_VALUE);
}
return result;
}
ConversionResult<AudioFormatDescription> convertAudioFormatToAidl(const std::string& xsdcFormat) {
audio_format_t legacyFormat = ::android::formatFromString(xsdcFormat, AUDIO_FORMAT_DEFAULT);
ConversionResult<AudioFormatDescription> result =
@@ -410,32 +531,240 @@ ConversionResult<std::unique_ptr<Module::Configuration>> convertModuleConfigToAi
return result;
}
ConversionResult<AudioPolicyForcedConfig> convertForcedConfigToAidl(
const std::string& xsdcForcedConfigCriterionType) {
const auto it = std::find_if(
kValidAudioPolicyForcedConfig.begin(), kValidAudioPolicyForcedConfig.end(),
[&](const auto& config) { return toString(config) == xsdcForcedConfigCriterionType; });
if (it == kValidAudioPolicyForcedConfig.end()) {
LOG(ERROR) << __func__ << " invalid forced config " << xsdcForcedConfigCriterionType;
return unexpected(BAD_VALUE);
}
return *it;
}
ConversionResult<AudioMode> convertTelephonyModeToAidl(const std::string& xsdcModeCriterionType) {
const auto it = std::find_if(kValidAudioModes.begin(), kValidAudioModes.end(),
[&xsdcModeCriterionType](const auto& mode) {
return toString(mode) == xsdcModeCriterionType;
});
if (it == kValidAudioModes.end()) {
LOG(ERROR) << __func__ << " invalid mode " << xsdcModeCriterionType;
return unexpected(BAD_VALUE);
}
return *it;
}
ConversionResult<AudioDeviceAddress> convertDeviceAddressToAidl(const std::string& xsdcAddress) {
return AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>(xsdcAddress);
}
ConversionResult<eng_xsd::CriterionTypeType> getCriterionTypeByName(
const std::string& name,
const std::vector<eng_xsd::CriterionTypesType>& xsdcCriterionTypesVec) {
for (const auto& xsdCriterionTypes : xsdcCriterionTypesVec) {
for (const auto& xsdcCriterionType : xsdCriterionTypes.getCriterion_type()) {
if (xsdcCriterionType.getName() == name) {
return xsdcCriterionType;
}
}
}
LOG(ERROR) << __func__ << " failed to find criterion type " << name;
return unexpected(BAD_VALUE);
}
ConversionResult<std::vector<std::optional<AudioHalCapCriterionV2>>>
convertCapCriteriaCollectionToAidl(
const std::vector<eng_xsd::CriteriaType>& xsdcCriteriaVec,
const std::vector<eng_xsd::CriterionTypesType>& xsdcCriterionTypesVec) {
std::vector<std::optional<AudioHalCapCriterionV2>> resultAidlCriterionVec;
if (xsdcCriteriaVec.empty() || xsdcCriterionTypesVec.empty()) {
LOG(ERROR) << __func__ << " empty criteria/criterionTypes";
return unexpected(BAD_VALUE);
}
for (const auto& xsdCriteria : xsdcCriteriaVec) {
for (const auto& xsdcCriterion : xsdCriteria.getCriterion()) {
resultAidlCriterionVec.push_back(
std::optional<AudioHalCapCriterionV2>(VALUE_OR_FATAL(
convertCapCriterionV2ToAidl(xsdcCriterion, xsdcCriterionTypesVec))));
}
}
return resultAidlCriterionVec;
}
ConversionResult<std::vector<AudioDeviceDescription>> convertDevicesToAidl(
const eng_xsd::CriterionTypeType& xsdcDeviceCriterionType) {
if (xsdcDeviceCriterionType.getValues().empty()) {
LOG(ERROR) << __func__ << " no values provided";
return unexpected(BAD_VALUE);
}
std::vector<AudioDeviceDescription> aidlDevices;
for (eng_xsd::ValuesType xsdcValues : xsdcDeviceCriterionType.getValues()) {
aidlDevices.reserve(xsdcValues.getValue().size());
for (const eng_xsd::ValueType& xsdcValue : xsdcValues.getValue()) {
if (!xsdcValue.hasAndroid_type()) {
LOG(ERROR) << __func__ << " empty android type";
return unexpected(BAD_VALUE);
}
uint32_t integerValue;
if (!convertTo(xsdcValue.getAndroid_type(), integerValue)) {
LOG(ERROR) << __func__ << " failed to convert android type "
<< xsdcValue.getAndroid_type();
return unexpected(BAD_VALUE);
}
aidlDevices.push_back(
VALUE_OR_RETURN(legacy2aidl_audio_devices_t_AudioDeviceDescription(
static_cast<audio_devices_t>(integerValue))));
}
}
return aidlDevices;
}
ConversionResult<std::vector<AudioDeviceAddress>> convertDeviceAddressesToAidl(
const eng_xsd::CriterionTypeType& xsdcDeviceAddressesCriterionType) {
if (xsdcDeviceAddressesCriterionType.getValues().empty()) {
LOG(ERROR) << __func__ << " no values provided";
return unexpected(BAD_VALUE);
}
std::vector<AudioDeviceAddress> aidlDeviceAddresses;
for (eng_xsd::ValuesType xsdcValues : xsdcDeviceAddressesCriterionType.getValues()) {
aidlDeviceAddresses.reserve(xsdcValues.getValue().size());
for (const eng_xsd::ValueType& xsdcValue : xsdcValues.getValue()) {
aidlDeviceAddresses.push_back(
AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>(xsdcValue.getLiteral()));
}
}
return aidlDeviceAddresses;
}
ConversionResult<std::vector<AudioMode>> convertTelephonyModesToAidl(
const eng_xsd::CriterionTypeType& xsdcTelephonyModeCriterionType) {
if (xsdcTelephonyModeCriterionType.getValues().empty()) {
LOG(ERROR) << __func__ << " no values provided";
return unexpected(BAD_VALUE);
}
std::vector<AudioMode> aidlAudioModes;
for (eng_xsd::ValuesType xsdcValues : xsdcTelephonyModeCriterionType.getValues()) {
aidlAudioModes.reserve(xsdcValues.getValue().size());
for (const eng_xsd::ValueType& xsdcValue : xsdcValues.getValue()) {
int integerValue = xsdcValue.getNumerical();
if (!isValidAudioMode(AudioMode(integerValue))) {
LOG(ERROR) << __func__ << " invalid audio mode " << integerValue;
return unexpected(BAD_VALUE);
}
aidlAudioModes.push_back(AudioMode(integerValue));
}
}
return aidlAudioModes;
}
ConversionResult<std::vector<AudioPolicyForcedConfig>> convertForcedConfigsToAidl(
const eng_xsd::CriterionTypeType& xsdcForcedConfigCriterionType) {
if (xsdcForcedConfigCriterionType.getValues().empty()) {
LOG(ERROR) << __func__ << " no values provided";
return unexpected(BAD_VALUE);
}
std::vector<AudioPolicyForcedConfig> aidlForcedConfigs;
for (eng_xsd::ValuesType xsdcValues : xsdcForcedConfigCriterionType.getValues()) {
aidlForcedConfigs.reserve(xsdcValues.getValue().size());
for (const eng_xsd::ValueType& xsdcValue : xsdcValues.getValue()) {
int integerValue = xsdcValue.getNumerical();
if (!isValidAudioPolicyForcedConfig(AudioPolicyForcedConfig(integerValue))) {
LOG(ERROR) << __func__ << " invalid forced config mode " << integerValue;
return unexpected(BAD_VALUE);
}
aidlForcedConfigs.push_back(AudioPolicyForcedConfig(integerValue));
}
}
return aidlForcedConfigs;
}
ConversionResult<AudioPolicyForceUse> convertForceUseCriterionToAidl(
const std::string& xsdcCriterionName) {
if (!fastcmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForCommunication,
strlen(kXsdcForceConfigForCommunication))) {
return AudioPolicyForceUse::COMMUNICATION;
}
if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForMedia,
strlen(kXsdcForceConfigForMedia))) {
return AudioPolicyForceUse::MEDIA;
}
if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForRecord,
strlen(kXsdcForceConfigForRecord))) {
return AudioPolicyForceUse::RECORD;
}
if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForDock,
strlen(kXsdcForceConfigForDock))) {
return AudioPolicyForceUse::DOCK;
}
if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForSystem,
strlen(kXsdcForceConfigForSystem))) {
return AudioPolicyForceUse::SYSTEM;
}
if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForHdmiSystemAudio,
strlen(kXsdcForceConfigForHdmiSystemAudio))) {
return AudioPolicyForceUse::HDMI_SYSTEM_AUDIO;
}
if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForEncodedSurround,
strlen(kXsdcForceConfigForEncodedSurround))) {
return AudioPolicyForceUse::ENCODED_SURROUND;
}
if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForVibrateRinging,
strlen(kXsdcForceConfigForVibrateRinging))) {
return AudioPolicyForceUse::VIBRATE_RINGING;
}
LOG(ERROR) << __func__ << " unrecognized force use " << xsdcCriterionName;
return unexpected(BAD_VALUE);
}
ConversionResult<AudioHalCapCriterionV2> convertCapCriterionV2ToAidl(
const eng_xsd::CriterionType& xsdcCriterion,
const std::vector<eng_xsd::CriterionTypesType>& xsdcCriterionTypesVec) {
eng_xsd::CriterionTypeType xsdcCriterionType =
VALUE_OR_RETURN(getCriterionTypeByName(xsdcCriterion.getType(), xsdcCriterionTypesVec));
std::string defaultLiteralValue =
xsdcCriterion.has_default() ? xsdcCriterion.get_default() : "";
using Tag = AudioHalCapCriterionV2::Tag;
if (iequals(xsdcCriterion.getName(), toString(Tag::availableInputDevices))) {
return AudioHalCapCriterionV2::make<Tag::availableInputDevices>(
VALUE_OR_RETURN(convertDevicesToAidl(xsdcCriterionType)));
}
if (iequals(xsdcCriterion.getName(), toString(Tag::availableOutputDevices))) {
return AudioHalCapCriterionV2::make<Tag::availableOutputDevices>(
VALUE_OR_RETURN(convertDevicesToAidl(xsdcCriterionType)));
}
if (iequals(xsdcCriterion.getName(), toString(Tag::availableInputDevicesAddresses))) {
return AudioHalCapCriterionV2::make<Tag::availableInputDevicesAddresses>(
VALUE_OR_RETURN(convertDeviceAddressesToAidl(xsdcCriterionType)));
}
if (iequals(xsdcCriterion.getName(), toString(Tag::availableOutputDevicesAddresses))) {
return AudioHalCapCriterionV2::make<Tag::availableOutputDevicesAddresses>(
VALUE_OR_RETURN(convertDeviceAddressesToAidl(xsdcCriterionType)));
}
if (iequals(xsdcCriterion.getName(), toString(Tag::telephonyMode))) {
return AudioHalCapCriterionV2::make<Tag::telephonyMode>(
VALUE_OR_RETURN(convertTelephonyModesToAidl(xsdcCriterionType)));
}
if (!fastcmp<strncmp>(xsdcCriterion.getName().c_str(), kXsdcForceConfigForUse,
strlen(kXsdcForceConfigForUse))) {
return AudioHalCapCriterionV2::make<Tag::forceConfigForUse>(
VALUE_OR_RETURN(convertForceUseCriterionToAidl(xsdcCriterion.getName())),
VALUE_OR_RETURN(convertForcedConfigsToAidl(xsdcCriterionType)));
}
LOG(ERROR) << __func__ << " unrecognized criterion " << xsdcCriterion.getName();
return unexpected(BAD_VALUE);
}
ConversionResult<AudioHalCapCriterion> convertCapCriterionToAidl(
const eng_xsd::CriterionType& xsdcCriterion) {
AudioHalCapCriterion aidlCapCriterion;
aidlCapCriterion.name = xsdcCriterion.getName();
aidlCapCriterion.criterionTypeName = xsdcCriterion.getType();
aidlCapCriterion.defaultLiteralValue = xsdcCriterion.get_default();
aidlCapCriterion.defaultLiteralValue =
xsdcCriterion.has_default() ? xsdcCriterion.get_default() : "";
return aidlCapCriterion;
}
ConversionResult<std::string> convertCriterionTypeValueToAidl(
const eng_xsd::ValueType& xsdcCriterionTypeValue) {
return xsdcCriterionTypeValue.getLiteral();
}
ConversionResult<AudioHalCapCriterionType> convertCapCriterionTypeToAidl(
const eng_xsd::CriterionTypeType& xsdcCriterionType) {
AudioHalCapCriterionType aidlCapCriterionType;
aidlCapCriterionType.name = xsdcCriterionType.getName();
aidlCapCriterionType.isInclusive = !(static_cast<bool>(xsdcCriterionType.getType()));
aidlCapCriterionType.values = VALUE_OR_RETURN(
(convertWrappedCollectionToAidl<eng_xsd::ValuesType, eng_xsd::ValueType, std::string>(
xsdcCriterionType.getValues(), &eng_xsd::ValuesType::getValue,
&convertCriterionTypeValueToAidl)));
return aidlCapCriterionType;
}
ConversionResult<AudioHalVolumeCurve::CurvePoint> convertCurvePointToAidl(
const std::string& xsdcCurvePoint) {
AudioHalVolumeCurve::CurvePoint aidlCurvePoint{};

View File

@@ -0,0 +1,17 @@
package {
default_team: "trendy_team_android_media_audio_framework",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "hardware_interfaces_license"
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
default_applicable_licenses: ["hardware_interfaces_license"],
}
xsd_config {
name: "audio_policy_capengine_configuration_aidl_default",
srcs: ["PolicyConfigurableDomains.xsd"],
package_name: "android.audio.policy.capengine.configuration",
nullability: true,
root_elements: ["ConfigurableDomains"],
}

View File

@@ -0,0 +1,467 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- BEGIN W3cXmlAttributes.xsd -->
<xs:annotation>
<xs:documentation>
See http://www.w3.org/XML/1998/namespace.html and
http://www.w3.org/TR/REC-xml for information about this namespace.
This schema document describes the XML namespace, in a form
suitable for import by other schema documents.
Note that local names in this namespace are intended to be defined
only by the World Wide Web Consortium or its subgroups. The
following names are currently defined in this namespace and should
not be used with conflicting semantics by any Working Group,
specification, or document instance:
base (as an attribute name): denotes an attribute whose value
provides a URI to be used as the base for interpreting any
relative URIs in the scope of the element on which it
appears; its value is inherited. This name is reserved
by virtue of its definition in the XML Base specification.
id (as an attribute name): denotes an attribute whose value
should be interpreted as if declared to be of type ID.
The xml:id specification is not yet a W3C Recommendation,
but this attribute is included here to facilitate experimentation
with the mechanisms it proposes. Note that it is _not_ included
in the specialAttrs attribute group.
lang (as an attribute name): denotes an attribute whose value
is a language code for the natural language of the content of
any element; its value is inherited. This name is reserved
by virtue of its definition in the XML specification.
space (as an attribute name): denotes an attribute whose
value is a keyword indicating what whitespace processing
discipline is intended for the content of the element; its
value is inherited. This name is reserved by virtue of its
definition in the XML specification.
Father (in any context at all): denotes Jon Bosak, the chair of
the original XML Working Group. This name is reserved by
the following decision of the W3C XML Plenary and
XML Coordination groups:
In appreciation for his vision, leadership and dedication
the W3C XML Plenary on this 10th day of February, 2000
reserves for Jon Bosak in perpetuity the XML name
xml:Father
</xs:documentation>
</xs:annotation>
<xs:annotation>
<xs:documentation>This schema defines attributes and an attribute group
suitable for use by
schemas wishing to allow xml:base, xml:lang, xml:space or xml:id
attributes on elements they define.
To enable this, such a schema must import this schema
for the XML namespace, e.g. as follows:
&lt;schema . . .>
. . .
&lt;import namespace="http://www.w3.org/XML/1998/namespace"
schemaLocation="http://www.w3.org/2005/08/xml.xsd"/>
Subsequently, qualified reference to any of the attributes
or the group defined below will have the desired effect, e.g.
&lt;type . . .>
. . .
&lt;attributeGroup ref="xml:specialAttrs"/>
will define a type which will schema-validate an instance
element with any of those attributes</xs:documentation>
</xs:annotation>
<xs:annotation>
<xs:documentation>In keeping with the XML Schema WG's standard versioning
policy, this schema document will persist at
http://www.w3.org/2005/08/xml.xsd.
At the date of issue it can also be found at
http://www.w3.org/2001/xml.xsd.
The schema document at that URI may however change in the future,
in order to remain compatible with the latest version of XML Schema
itself, or with the XML namespace itself. In other words, if the XML
Schema or XML namespaces change, the version of this document at
http://www.w3.org/2001/xml.xsd will change
accordingly; the version at
http://www.w3.org/2005/08/xml.xsd will not change.
</xs:documentation>
</xs:annotation>
<xs:attribute name="lang">
<xs:annotation>
<xs:documentation>Attempting to install the relevant ISO 2- and 3-letter
codes as the enumerated possible values is probably never
going to be a realistic possibility. See
RFC 3066 at http://www.ietf.org/rfc/rfc3066.txt and the IANA registry
at http://www.iana.org/assignments/lang-tag-apps.htm for
further information.
The union allows for the 'un-declaration' of xml:lang with
the empty string.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:union memberTypes="xs:language">
<xs:simpleType name="langEnum">
<xs:restriction base="xs:string">
<xs:enumeration value=""/>
</xs:restriction>
</xs:simpleType>
</xs:union>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="space">
<xs:simpleType name="spaceEnum">
<xs:restriction base="xs:NCName">
<xs:enumeration value="default"/>
<xs:enumeration value="preserve"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="base" type="xs:anyURI">
<xs:annotation>
<xs:documentation>See http://www.w3.org/TR/xmlbase/ for
information about this attribute.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="id" type="xs:ID">
<xs:annotation>
<xs:documentation>See http://www.w3.org/TR/xml-id/ for
information about this attribute.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributeGroup name="specialAttrs">
<xs:attribute ref="xml:base"/>
<xs:attribute ref="xml:lang"/>
<xs:attribute ref="xml:space"/>
</xs:attributeGroup>
<!-- END W3cXmlAttributes.xsd -->
<!-- BEGIN ParameterSettings.xsd -->
<!-- BUG b/147297854 - removed "abstract" from type definition -->
<xs:complexType name="BooleanParameterType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="Name" type="ParameterNameEnumType" use="required"/>
</xs:extension>
<!--xs:restriction base="xs:string">
<xs:pattern value="([01][\s]*)+"/>
<xs:pattern value="((0x0|0x1)[\s]*)+"/>
<xs:attribute name="Name" type="xs:string" use="required"/>
</xs:restriction-->
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="IntegerParameterType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="Name" type="ParameterNameEnumType" use="required"/>
</xs:extension>
<!--xs:restriction base="xs:string">
<xs:pattern value="(0|([+-]?[1-9][0-9]*))(\s+(0|([+-]?[1-9][0-9]*)))*"/>
<xs:pattern value="(0x[0-9a-fA-F]+)(\s+(0x[0-9a-fA-F]+))*"/>
<xs:attribute name="Name" type="xs:string" use="required"/>
</xs:restriction-->
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="EnumParameterType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="Name" type="ParameterNameEnumType" use="required"/>
</xs:extension>
<!--xs:extension base="xs:string">
<xs:attribute name="Name" type="xs:string" use="required"/>
</xs:extension-->
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="PointParameterType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="Name" type="ParameterNameEnumType" use="required"/>
</xs:extension>
<!--xs:restriction base="xs:string">
<xs:pattern value="((0|[+-]?0\.[0-9]+|(([+-]?[1-9][0-9]*)(\.[0-9]+)?))([Ee][+-]?[0-9]+)?)(\s+(0|[+-]?0\.[0-9]+|(([+-]?[1-9][0-9]*)(\.[0-9]+)?))([Ee][+-]?[0-9]+)?)*"/>
<xs:pattern value="(0x[0-9a-fA-F]+)(\s+(0x[0-9a-fA-F]+))*"/>
<xs:attribute name="Name" type="xs:NMTOKEN" use="required"/>
</xs:restriction-->
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="BitParameterBlockType">
<xs:sequence>
<xs:element name="BitParameter" maxOccurs="unbounded" type="IntegerParameterType"/>
</xs:sequence>
<xs:attribute name="Name" type="ParameterNameEnumType" use="required"/>
</xs:complexType>
<xs:complexType name="StringParameterType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="Name" type="ParameterNameEnumType" use="required"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:group name="ParameterBlockGroup">
<xs:choice>
<xs:element name="BooleanParameter" type="BooleanParameterType"/>
<xs:element name="IntegerParameter" type="IntegerParameterType"/>
<xs:element name="EnumParameter" type="EnumParameterType"/>
<xs:element name="FixedPointParameter" type="PointParameterType"/>
<xs:element name="FloatingPointParameter" type="PointParameterType"/>
<xs:element name="BitParameterBlock" type="BitParameterBlockType">
<xs:unique name="BitParameterBlockSubElementsUniqueness">
<xs:selector xpath="*"/>
<xs:field xpath="@Name"/>
</xs:unique>
</xs:element>
<xs:element name="StringParameter" type="StringParameterType"/>
<!--xs:element name="Component" type="ParameterBlockType"/-->
<xs:element name="ParameterBlock" type="ParameterBlockType">
<xs:unique name="ParameterBlockSubElementsUniqueness">
<xs:selector xpath="*"/>
<xs:field xpath="@Name"/>
</xs:unique>
</xs:element>
</xs:choice>
</xs:group>
<xs:complexType name="ParameterBlockType">
<xs:sequence>
<xs:group ref="ParameterBlockGroup" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="Name" type="xs:NMTOKEN" use="required"/>
</xs:complexType>
<!-- END ParameterSettings.xsd -->
<!-- BEGIN ConfigurableDomain.xsd -->
<xs:complexType name="SelectionCriterionRuleType">
<xs:attribute name="SelectionCriterion" type="xs:NMTOKEN" use="required"/>
<xs:attribute name="MatchesWhen" use="required">
<xs:simpleType name="MatchesWhenEnum">
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="Is"/>
<xs:enumeration value="IsNot"/>
<xs:enumeration value="Includes"/>
<xs:enumeration value="Excludes"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="Value" use="required" type="xs:NMTOKEN"/>
</xs:complexType>
<xs:group name="RuleGroup">
<xs:choice>
<xs:element name="CompoundRule" type="CompoundRuleType"/>
<xs:element name="SelectionCriterionRule" type="SelectionCriterionRuleType"/>
</xs:choice>
</xs:group>
<xs:complexType name="CompoundRuleType">
<xs:sequence>
<xs:group ref="RuleGroup" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="Type">
<xs:simpleType name="TypeEnum">
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="Any"/>
<xs:enumeration value="All"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
<xs:complexType name="ConfigurationsType">
<xs:sequence>
<xs:element maxOccurs="unbounded" name="Configuration">
<xs:complexType>
<xs:sequence>
<xs:element name="CompoundRule" type="CompoundRuleType" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
<xs:attribute name="Name" use="required" type="xs:NCName"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:group name="ComponentGroup">
<xs:sequence>
<xs:group ref="ParameterBlockGroup"/>
</xs:sequence>
</xs:group>
<xs:complexType name="ComponentType">
<xs:sequence>
<xs:choice>
<xs:group ref="ComponentGroup" maxOccurs="unbounded"/>
<xs:element name="Subsystem" type="ComponentType" maxOccurs="unbounded"/>
</xs:choice>
</xs:sequence>
<xs:attribute name="Name" use="required" type="xs:NCName"/>
</xs:complexType>
<xs:complexType name="ConfigurableElementsType">
<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="ConfigurableElement">
<xs:complexType>
<xs:attribute name="Path" use="required">
<xs:simpleType>
<xs:restriction base="xs:anyURI">
<xs:pattern value="/.*[^/]"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="ConfigurableElementSettingsType">
<xs:choice>
<xs:element name="BooleanParameter" type="BooleanParameterType"/>
<xs:element name="IntegerParameter" type="IntegerParameterType"/>
<xs:element name="EnumParameter" type="EnumParameterType"/>
<xs:element name="FixedPointParameter" type="PointParameterType"/>
<xs:element name="FloatingPointParameter" type="PointParameterType"/>
<xs:element name="BitParameter" type="IntegerParameterType"/>
<xs:element name="BitParameterBlock" type="BitParameterBlockType">
<xs:unique name="BitParameterBlockSubElementsUniqueness">
<xs:selector xpath="*"/>
<xs:field xpath="@Name"/>
</xs:unique>
</xs:element>
<xs:element name="StringParameter" type="StringParameterType"/>
<!--xs:element name="Component" type="ParameterBlockType"/-->
<xs:element name="ParameterBlock" type="ParameterBlockType">
<xs:unique name="ParameterBlockSubElementsUniqueness">
<xs:selector xpath="*"/>
<xs:field xpath="@Name"/>
</xs:unique>
</xs:element>
</xs:choice>
<!--xs:choice>
<xs:element name="BitParameter" type="IntegerParameterType"/>
<xs:group ref="ComponentGroup"/>
</xs:choice-->
<xs:attribute name="Path" use="required">
<xs:simpleType>
<xs:restriction base="xs:anyURI">
<xs:pattern value="/.*[^/]"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
<xs:complexType name="SettingsType">
<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="Configuration">
<xs:complexType>
<xs:sequence>
<xs:element name="ConfigurableElement" minOccurs="0" maxOccurs="unbounded" type="ConfigurableElementSettingsType"/>
</xs:sequence>
<xs:attribute name="Name" use="required" type="xs:NCName"/>
</xs:complexType>
<xs:unique name="ConfigurableElementUniqueness">
<xs:selector xpath="ConfigurableElement"/>
<xs:field xpath="@Path"/>
</xs:unique>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="ConfigurableDomainType">
<xs:sequence>
<xs:element name="Configurations" type="ConfigurationsType"/>
<xs:element name="ConfigurableElements" type="ConfigurableElementsType"/>
<xs:element name="Settings" type="SettingsType" minOccurs="0"/>
</xs:sequence>
<xs:attribute name="Name" use="required" type="xs:NCName"/>
<xs:attribute name="SequenceAware" use="optional" type="xs:boolean" default="false"/>
</xs:complexType>
<xs:element name="ConfigurableDomain" type="ConfigurableDomainType"/>
<!-- END ConfigurableDomain.xsd -->
<!-- BEGIN ConfigurableDomains.xsd -->
<xs:element name="ConfigurableDomains">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="ConfigurableDomain" type="ConfigurableDomainType">
<xs:key name="ConfigurableElementKey">
<xs:selector xpath="ConfigurableElements/ConfigurableElement"/>
<xs:field xpath="@Path"/>
</xs:key>
<xs:keyref refer="ConfigurableElementKey" name="ConfigurableDomainReference">
<xs:selector xpath="Settings/Configuration/ConfigurableElement"/>
<xs:field xpath="@Path"/>
</xs:keyref>
<xs:key name="ConfigurationKey">
<xs:selector xpath="Configurations/Configuration"/>
<xs:field xpath="@Name"/>
</xs:key>
<xs:keyref refer="ConfigurationKey" name="ConfigurationReference2">
<xs:selector xpath="ConfigurableElements/ConfigurableElement/Configuration"/>
<xs:field xpath="@Name"/>
</xs:keyref>
<xs:keyref refer="ConfigurationKey" name="ConfigurationReference">
<xs:selector xpath="Settings/Configuration"/>
<xs:field xpath="@Name"/>
</xs:keyref>
</xs:element>
</xs:sequence>
<xs:attribute name="SystemClassName" use="required" type="xs:NCName"/>
</xs:complexType>
<xs:unique name="ConfigurableDomainUniqueness">
<xs:selector xpath="ConfigurableDomain"/>
<xs:field xpath="@Name"/>
</xs:unique>
</xs:element>
<!-- END ConfigurableDomains.xsd -->
<xs:simpleType name="ParameterNameEnumType">
<xs:restriction base="xs:string">
<xs:enumeration value="volume_profile"/>
<xs:enumeration value="communication"/>
<xs:enumeration value="ambient"/>
<xs:enumeration value="builtin_mic"/>
<xs:enumeration value="bluetooth_sco_headset"/>
<xs:enumeration value="wired_headset"/>
<xs:enumeration value="hdmi"/>
<xs:enumeration value="telephony_rx"/>
<xs:enumeration value="back_mic"/>
<xs:enumeration value="remote_submix"/>
<xs:enumeration value="anlg_dock_headset"/>
<xs:enumeration value="dgtl_dock_headset"/>
<xs:enumeration value="usb_accessory"/>
<xs:enumeration value="usb_device"/>
<xs:enumeration value="fm_tuner"/>
<xs:enumeration value="tv_tuner"/>
<xs:enumeration value="line"/>
<xs:enumeration value="spdif"/>
<xs:enumeration value="bluetooth_a2dp" />
<xs:enumeration value="loopback" />
<xs:enumeration value="ip" />
<xs:enumeration value="bus" />
<xs:enumeration value="proxy"/>
<xs:enumeration value="usb_headset"/>
<xs:enumeration value="bluetooth_ble"/>
<xs:enumeration value="hdmi_arc"/>
<xs:enumeration value="echo_reference"/>
<xs:enumeration value="ble_headset"/>
<xs:enumeration value="stub"/>
<xs:enumeration value="hdmi_earc"/>
<xs:enumeration value="device_address"/>
<xs:enumeration value="earpiece" />
<xs:enumeration value="speaker" />
<xs:enumeration value="wired_headphone" />
<xs:enumeration value="bluetooth_sco" />
<xs:enumeration value="bluetooth_sco_carkit"/>
<xs:enumeration value="bluetooth_a2dp_headphones"/>
<xs:enumeration value="bluetooth_a2dp_speaker"/>
<xs:enumeration value="telephony_tx"/>
<xs:enumeration value="fm"/>
<xs:enumeration value="aux_line"/>
<xs:enumeration value="speaker_safe"/>
<xs:enumeration value="hearing_aid" />
<xs:enumeration value="echo_canceller" />
<xs:enumeration value="ble_speaker" />
<xs:enumeration value="ble_broadcast" />
</xs:restriction>
</xs:simpleType>
</xs:schema>

View File

@@ -0,0 +1,264 @@
// Signature format: 2.0
package android.audio.policy.capengine.configuration {
public class BitParameterBlockType {
ctor public BitParameterBlockType();
method @Nullable public java.util.List<android.audio.policy.capengine.configuration.IntegerParameterType> getBitParameter();
method @Nullable public android.audio.policy.capengine.configuration.ParameterNameEnumType getName();
method public void setName(@Nullable android.audio.policy.capengine.configuration.ParameterNameEnumType);
}
public class BooleanParameterType {
ctor public BooleanParameterType();
method @Nullable public android.audio.policy.capengine.configuration.ParameterNameEnumType getName();
method @Nullable public String getValue();
method public void setName(@Nullable android.audio.policy.capengine.configuration.ParameterNameEnumType);
method public void setValue(@Nullable String);
}
public class ComponentType {
ctor public ComponentType();
method @Nullable public String getName();
method @Nullable public java.util.List<android.audio.policy.capengine.configuration.ComponentType> getSubsystem_optional();
method public void setName(@Nullable String);
}
public class CompoundRuleType {
ctor public CompoundRuleType();
method @Nullable public android.audio.policy.capengine.configuration.CompoundRuleType getCompoundRule_optional();
method @Nullable public android.audio.policy.capengine.configuration.SelectionCriterionRuleType getSelectionCriterionRule_optional();
method @Nullable public android.audio.policy.capengine.configuration.TypeEnum getType();
method public void setCompoundRule_optional(@Nullable android.audio.policy.capengine.configuration.CompoundRuleType);
method public void setSelectionCriterionRule_optional(@Nullable android.audio.policy.capengine.configuration.SelectionCriterionRuleType);
method public void setType(@Nullable android.audio.policy.capengine.configuration.TypeEnum);
}
public class ConfigurableDomainType {
ctor public ConfigurableDomainType();
method @Nullable public android.audio.policy.capengine.configuration.ConfigurableElementsType getConfigurableElements();
method @Nullable public android.audio.policy.capengine.configuration.ConfigurationsType getConfigurations();
method @Nullable public String getName();
method @Nullable public boolean getSequenceAware();
method @Nullable public android.audio.policy.capengine.configuration.SettingsType getSettings();
method public void setConfigurableElements(@Nullable android.audio.policy.capengine.configuration.ConfigurableElementsType);
method public void setConfigurations(@Nullable android.audio.policy.capengine.configuration.ConfigurationsType);
method public void setName(@Nullable String);
method public void setSequenceAware(@Nullable boolean);
method public void setSettings(@Nullable android.audio.policy.capengine.configuration.SettingsType);
}
public class ConfigurableDomains {
ctor public ConfigurableDomains();
method @Nullable public java.util.List<android.audio.policy.capengine.configuration.ConfigurableDomainType> getConfigurableDomain();
method @Nullable public String getSystemClassName();
method public void setSystemClassName(@Nullable String);
}
public class ConfigurableElementSettingsType {
ctor public ConfigurableElementSettingsType();
method @Nullable public android.audio.policy.capengine.configuration.BitParameterBlockType getBitParameterBlock_optional();
method @Nullable public android.audio.policy.capengine.configuration.IntegerParameterType getBitParameter_optional();
method @Nullable public android.audio.policy.capengine.configuration.BooleanParameterType getBooleanParameter_optional();
method @Nullable public android.audio.policy.capengine.configuration.EnumParameterType getEnumParameter_optional();
method @Nullable public android.audio.policy.capengine.configuration.PointParameterType getFixedPointParameter_optional();
method @Nullable public android.audio.policy.capengine.configuration.PointParameterType getFloatingPointParameter_optional();
method @Nullable public android.audio.policy.capengine.configuration.IntegerParameterType getIntegerParameter_optional();
method @Nullable public android.audio.policy.capengine.configuration.ParameterBlockType getParameterBlock_optional();
method @Nullable public String getPath();
method @Nullable public android.audio.policy.capengine.configuration.StringParameterType getStringParameter_optional();
method public void setBitParameterBlock_optional(@Nullable android.audio.policy.capengine.configuration.BitParameterBlockType);
method public void setBitParameter_optional(@Nullable android.audio.policy.capengine.configuration.IntegerParameterType);
method public void setBooleanParameter_optional(@Nullable android.audio.policy.capengine.configuration.BooleanParameterType);
method public void setEnumParameter_optional(@Nullable android.audio.policy.capengine.configuration.EnumParameterType);
method public void setFixedPointParameter_optional(@Nullable android.audio.policy.capengine.configuration.PointParameterType);
method public void setFloatingPointParameter_optional(@Nullable android.audio.policy.capengine.configuration.PointParameterType);
method public void setIntegerParameter_optional(@Nullable android.audio.policy.capengine.configuration.IntegerParameterType);
method public void setParameterBlock_optional(@Nullable android.audio.policy.capengine.configuration.ParameterBlockType);
method public void setPath(@Nullable String);
method public void setStringParameter_optional(@Nullable android.audio.policy.capengine.configuration.StringParameterType);
}
public class ConfigurableElementsType {
ctor public ConfigurableElementsType();
method @Nullable public java.util.List<android.audio.policy.capengine.configuration.ConfigurableElementsType.ConfigurableElement> getConfigurableElement();
}
public static class ConfigurableElementsType.ConfigurableElement {
ctor public ConfigurableElementsType.ConfigurableElement();
method @Nullable public String getPath();
method public void setPath(@Nullable String);
}
public class ConfigurationsType {
ctor public ConfigurationsType();
method @Nullable public java.util.List<android.audio.policy.capengine.configuration.ConfigurationsType.Configuration> getConfiguration();
}
public static class ConfigurationsType.Configuration {
ctor public ConfigurationsType.Configuration();
method @Nullable public android.audio.policy.capengine.configuration.CompoundRuleType getCompoundRule();
method @Nullable public String getName();
method public void setCompoundRule(@Nullable android.audio.policy.capengine.configuration.CompoundRuleType);
method public void setName(@Nullable String);
}
public class EnumParameterType {
ctor public EnumParameterType();
method @Nullable public android.audio.policy.capengine.configuration.ParameterNameEnumType getName();
method @Nullable public String getValue();
method public void setName(@Nullable android.audio.policy.capengine.configuration.ParameterNameEnumType);
method public void setValue(@Nullable String);
}
public class IntegerParameterType {
ctor public IntegerParameterType();
method @Nullable public android.audio.policy.capengine.configuration.ParameterNameEnumType getName();
method @Nullable public String getValue();
method public void setName(@Nullable android.audio.policy.capengine.configuration.ParameterNameEnumType);
method public void setValue(@Nullable String);
}
public enum LangEnum {
method @NonNull public String getRawName();
enum_constant public static final android.audio.policy.capengine.configuration.LangEnum EMPTY;
}
public enum MatchesWhenEnum {
method @NonNull public String getRawName();
enum_constant public static final android.audio.policy.capengine.configuration.MatchesWhenEnum Excludes;
enum_constant public static final android.audio.policy.capengine.configuration.MatchesWhenEnum Includes;
enum_constant public static final android.audio.policy.capengine.configuration.MatchesWhenEnum Is;
enum_constant public static final android.audio.policy.capengine.configuration.MatchesWhenEnum IsNot;
}
public class ParameterBlockType {
ctor public ParameterBlockType();
method @Nullable public android.audio.policy.capengine.configuration.BitParameterBlockType getBitParameterBlock_optional();
method @Nullable public android.audio.policy.capengine.configuration.BooleanParameterType getBooleanParameter_optional();
method @Nullable public android.audio.policy.capengine.configuration.EnumParameterType getEnumParameter_optional();
method @Nullable public android.audio.policy.capengine.configuration.PointParameterType getFixedPointParameter_optional();
method @Nullable public android.audio.policy.capengine.configuration.PointParameterType getFloatingPointParameter_optional();
method @Nullable public android.audio.policy.capengine.configuration.IntegerParameterType getIntegerParameter_optional();
method @Nullable public String getName();
method @Nullable public android.audio.policy.capengine.configuration.ParameterBlockType getParameterBlock_optional();
method @Nullable public android.audio.policy.capengine.configuration.StringParameterType getStringParameter_optional();
method public void setBitParameterBlock_optional(@Nullable android.audio.policy.capengine.configuration.BitParameterBlockType);
method public void setBooleanParameter_optional(@Nullable android.audio.policy.capengine.configuration.BooleanParameterType);
method public void setEnumParameter_optional(@Nullable android.audio.policy.capengine.configuration.EnumParameterType);
method public void setFixedPointParameter_optional(@Nullable android.audio.policy.capengine.configuration.PointParameterType);
method public void setFloatingPointParameter_optional(@Nullable android.audio.policy.capengine.configuration.PointParameterType);
method public void setIntegerParameter_optional(@Nullable android.audio.policy.capengine.configuration.IntegerParameterType);
method public void setName(@Nullable String);
method public void setParameterBlock_optional(@Nullable android.audio.policy.capengine.configuration.ParameterBlockType);
method public void setStringParameter_optional(@Nullable android.audio.policy.capengine.configuration.StringParameterType);
}
public enum ParameterNameEnumType {
method @NonNull public String getRawName();
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType ambient;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType anlg_dock_headset;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType aux_line;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType back_mic;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType ble_broadcast;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType ble_headset;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType ble_speaker;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType bluetooth_a2dp;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType bluetooth_a2dp_headphones;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType bluetooth_a2dp_speaker;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType bluetooth_ble;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType bluetooth_sco;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType bluetooth_sco_carkit;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType bluetooth_sco_headset;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType builtin_mic;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType bus;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType communication;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType device_address;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType dgtl_dock_headset;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType earpiece;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType echo_canceller;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType echo_reference;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType fm;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType fm_tuner;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType hdmi;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType hdmi_arc;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType hdmi_earc;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType hearing_aid;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType ip;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType line;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType loopback;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType proxy;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType remote_submix;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType spdif;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType speaker;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType speaker_safe;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType stub;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType telephony_rx;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType telephony_tx;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType tv_tuner;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType usb_accessory;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType usb_device;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType usb_headset;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType volume_profile;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType wired_headphone;
enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType wired_headset;
}
public class PointParameterType {
ctor public PointParameterType();
method @Nullable public android.audio.policy.capengine.configuration.ParameterNameEnumType getName();
method @Nullable public String getValue();
method public void setName(@Nullable android.audio.policy.capengine.configuration.ParameterNameEnumType);
method public void setValue(@Nullable String);
}
public class SelectionCriterionRuleType {
ctor public SelectionCriterionRuleType();
method @Nullable public android.audio.policy.capengine.configuration.MatchesWhenEnum getMatchesWhen();
method @Nullable public String getSelectionCriterion();
method @Nullable public String getValue();
method public void setMatchesWhen(@Nullable android.audio.policy.capengine.configuration.MatchesWhenEnum);
method public void setSelectionCriterion(@Nullable String);
method public void setValue(@Nullable String);
}
public class SettingsType {
ctor public SettingsType();
method @Nullable public java.util.List<android.audio.policy.capengine.configuration.SettingsType.Configuration> getConfiguration();
}
public static class SettingsType.Configuration {
ctor public SettingsType.Configuration();
method @Nullable public java.util.List<android.audio.policy.capengine.configuration.ConfigurableElementSettingsType> getConfigurableElement();
method @Nullable public String getName();
method public void setName(@Nullable String);
}
public enum SpaceEnum {
method @NonNull public String getRawName();
enum_constant public static final android.audio.policy.capengine.configuration.SpaceEnum _default;
enum_constant public static final android.audio.policy.capengine.configuration.SpaceEnum preserve;
}
public class StringParameterType {
ctor public StringParameterType();
method @Nullable public android.audio.policy.capengine.configuration.ParameterNameEnumType getName();
method @Nullable public String getValue();
method public void setName(@Nullable android.audio.policy.capengine.configuration.ParameterNameEnumType);
method public void setValue(@Nullable String);
}
public enum TypeEnum {
method @NonNull public String getRawName();
enum_constant public static final android.audio.policy.capengine.configuration.TypeEnum All;
enum_constant public static final android.audio.policy.capengine.configuration.TypeEnum Any;
}
public class XmlParser {
ctor public XmlParser();
method @Nullable public static android.audio.policy.capengine.configuration.ConfigurableDomains readConfigurableDomains(@NonNull java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method @Nullable public static String readText(@NonNull org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public static void skip(@NonNull org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
}
}

View File

@@ -0,0 +1 @@
// Signature format: 2.0

View File

@@ -162,7 +162,9 @@ package android.audio.policy.engine.configuration {
public static class ProductStrategies.ProductStrategy {
ctor public ProductStrategies.ProductStrategy();
method @Nullable public java.util.List<android.audio.policy.engine.configuration.AttributesGroup> getAttributesGroup();
method @Nullable public int getId();
method @Nullable public String getName();
method public void setId(@Nullable int);
method public void setName(@Nullable String);
}

View File

@@ -105,6 +105,7 @@
<xs:element name="AttributesGroup" type="AttributesGroup" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required"/>
<xs:attribute name="id" type="xs:int" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
@@ -188,6 +189,19 @@
</xs:sequence>
</xs:complexType>
<xs:complexType name="valueType">
<xs:annotation>
<xs:documentation xml:lang="en">
Criterion type is provided as a tuple of 'human readable' string (referred as the
literal part, that will allow to express 'human readable' rules, numerical value
associated in order to improve performances of the parameter framework library used,
and an optional android type.
This android type is reserved for device type mapping with parameter framework
representation on a bitfield (Only one bit is expected to represent a device) and
android representation of a type that may use several bits.
The lookup table will allow wrap android device type to parameter framework device
types data model.
</xs:documentation>
</xs:annotation>
<xs:attribute name="literal" type="xs:string" use="required"/>
<xs:attribute name="numerical" type="xs:long" use="required"/>
<xs:attribute name="android_type" type="longDecimalOrHexType" use="optional"/>

View File

@@ -0,0 +1,76 @@
/*
* Copyright (C) 2024 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.
*/
#pragma once
#include <aidl/android/hardware/audio/core/BnConfig.h>
#include <aidl/android/media/audio/common/AudioHalEngineConfig.h>
#include <system/audio_config.h>
#include <android_audio_policy_capengine_configuration.h>
#include <android_audio_policy_capengine_configuration_enums.h>
#include "EngineConfigXmlConverter.h"
namespace aidl::android::hardware::audio::core::internal {
namespace capconfiguration = ::android::audio::policy::capengine::configuration;
namespace aidlcommon = ::aidl::android::media::audio::common;
class CapEngineConfigXmlConverter {
public:
explicit CapEngineConfigXmlConverter(const std::string& configFilePath)
: mConverter(configFilePath, &capconfiguration::readConfigurableDomains) {
if (mConverter.getXsdcConfig()) {
init();
}
}
std::string getError() const { return mConverter.getError(); }
::android::status_t getStatus() const { return mConverter.getStatus(); }
std::optional<
std::vector<std::optional<::aidl::android::media::audio::common::AudioHalCapDomain>>>&
getAidlCapEngineConfig();
private:
ConversionResult<std::vector<aidlcommon::AudioHalCapParameter>> convertSettingToAidl(
const capconfiguration::SettingsType::Configuration& xsdcSetting);
ConversionResult<std::vector<aidlcommon::AudioHalCapConfiguration>> convertConfigurationsToAidl(
const std::vector<capconfiguration::ConfigurationsType>& xsdcConfigurationsVec,
const std::vector<capconfiguration::SettingsType>& xsdcSettingsVec);
ConversionResult<aidlcommon::AudioHalCapConfiguration> convertConfigurationToAidl(
const capconfiguration::ConfigurationsType::Configuration& xsdcConfiguration,
const capconfiguration::SettingsType::Configuration& xsdcSettingConfiguration);
ConversionResult<aidlcommon::AudioHalCapParameter> convertParamToAidl(
const capconfiguration::ConfigurableElementSettingsType& element);
ConversionResult<aidlcommon::AudioHalCapConfiguration> convertConfigurationToAidl(
const capconfiguration::ConfigurationsType::Configuration& xsdcConfiguration);
ConversionResult<aidlcommon::AudioHalCapDomain> convertConfigurableDomainToAidl(
const capconfiguration::ConfigurableDomainType& xsdcConfigurableDomain);
const std::optional<capconfiguration::ConfigurableDomains>& getXsdcConfig() {
return mConverter.getXsdcConfig();
}
void init();
std::optional<std::vector<std::optional<aidlcommon::AudioHalCapDomain>>> mAidlCapDomains;
XmlConverter<capconfiguration::ConfigurableDomains> mConverter;
};
} // namespace aidl::android::hardware::audio::core::internal

View File

@@ -59,6 +59,7 @@ class EngineConfigXmlConverter {
ConversionResult<::aidl::android::media::audio::common::AudioHalProductStrategy>
convertProductStrategyToAidl(const ::android::audio::policy::engine::configuration::
ProductStrategies::ProductStrategy& xsdcProductStrategy);
ConversionResult<int> convertProductStrategyIdToAidl(int xsdcId);
ConversionResult<int> convertProductStrategyNameToAidl(
const std::string& xsdcProductStrategyName);
ConversionResult<::aidl::android::media::audio::common::AudioHalVolumeCurve>

View File

@@ -105,6 +105,19 @@ static ConversionResult<std::vector<A>> convertWrappedCollectionToAidl(
return resultAidlTypeVec;
}
template <typename X, typename A>
static ConversionResult<std::vector<std::optional<A>>> convertCollectionToAidlOptionalValues(
const std::vector<X>& xsdcTypeVec,
std::function<ConversionResult<A>(const X&)> convertToAidl) {
std::vector<std::optional<A>> resultAidlTypeVec;
resultAidlTypeVec.reserve(xsdcTypeVec.size());
for (const X& xsdcType : xsdcTypeVec) {
resultAidlTypeVec.push_back(
std::optional<A>(std::move(VALUE_OR_FATAL(convertToAidl(xsdcType)))));
}
return resultAidlTypeVec;
}
template <typename X, typename A>
static ConversionResult<std::vector<A>> convertCollectionToAidl(
const std::vector<X>& xsdcTypeVec,

View File

@@ -4,6 +4,7 @@
#include <aidl/android/media/audio/common/AudioHalCapCriterion.h>
#include <aidl/android/media/audio/common/AudioHalCapCriterionType.h>
#include <aidl/android/media/audio/common/AudioHalCapCriterionV2.h>
#include <aidl/android/media/audio/common/AudioHalVolumeCurve.h>
#include <aidl/android/media/audio/common/AudioPort.h>
#include <android_audio_policy_configuration.h>
@@ -15,15 +16,40 @@
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);
namespace engineconfiguration = ::android::audio::policy::engine::configuration;
namespace aidlaudiocommon = ::aidl::android::media::audio::common;
static constexpr const char kXsdcForceConfigForUse[] = "ForceUseFor";
ConversionResult<aidlaudiocommon::AudioPolicyForceUse> convertForceUseCriterionToAidl(
const std::string& xsdcCriterionName);
ConversionResult<aidlaudiocommon::AudioPolicyForcedConfig> convertForcedConfigToAidl(
const std::string& xsdcForcedConfigCriterionType);
ConversionResult<aidlaudiocommon::AudioDeviceAddress> convertDeviceAddressToAidl(
const std::string& xsdcAddress);
ConversionResult<aidlaudiocommon::AudioMode> convertTelephonyModeToAidl(
const std::string& xsdcModeCriterionType);
ConversionResult<aidlaudiocommon::AudioDeviceDescription> convertDeviceTypeToAidl(
const std::string& xType);
ConversionResult<std::vector<std::optional<aidlaudiocommon::AudioHalCapCriterionV2>>>
convertCapCriteriaCollectionToAidl(
const std::vector<engineconfiguration::CriteriaType>& xsdcCriteriaVec,
const std::vector<engineconfiguration::CriterionTypesType>& xsdcCriterionTypesVec);
ConversionResult<aidlaudiocommon::AudioHalCapCriterionV2> convertCapCriterionV2ToAidl(
const engineconfiguration::CriterionType& xsdcCriterion,
const std::vector<engineconfiguration::CriterionTypesType>& xsdcCriterionTypesVec);
ConversionResult<aidlaudiocommon::AudioHalVolumeCurve::CurvePoint> convertCurvePointToAidl(
const std::string& xsdcCurvePoint);
ConversionResult<std::unique_ptr<Module::Configuration>> convertModuleConfigToAidl(
const ::android::audio::policy::configuration::Modules::Module& moduleConfig);
ConversionResult<aidlaudiocommon::AudioUsage> convertAudioUsageToAidl(
const engineconfiguration::UsageEnumType& xsdcUsage);
ConversionResult<aidlaudiocommon::AudioContentType> convertAudioContentTypeToAidl(
const engineconfiguration::ContentType& xsdcContentType);
ConversionResult<aidlaudiocommon::AudioSource> convertAudioSourceToAidl(
const engineconfiguration::SourceEnumType& xsdcSourceType);
ConversionResult<aidlaudiocommon::AudioStreamType> convertAudioStreamTypeToAidl(
const engineconfiguration::Stream& xsdStreamType);
ConversionResult<int32_t> convertAudioFlagsToAidl(
const std::vector<engineconfiguration::FlagType>& xsdcFlagTypeVec);
} // namespace aidl::android::hardware::audio::core::internal

View File

@@ -38,16 +38,24 @@ using aidl::android::hardware::audio::common::isDefaultAudioFormat;
using aidl::android::hardware::audio::core::IConfig;
using aidl::android::hardware::audio::core::SurroundSoundConfig;
using aidl::android::media::audio::common::AudioAttributes;
using aidl::android::media::audio::common::AudioDeviceAddress;
using aidl::android::media::audio::common::AudioDeviceDescription;
using aidl::android::media::audio::common::AudioFlag;
using aidl::android::media::audio::common::AudioFormatDescription;
using aidl::android::media::audio::common::AudioFormatType;
using aidl::android::media::audio::common::AudioHalAttributesGroup;
using aidl::android::media::audio::common::AudioHalCapCriterion;
using aidl::android::media::audio::common::AudioHalCapCriterionType;
using aidl::android::media::audio::common::AudioHalCapConfiguration;
using aidl::android::media::audio::common::AudioHalCapCriterionV2;
using aidl::android::media::audio::common::AudioHalCapDomain;
using aidl::android::media::audio::common::AudioHalCapParameter;
using aidl::android::media::audio::common::AudioHalCapRule;
using aidl::android::media::audio::common::AudioHalEngineConfig;
using aidl::android::media::audio::common::AudioHalProductStrategy;
using aidl::android::media::audio::common::AudioHalVolumeCurve;
using aidl::android::media::audio::common::AudioHalVolumeGroup;
using aidl::android::media::audio::common::AudioMode;
using aidl::android::media::audio::common::AudioPolicyForceUse;
using aidl::android::media::audio::common::AudioPolicyForcedConfig;
using aidl::android::media::audio::common::AudioProductStrategyType;
using aidl::android::media::audio::common::AudioSource;
using aidl::android::media::audio::common::AudioStreamType;
@@ -256,48 +264,318 @@ class AudioCoreConfig : public testing::TestWithParam<std::string> {
}
/**
* Verify defaultLiteralValue is empty for inclusive criterion.
* Verify criterion provides a non empty value list.
* Verify logic rule provided is the expected one.
*/
void ValidateAudioHalCapCriterion(const AudioHalCapCriterion& criterion,
const AudioHalCapCriterionType& criterionType) {
if (criterionType.isInclusive) {
EXPECT_TRUE(criterion.defaultLiteralValue.empty());
void ValidateAudioHalCapCriterion(const AudioHalCapCriterionV2& criterionV2) {
switch (criterionV2.getTag()) {
case AudioHalCapCriterionV2::availableInputDevices: {
auto criterion = criterionV2.get<AudioHalCapCriterionV2::availableInputDevices>();
EXPECT_FALSE(criterion.values.empty());
EXPECT_EQ(criterion.logic, AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE);
break;
}
case AudioHalCapCriterionV2::availableOutputDevices: {
auto criterion = criterionV2.get<AudioHalCapCriterionV2::availableOutputDevices>();
EXPECT_FALSE(criterion.values.empty());
EXPECT_EQ(criterion.logic, AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE);
break;
}
case AudioHalCapCriterionV2::availableInputDevicesAddresses: {
auto criterion =
criterionV2.get<AudioHalCapCriterionV2::availableInputDevicesAddresses>();
EXPECT_FALSE(criterion.values.empty());
EXPECT_EQ(criterion.logic, AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE);
break;
}
case AudioHalCapCriterionV2::availableOutputDevicesAddresses: {
auto criterion =
criterionV2.get<AudioHalCapCriterionV2::availableOutputDevicesAddresses>();
EXPECT_FALSE(criterion.values.empty());
EXPECT_EQ(criterion.logic, AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE);
break;
}
case AudioHalCapCriterionV2::telephonyMode: {
auto criterion = criterionV2.get<AudioHalCapCriterionV2::telephonyMode>();
EXPECT_FALSE(criterion.values.empty());
EXPECT_EQ(criterion.logic, AudioHalCapCriterionV2::LogicalDisjunction::EXCLUSIVE);
break;
}
case AudioHalCapCriterionV2::forceConfigForUse: {
auto criterion = criterionV2.get<AudioHalCapCriterionV2::forceConfigForUse>();
EXPECT_FALSE(criterion.values.empty());
EXPECT_EQ(criterion.logic, AudioHalCapCriterionV2::LogicalDisjunction::EXCLUSIVE);
break;
}
default:
ADD_FAILURE() << "Invalid criterion tag " << toString(criterionV2.getTag());
}
}
/**
* Verify values only contain alphanumeric characters.
* Verify the rule involve the right matching logic according to the criterion logic.
* @param matchingRule logic followed by the rule
* @param logicalDisjunction logic exposed by the criterion
*/
void ValidateAudioHalCapCriterionType(const AudioHalCapCriterionType& criterionType) {
auto isNotAlnum = [](const char& c) { return !isalnum(c); };
for (const std::string& value : criterionType.values) {
EXPECT_EQ(find_if(value.begin(), value.end(), isNotAlnum), value.end());
void ValidateAudioHalCapRuleMatchingRule(
const AudioHalCapRule::MatchingRule matchingRule,
const AudioHalCapCriterionV2::LogicalDisjunction logicalDisjunction) {
if (logicalDisjunction == AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE) {
EXPECT_TRUE(matchingRule == AudioHalCapRule::MatchingRule::EXCLUDES ||
matchingRule == AudioHalCapRule::MatchingRule::INCLUDES);
} else if (logicalDisjunction == AudioHalCapCriterionV2::LogicalDisjunction::EXCLUSIVE) {
EXPECT_TRUE(matchingRule == AudioHalCapRule::MatchingRule::IS ||
matchingRule == AudioHalCapRule::MatchingRule::IS_NOT);
} else {
ADD_FAILURE() << "Invalid criterion Logical rule";
}
}
/**
* Verify each criterionType has a unique name.
* Verify each criterion has a unique name.
* Verify each criterion maps to a criterionType.
* Verify each criterionType is used in a criterion.
* Validate contained types.
* Verify that the value and the matching rule are supported by the given criterion
*/
template <typename CriterionV2, typename Value>
void validateAudioHalCapRule(CriterionV2 criterionV2, Value value,
const AudioHalCapRule::MatchingRule matchingRule) {
ValidateAudioHalCapRuleMatchingRule(matchingRule, criterionV2.logic);
EXPECT_FALSE(criterionV2.values.empty());
auto values = criterionV2.values;
auto valueIt = find_if(values.begin(), values.end(),
[&](const auto& typedValue) { return typedValue == value; });
EXPECT_NE(valueIt, values.end());
}
/**
* Verify rule involves a supported criterion.
* Verify rule involves supported logic keyword according to logic rule exposed by the
* criterion.
* Verify rule involves a value supported by the associated criterion.
*/
void ValidateAudioHalConfigurationRule(
const AudioHalCapRule& rule,
const std::vector<std::optional<AudioHalCapCriterionV2>>& criteria) {
const auto& compoundRule = rule.compoundRule;
using TypeTag = AudioHalCapCriterionV2::Type::Tag;
if (rule.nestedRules.empty() && rule.criterionRules.empty()) {
EXPECT_EQ(compoundRule, AudioHalCapRule::CompoundRule::ALL);
}
EXPECT_TRUE(compoundRule == AudioHalCapRule::CompoundRule::ANY ||
compoundRule == AudioHalCapRule::CompoundRule::ALL);
for (const auto& nestedRule : rule.nestedRules) {
ValidateAudioHalConfigurationRule(nestedRule, criteria);
}
for (const auto& criterionRule : rule.criterionRules) {
auto selectionCriterion = criterionRule.criterion;
auto criterionValue = criterionRule.criterionTypeValue;
auto matchesWhen = criterionRule.matchingRule;
auto criteriaIt = find_if(criteria.begin(), criteria.end(), [&](const auto& criterion) {
return criterion.has_value() &&
criterion.value().getTag() == selectionCriterion.getTag();
});
EXPECT_NE(criteriaIt, criteria.end())
<< " Invalid rule criterion " << toString(selectionCriterion.getTag());
AudioHalCapCriterionV2 matchingCriterion = (*criteriaIt).value();
switch (selectionCriterion.getTag()) {
case AudioHalCapCriterionV2::availableInputDevices: {
EXPECT_EQ(criterionValue.getTag(), TypeTag::availableDevicesType);
validateAudioHalCapRule(
matchingCriterion.get<AudioHalCapCriterionV2::availableInputDevices>(),
criterionValue.get<TypeTag::availableDevicesType>(), matchesWhen);
break;
}
case AudioHalCapCriterionV2::availableOutputDevices: {
EXPECT_EQ(criterionValue.getTag(), TypeTag::availableDevicesType);
validateAudioHalCapRule(
matchingCriterion.get<AudioHalCapCriterionV2::availableOutputDevices>(),
criterionValue.get<TypeTag::availableDevicesType>(), matchesWhen);
break;
}
case AudioHalCapCriterionV2::availableInputDevicesAddresses: {
EXPECT_EQ(criterionValue.getTag(), TypeTag::availableDevicesAddressesType);
validateAudioHalCapRule(
matchingCriterion
.get<AudioHalCapCriterionV2::availableInputDevicesAddresses>(),
criterionValue.get<TypeTag::availableDevicesAddressesType>(),
matchesWhen);
break;
}
case AudioHalCapCriterionV2::availableOutputDevicesAddresses: {
EXPECT_EQ(criterionValue.getTag(), TypeTag::availableDevicesAddressesType);
validateAudioHalCapRule(
matchingCriterion
.get<AudioHalCapCriterionV2::availableOutputDevicesAddresses>(),
criterionValue.get<TypeTag::availableDevicesAddressesType>(),
matchesWhen);
break;
}
case AudioHalCapCriterionV2::telephonyMode: {
EXPECT_EQ(criterionValue.getTag(), TypeTag::telephonyModeType);
validateAudioHalCapRule(
matchingCriterion.get<AudioHalCapCriterionV2::telephonyMode>(),
criterionValue.get<TypeTag::telephonyModeType>(), matchesWhen);
break;
}
case AudioHalCapCriterionV2::forceConfigForUse: {
EXPECT_EQ(criterionValue.getTag(), TypeTag::forcedConfigType);
validateAudioHalCapRule(
matchingCriterion
.get<AudioHalCapCriterionV2::forceConfigForUse>(),
criterionValue.get<TypeTag::forcedConfigType>(), matchesWhen);
break;
}
default:
break;
}
}
}
/**
* Get the number of occurrence of a given parameter within a given vector of parameter.
* It just take into account the parameter, not its associated value.
* @param parameter to consider
* @param domainParameters to check against
* @return matching occurrence of the parameter within the provided vector.
*/
size_t countsParameter(const AudioHalCapParameter& parameter,
const std::vector<AudioHalCapParameter>& domainParameters) {
size_t count = 0;
for (const auto& domainParameter : domainParameters) {
if (domainParameter.getTag() != parameter.getTag()) {
continue;
}
switch (domainParameter.getTag()) {
case AudioHalCapParameter::selectedStrategyDevice: {
auto typedDomainParam =
domainParameter.get<AudioHalCapParameter::selectedStrategyDevice>();
auto typedParam = parameter.get<AudioHalCapParameter::selectedStrategyDevice>();
if (typedDomainParam.id == typedParam.id &&
typedDomainParam.device == typedParam.device) {
count += 1;
}
break;
}
case AudioHalCapParameter::strategyDeviceAddress: {
auto typedDomainParam =
domainParameter.get<AudioHalCapParameter::strategyDeviceAddress>();
auto typedParam = parameter.get<AudioHalCapParameter::strategyDeviceAddress>();
if (typedDomainParam.id == typedParam.id) {
count += 1;
}
break;
}
case AudioHalCapParameter::selectedInputSourceDevice: {
auto typedDomainParam =
domainParameter.get<AudioHalCapParameter::selectedInputSourceDevice>();
auto typedParam =
parameter.get<AudioHalCapParameter::selectedInputSourceDevice>();
if (typedDomainParam.inputSource == typedParam.inputSource &&
typedDomainParam.device == typedParam.device) {
count += 1;
}
break;
}
case AudioHalCapParameter::streamVolumeProfile: {
auto typedDomainParam =
domainParameter.get<AudioHalCapParameter::streamVolumeProfile>();
auto typedParam = parameter.get<AudioHalCapParameter::streamVolumeProfile>();
if (typedDomainParam.stream == typedParam.stream) {
count += 1;
}
break;
}
default:
break;
}
}
return count;
}
/**
* Verify each configuration has unique name within a domain
* Verify no duplicate parameter within a domain.
* Verify that each configuration has no duplicated parameter.
* Verify that each configuration has an associated value for all parameter within a domain.
*/
void ValidateAudioHalCapDomain(
const AudioHalCapDomain& domain,
const std::vector<std::optional<AudioHalCapCriterionV2>>& criteria) {
std::unordered_set<std::string> configurationNames;
for (const AudioHalCapConfiguration& configuration : domain.configurations) {
EXPECT_TRUE(configurationNames.insert(configuration.name).second);
ValidateAudioHalConfigurationRule(configuration.rule, criteria);
}
auto domainParameters = domain.configurations[0].parameterSettings;
for (const auto& settingParameter : domainParameters) {
EXPECT_EQ(1ul, countsParameter(settingParameter, domainParameters))
<< "Duplicated parameter within domain " << domain.name << " configuration "
<< domain.configurations[0].name << " for parameter "
<< settingParameter.toString();
}
for (const auto& configuration : domain.configurations) {
auto configurationParameters = configuration.parameterSettings;
for (const auto& configurationParameter : configurationParameters) {
EXPECT_EQ(1ul, countsParameter(configurationParameter, configurationParameters))
<< "Duplicated parameter within domain " << domain.name << " configuration "
<< configuration.name << " for parameter "
<< configurationParameter.toString();
}
EXPECT_EQ(domainParameters.size(), configurationParameters.size());
for (const auto& settingParameter : configuration.parameterSettings) {
EXPECT_EQ(1ul, countsParameter(settingParameter, domainParameters))
<< "Confiugration " << configuration.name << " within domain "
<< domain.name << " exposes invalid parameter "
<< settingParameter.toString();
;
}
}
}
/**
* Verify each domain has a unique name.
* Verify that a given parameter does not appear in more than one domain.
*/
void ValidateAudioHalCapDomains(
const std::vector<std::optional<AudioHalCapDomain>>& domains,
const std::vector<std::optional<AudioHalCapCriterionV2>>& criteria) {
std::unordered_map<std::string, AudioHalCapDomain> domainMap;
std::vector<AudioHalCapParameter> allDomainParameters;
for (const auto& domain : domains) {
EXPECT_TRUE(domain.has_value());
EXPECT_FALSE(domain.value().configurations.empty());
auto domainParameters = domain.value().configurations[0].parameterSettings;
for (const auto& domainParameter : domainParameters) {
EXPECT_EQ(0ul, countsParameter(domainParameter, allDomainParameters))
<< "Duplicated parameter in domain " << domain.value().name
<< " for parameter " << domainParameter.toString();
allDomainParameters.push_back(domainParameter);
}
EXPECT_NO_FATAL_FAILURE(ValidateAudioHalCapDomain(domain.value(), criteria));
EXPECT_TRUE(domainMap.insert({domain.value().name, domain.value()}).second);
}
}
/**
* Verify unique criterion is provided for a given Tag, except for ForceUse
* Verify unique forceUse criterion are provided for usage
* Verify each criterion is validating.
* Verify domains.
*/
void ValidateCapSpecificConfig(const AudioHalEngineConfig::CapSpecificConfig& capCfg) {
EXPECT_FALSE(capCfg.criteria.empty());
EXPECT_FALSE(capCfg.criterionTypes.empty());
std::unordered_map<std::string, AudioHalCapCriterionType> criterionTypeMap;
for (const AudioHalCapCriterionType& criterionType : capCfg.criterionTypes) {
EXPECT_NO_FATAL_FAILURE(ValidateAudioHalCapCriterionType(criterionType));
EXPECT_TRUE(criterionTypeMap.insert({criterionType.name, criterionType}).second);
EXPECT_TRUE(capCfg.criteriaV2.has_value());
std::unordered_set<AudioHalCapCriterionV2::Tag> criterionTagSet;
std::unordered_set<AudioPolicyForceUse> forceUseCriterionUseSet;
for (const auto& criterion : capCfg.criteriaV2.value()) {
EXPECT_TRUE(criterion.has_value());
if (criterion.value().getTag() != AudioHalCapCriterionV2::forceConfigForUse) {
EXPECT_TRUE(criterionTagSet.insert(criterion.value().getTag()).second);
} else {
auto forceUseCriterion =
criterion.value().get<AudioHalCapCriterionV2::forceConfigForUse>();
EXPECT_TRUE(forceUseCriterionUseSet.insert(forceUseCriterion.forceUse).second);
}
EXPECT_NO_FATAL_FAILURE(ValidateAudioHalCapCriterion(criterion.value()));
}
std::unordered_set<std::string> criterionNameSet;
for (const AudioHalCapCriterion& criterion : capCfg.criteria) {
EXPECT_TRUE(criterionNameSet.insert(criterion.name).second);
EXPECT_EQ(criterionTypeMap.count(criterion.criterionTypeName), 1UL);
EXPECT_NO_FATAL_FAILURE(ValidateAudioHalCapCriterion(
criterion, criterionTypeMap.at(criterion.criterionTypeName)));
}
EXPECT_EQ(criterionTypeMap.size(), criterionNameSet.size());
ValidateAudioHalCapDomains(capCfg.domains.value(), capCfg.criteriaV2.value());
}
/**

View File

@@ -17,8 +17,9 @@ cc_test {
"libxml2",
"liblog",
"libmedia_helper",
"libaudiopolicyengine_config",
"libaudiopolicycapengine_config",
"libaudiopolicycomponents",
"libaudiopolicyengine_config",
"libaudiopolicyengineconfigurable_pfwwrapper",
"android.hardware.audio.common.test.utility",
"libparameter",

View File

@@ -162,7 +162,9 @@ package audio.policy.V1_0 {
public static class ProductStrategies.ProductStrategy {
ctor public ProductStrategies.ProductStrategy();
method public java.util.List<audio.policy.V1_0.AttributesGroup> getAttributesGroup();
method public int getId();
method public String getName();
method public void setId(int);
method public void setName(String);
}

View File

@@ -105,6 +105,7 @@
<xs:element name="AttributesGroup" type="AttributesGroup" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required"/>
<xs:attribute name="id" type="xs:int" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>