当前位置: 首页 > news >正文

audio policy config xml解析过程

一、获取xml文件

1.启动audioservice

frameworks/av/media/audioserver/main_audioserver.cpp //main函数中定义一个对象: const auto aps = sp<AudioPolicyService>::make();

2.执行构造函数并mCreateAudioPolicyManager(createAudioPolicyManager)进行初始化

frameworks/av/services/audiopolicy/service/AudioPolicyService.cpp AudioPolicyService::AudioPolicyService()

3.调用void AudioPolicyService::onFirstRef()函数

void AudioPolicyService::onFirstRef() { ...... mAudioPolicyManager = mCreateAudioPolicyManager(mAudioPolicyClient); ...... }

4.解析配置文件audio policy config xml

static AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface) { AudioPolicyManager *apm = nullptr; media::AudioPolicyConfig apmConfig; if (status_t status = clientInterface->getAudioPolicyConfig(&apmConfig); status == OK) { ...... } else { auto config = AudioPolicyConfig::loadFromApmXmlConfigWithFallback(); // This can't fail.解析配置文件audio policy config xml ...... } }
sp<const AudioPolicyConfig> AudioPolicyConfig::loadFromApmXmlConfigWithFallback( const std::string& xmlFilePath) { const std::string filePath = xmlFilePath.empty() ? audio_get_audio_policy_config_file() : xmlFilePath;//获取xml文件 auto config = sp<AudioPolicyConfig>::make(); if (status_t status = config->loadFromXml(filePath, false /*forVts*/); status == NO_ERROR) { return config; } return createDefault(); }
static inline std::string audio_get_audio_policy_config_file() { static constexpr const char *apmXmlConfigFileName = "audio_policy_configuration.xml"; static constexpr const char *apmA2dpOffloadDisabledXmlConfigFileName = "audio_policy_configuration_a2dp_offload_disabled.xml"; static constexpr const char *apmLeOffloadDisabledXmlConfigFileName = "audio_policy_configuration_le_offload_disabled.xml"; static constexpr const char *apmBluetoothLegacyHalXmlConfigFileName = "audio_policy_configuration_bluetooth_legacy_hal.xml"; std::string audioPolicyXmlConfigFile; // First try alternative files if needed if (property_get_bool("ro.bluetooth.a2dp_offload.supported", false)) { if (property_get_bool("persist.bluetooth.bluetooth_audio_hal.disabled", false) && property_get_bool("persist.bluetooth.a2dp_offload.disabled", false)) { // Both BluetoothAudio@2.0 and BluetoothA2dp@1.0 (Offload) are disabled, and uses // the legacy hardware module for A2DP and hearing aid. audioPolicyXmlConfigFile = audio_find_readable_configuration_file( apmBluetoothLegacyHalXmlConfigFileName); } else if (property_get_bool("persist.bluetooth.a2dp_offload.disabled", false)) { // A2DP offload supported but disabled: try to use special XML file // assume that if a2dp offload is not supported, le offload is not supported as well audioPolicyXmlConfigFile = audio_find_readable_configuration_file( apmA2dpOffloadDisabledXmlConfigFileName); } else if (!property_get_bool("ro.bluetooth.leaudio_offload.supported", false) || property_get_bool("persist.bluetooth.leaudio_offload.disabled", false)) { // A2DP offload supported but LE offload disabled: try to use special XML file audioPolicyXmlConfigFile = audio_find_readable_configuration_file( apmLeOffloadDisabledXmlConfigFileName); } } else if (property_get_bool("persist.bluetooth.bluetooth_audio_hal.disabled", false)) { audioPolicyXmlConfigFile = audio_find_readable_configuration_file( apmBluetoothLegacyHalXmlConfigFileName); } else { audioPolicyXmlConfigFile = audio_find_readable_configuration_file( apmA2dpOffloadDisabledXmlConfigFileName); } return audioPolicyXmlConfigFile.empty() ? audio_find_readable_configuration_file(apmXmlConfigFileName) : audioPolicyXmlConfigFile; } }
static inline std::string audio_find_readable_configuration_file(const char* fileName) { for (const auto& path : audio_get_configuration_paths()) { std::string tryPath = path + "/" + fileName; if (audio_is_readable_configuration_file(tryPath.c_str())) { return tryPath; } } return {}; }//最后加载vendor/etc/audio_policy_configuration.xml,具体是哪个路径根据代码而定

5.回到createAudioPolicyManager函数

apm = new AudioPolicyManager(config, loadApmEngineLibraryAndCreateEngine(config->getEngineLibraryNameSuffix()), clientInterface);//最终加载/vendor/etc/audio_policy_engine_configuration.xml,有的平台会客制化这部分

二、解析xml

1.入口deserializeAudioPolicyFile函数,此时的filename为audio_policy_configuration.xml

//frameworks/av/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp status_t deserializeAudioPolicyFile(const char *fileName, AudioPolicyConfig *config) { PolicySerializer serializer; status_t status = serializer.deserialize(fileName, config); return status; }

2.调用deserialize,解析xml,把xml的节点都解析出来

auto doc = make_xmlUnique(xmlParseFile(configFile));//解析 XML 文件 (libxml2)

3. 获取xml根节点

xmlNodePtr root = xmlDocGetRootElement(doc.get());

4.解析include xml文件

xmlXIncludeProcess(doc.get())//比如:<xi:include href="primary_audio_policy_configuration.xml"/>

5.验证根元素和版本

xmlStrcmp(root->name, reinterpret_cast<const xmlChar*>(rootName));//rootname = "audioPolicyConfiguration" std::string version = getXmlAttribute(root, versionAttribute);//versionAttribute = "version"

6.开始解析modules

status_t status = deserializeCollection<ModuleTraits>(root, &modules, config);//传入的是modules

7.看deserializeCollection函数

for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {//遍历之前解析xml的节点,比如:modules,globalConfiguration等 const xmlNode *child = NULL; if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(Trait::collectionTag))) {//与collectionTag相比较,判断是否是modules child = cur->xmlChildrenNode; } else if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(Trait::tag))) { child = cur; } for (; child != NULL; child = child->next) {//遍历modules下的节点 if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>(Trait::tag))) {//与tag相比较,即判断是否是module,如果是则继续往下走 auto maybeElement = deserialize<Trait>(child, serializingContext); if (maybeElement.index() == 1) { status_t status = Trait::addElementToCollection( std::get<1>(maybeElement), collection); if (status != NO_ERROR) { ALOGE("%s: could not add element to %s collection", __func__, Trait::collectionTag); return status; } } else if (mIgnoreVendorExtensions && std::get<status_t>(maybeElement) == NO_INIT) { // Skip a vendor extension element. } else { return BAD_VALUE; } } }

8.继续看deserialize文件,此时是module模块的,则调用module模块的deserialize函数

template<> std::variant<status_t, ModuleTraits::Element> PolicySerializer::deserialize<ModuleTraits>( const xmlNode *cur, ModuleTraits::PtrSerializingCtx ctx) { using Attributes = ModuleTraits::Attributes; auto& tag = ModuleTraits::tag; auto& childAttachedDevicesTag = ModuleTraits::childAttachedDevicesTag; auto& childAttachedDeviceTag = ModuleTraits::childAttachedDeviceTag; auto& childDefaultOutputDeviceTag = ModuleTraits::childDefaultOutputDeviceTag; std::string name = getXmlAttribute(cur, Attributes::name);//获取属性name的值,即为"primary" if (name.empty()) { ALOGE("%s: No %s found", __func__, Attributes::name); return BAD_VALUE; } uint32_t versionMajor = 0, versionMinor = 0; std::string versionLiteral = getXmlAttribute(cur, Attributes::version);//获取属性halVersion的值,即为"2.0" if (!versionLiteral.empty()) { sscanf(versionLiteral.c_str(), "%u.%u", &versionMajor, &versionMinor); ALOGV("%s: mHalVersion = major %u minor %u", __func__, versionMajor, versionMajor); } ALOGD("%s: %s %s=%s", __func__, ModuleTraits::tag, Attributes::name, name.c_str()); ModuleTraits::Element module = new HwModule(name.c_str(), versionMajor, versionMinor); // Deserialize children: Audio Mix Port, Audio Device Ports (Source/Sink), Audio Routes MixPortTraits::Collection mixPorts; status_t status = deserializeCollection<MixPortTraits>(cur, &mixPorts, NULL);//解析mixPorts参数 if (status != NO_ERROR) { return status; } module->setProfiles(mixPorts); DevicePortTraits::Collection devicePorts; status = deserializeCollection<DevicePortTraits>(cur, &devicePorts, NULL); if (status != NO_ERROR) { return status; } module->setDeclaredDevices(devicePorts); RouteTraits::Collection routes; status = deserializeCollection<RouteTraits>(cur, &routes, module.get()); if (status != NO_ERROR) { return status; } module->setRoutes(routes); for (const xmlNode *children = cur->xmlChildrenNode; children != NULL; children = children->next) { if (!xmlStrcmp(children->name, reinterpret_cast<const xmlChar*>(childAttachedDevicesTag))) { ALOGD("%s: %s %s found", __func__, tag, childAttachedDevicesTag); for (const xmlNode *child = children->xmlChildrenNode; child != NULL; child = child->next) { if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>(childAttachedDeviceTag))) { //MIUI ADD: Audio_DecoupledMtk #ifdef XIAOMI_PLATFORM_MTK if (xmlNodeListGetString(child->doc, child->xmlChildrenNode, 1) == nullptr) { //MTK_AUDIO ALOGW("%s: 1.Get Null string", __func__); continue; } #endif //END Audio_DecoupledMtk auto attachedDevice = make_xmlUnique(xmlNodeListGetString( child->doc, child->xmlChildrenNode, 1)); if (attachedDevice != nullptr) { ALOGD("%s: %s %s=%s", __func__, tag, childAttachedDeviceTag, reinterpret_cast<const char*>(attachedDevice.get())); sp<DeviceDescriptor> device = module->getDeclaredDevices(). getDeviceFromTagName(std::string(reinterpret_cast<const char*>( attachedDevice.get()))); if (device == NULL) { if (mIgnoreVendorExtensions) { ALOGD("%s: skipped attached device \"%s\" because it likely uses a " "vendor extension type", __func__, reinterpret_cast<const char*>(attachedDevice.get())); } else { ALOGE("%s: got null device in %s, \"%s\"", __func__, child->name, reinterpret_cast<const char*>(attachedDevice.get())); } continue; } ctx->addDevice(device); } } } } if (!xmlStrcmp(children->name, reinterpret_cast<const xmlChar*>(childDefaultOutputDeviceTag))) { //MIUI ADD: Audio_DecoupledMtk #ifdef XIAOMI_PLATFORM_MTK if (xmlNodeListGetString(children->doc, children->xmlChildrenNode, 1) == nullptr) { //MTK_AUDIO ALOGW("%s: 2.Get Null string", __func__); continue; } #endif //END Audio_DecoupledMtk auto defaultOutputDevice = make_xmlUnique(xmlNodeListGetString( children->doc, children->xmlChildrenNode, 1)); if (defaultOutputDevice != nullptr) { ALOGD("%s: %s %s=%s", __func__, tag, childDefaultOutputDeviceTag, reinterpret_cast<const char*>(defaultOutputDevice.get())); sp<DeviceDescriptor> device = module->getDeclaredDevices().getDeviceFromTagName( std::string(reinterpret_cast<const char*>(defaultOutputDevice.get()))); if (device != 0 && ctx->getDefaultOutputDevice() == 0) { ctx->setDefaultOutputDevice(device); ALOGD("%s: default is %08x", __func__, ctx->getDefaultOutputDevice()->type()); } } } } return module; }

9.看deserializeCollection函数,此时解析的是mixports

<mixPorts> <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> </mixPort> <mixPorts>
for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {//遍历mixports const xmlNode *child = NULL; if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(Trait::collectionTag))) {//与collectionTag相比较,判断是否是mixports child = cur->xmlChildrenNode; } else if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(Trait::tag))) { child = cur; } for (; child != NULL; child = child->next) {//遍历mixports下的节点 if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>(Trait::tag))) {//与tag相比较,即判断是否是mixport,如果是则继续往下走 auto maybeElement = deserialize<Trait>(child, serializingContext); if (maybeElement.index() == 1) { status_t status = Trait::addElementToCollection( std::get<1>(maybeElement), collection); if (status != NO_ERROR) { ALOGE("%s: could not add element to %s collection", __func__, Trait::collectionTag); return status; } } else if (mIgnoreVendorExtensions && std::get<status_t>(maybeElement) == NO_INIT) { // Skip a vendor extension element. } else { return BAD_VALUE; } } }
http://www.jsqmd.com/news/616070/

相关文章:

  • OpenClaw(一)| 认识 OpenClaw
  • 突破付费内容限制:6种高效内容解锁技术全解析
  • 机器人零件设计优化:如何帮客户降低成本30%
  • 【2026年最新600套毕设项目分享】新闻资讯微信小程序(30013)
  • TCP/IP协议栈中网络接口层和网际层的核心概念与协议特性,是软件设计师考试中计算机网络部分的重要考点
  • ISDANet:交互式与监督双模式注意力的遥感变化检测
  • AccelStepper:Arduino步进电机精准控制与多轴协同解决方案
  • 作业二6位数码管显示
  • OpenClaw+SecGPT-14B实战:Git仓库敏感信息自动化审计
  • 慧谷新材深交所上市:市值73亿 年营收9.85亿,净利2亿
  • 学习嵌入式:单片机、MCU、RTOS、Linux 到底该学啥?
  • 2026年纯正弦波逆变器权威厂家盘点:储能电源/光伏控制器/太阳能控制器/磷酸铁锂电池/逆变器/锂电池/储能电池/选择指南 - 优质品牌商家
  • 财税行业AI落地:记账、报税、风控的自动化解决方案
  • 【单片机0.2】
  • AI搜索时代,跨境电商获客的核心逻辑变了
  • 账号没有明显违规却突然受限很多时候问题藏在哪些地方
  • 想学ARM/Linux,必须要先学会单片机吗?
  • 大金重工冲刺港股:年营收62亿,利润11亿 金鑫控制40%股权
  • Java 的4 种核心内部类
  • Keep平台API开发实战指南:从设计理念到生产落地
  • 2026届最火的六大AI学术平台实测分析
  • 2026年微软Dynamics365BC选购指南:微软Dynamics365BusinessCentral、微软微软Dynamics 365 BC代理商推荐选择指南 - 优质品牌商家
  • 跨境电商AI搜索优化,最容易踩的4个坑
  • 个人知识库助手:OpenClaw+Qwen3-14B构建智能检索系统
  • 九岭锂业IPO被终止:年营收43.8亿 曾拟募资34亿
  • 全球首发 | 「AI智能库」正式官宣,智库智能重新定义仓库!
  • OpenClaw备份方案:Phi-3-mini-128k-instruct智能归类云端与本地存储
  • LM-Studio-0.4.10 安装完,不显示显卡信息
  • OpenClaw+千问3.5-9B:自媒体内容生成流水线
  • 2026年比较好的山西废气治理/有机废气治理推荐品牌厂家 - 行业平台推荐