/*****************************************************************************************************************/
声明: 本博客内容均由https://blog.csdn.net/weixin_47702410原创,转载or引用请注明出处,谢谢!
创作不易,如果文章对你有帮助,麻烦点赞 收藏支持~感谢
/*****************************************************************************************************************/
上一篇文章启动过程提到:
/frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp void AudioPolicyManager::loadConfig() { ALOGE("Mylog_AP:AudioPolicyManager::loadConfig() !"); if (deserializeAudioPolicyXmlConfig(getConfig()) != NO_ERROR) { ALOGE("could not load audio policy configuration file, setting defaults"); getConfig().setDefault(); } }
本文详细讲一下这个解析配置文件的过程。
deserializeAudioPolicyXmlConfig()的定义在:
/frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp static status_t deserializeAudioPolicyXmlConfig(AudioPolicyConfig &config) { if (std::string audioPolicyXmlConfigFile = audio_get_audio_policy_config_file(); !audioPolicyXmlConfigFile.empty()) { status_t ret = deserializeAudioPolicyFile(audioPolicyXmlConfigFile.c_str(), &config); if (ret == NO_ERROR) { config.setSource(audioPolicyXmlConfigFile); } return ret; } return BAD_VALUE; }
这个函数主要做了两个事情:
其中第一步骤的函数在如下的定义(有可能这个函数会被客制化修改):
//https://cs.android.com/android/platform/superproject/+/android-12.0.0_r8:system/media/audio/include/system/audio_config.h?hl=zh-cn /system/media/audio/include/system/audio_config.h static inline std::string audio_get_audio_policy_config_file()
函数内容不是很难,感兴趣可以自己阅读源码,我这里总结一下:
这个函数主要是根据系统的属性选择不同的配置文件,简单的画个系统属性和配置文件的关系图:
这里我们主要分析第二个函数deserializeAudioPolicyFile.但在分析这个函数前需要了解一下知识:
也就是audio_policy_config_file中child的概念,我画一张简图表示一下这个关系(以audio_policy_configuration.xml为例):
看图应该不难分析,就是套娃又套娃。一个modules对应一个so文件,例如,这个就是对于一个primary HAL;其中一个module允许有多个设备列表。
有上面的了解后,再看一下源码:
/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); --> 重构+函数模板 if (status != OK) config->clear(); return status; }
结合C++的语法,上面函数调用到:
/frameworks/av/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp status_t PolicySerializer::deserialize(const char *configFile, AudioPolicyConfig *config, bool ignoreVendorExtensions) { mIgnoreVendorExtensions = ignoreVendorExtensions; auto doc = make_xmlUnique(xmlParseFile(configFile)); --> 解析XML配置文件 if (doc == nullptr) { ALOGE("%s: Could not parse %s document.", __func__, configFile); return BAD_VALUE; } xmlNodePtr root = xmlDocGetRootElement(doc.get()); --> 获取XML文档的根节点 if (root == NULL) { ALOGE("%s: Could not parse %s document: empty.", __func__, configFile); return BAD_VALUE; } if (xmlXIncludeProcess(doc.get()) < 0) { --> 处理XML文档中的XInclude指令 ALOGE("%s: libxml failed to resolve XIncludes on %s document.", __func__, configFile); } if (xmlStrcmp(root->name, reinterpret_cast(rootName))) { -->// 检查根节点的名称是否与"rootName = "audioPolicyConfiguration""的一致 ALOGE("%s: No %s root element found in xml data %s.", __func__, rootName, reinterpret_cast (root->name)); return BAD_VALUE; } std::string version = getXmlAttribute(root, versionAttribute); --> 获取根节点的版本属性 if (version.empty()) { ALOGE("%s: No version found in root node %s", __func__, rootName); return BAD_VALUE; } if (version == "7.0") { mChannelMasksSeparator = mSamplingRatesSeparator = mFlagsSeparator = " "; } else if (version != "1.0") { ALOGE("%s: Version does not match; expected \"1.0\" or \"7.0\" got \"%s\"", __func__, version.c_str()); return BAD_VALUE; } // Let's deserialize children // Modules ModuleTraits::Collection modules; status_t status = deserializeCollection (root, &modules, config); if (status != NO_ERROR) { return status; } config->setHwModules(modules); // Global Configuration deserialize (root, config); --> 利用C++的函数模板语法调用到不同的deserialize // Surround configuration deserialize (root, config); return android::OK; }
上面这个函数重点关注一下下面的语句,其是在这个函数中解析文件的:
status_t status = deserializeCollection(root, &modules, config); 其调用的函数是: /frameworks/av/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp template status_t PolicySerializer::deserializeCollection(const xmlNode *cur, typename Trait::Collection *collection, typename Trait::PtrSerializingCtx serializingContext) { --> 用两个for循环,遍历当前xml节点的所有子节点 for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { const xmlNode *child = NULL; if (!xmlStrcmp(cur->name, reinterpret_cast (Trait::collectionTag))) { child = cur->xmlChildrenNode; } else if (!xmlStrcmp(cur->name, reinterpret_cast (Trait::tag))) { child = cur; } for (; child != NULL; child = child->next) { if (!xmlStrcmp(child->name, reinterpret_cast (Trait::tag))) { auto maybeElement = deserialize (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 (maybeElement) == NO_INIT) { // Skip a vendor extension element. } else { return BAD_VALUE; } } } if (!xmlStrcmp(cur->name, reinterpret_cast (Trait::tag))) { return NO_ERROR; } } return NO_ERROR; }
单从函数分析并不难,找到对应模板的名字,然后再调用
auto maybeElement = deserialize(child, serializingContext);
最后的结果就是:
/frameworks/av/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h class AudioPolicyConfig { public: .... private: std::string mSource; std::string mEngineLibraryNameSuffix; HwModuleCollection &mHwModules; /**< Collection of Module, with Profiles, i.e. Mix Ports. */ DeviceVector &mOutputDevices; // xm中所以output devices模块集合 DeviceVector &mInputDevices; //xml中所以input devices模块集合 sp&mDefaultOutputDevice; //默认的output device ... };
推荐阅读: