Android源码分析--Audio设备文件解析(07)

        上篇文章中只是讲到配置文件在哪里,怎么读取文件,但是真正的文件解析还没有开始。这篇就开始分析文件解析,认识这些解析的参数。

 接着上篇Audio设备文件加载继续进行分析,知道主要是这个函数起到解析的作用。

static status_t deserializeAudioPolicyXmlConfig(AudioPolicyConfig &config) {
    char audioPolicyXmlConfigFile[AUDIO_POLICY_XML_CONFIG_FILE_PATH_MAX_LENGTH];
    status_t ret;

    for (int i = 0; i < kConfigLocationListSize; i++) {
        PolicySerializer serializer;
        snprintf(audioPolicyXmlConfigFile,
                 sizeof(audioPolicyXmlConfigFile),
                 "%s/%s",
                 kConfigLocationList[i],
                 AUDIO_POLICY_XML_CONFIG_FILE_NAME);
        ret = serializer.deserialize(audioPolicyXmlConfigFile, config);
        if (ret == NO_ERROR) {
            break;
        }
    }
    return ret;
}

也知道audioPolicyXmlConfigFile的配置文件是/system/etc/auido_policy_configuration.xml文件。传入的参数是AudioPolicyConfig,这个类包含很多变量,

private:
    HwModuleCollection &mHwModules; /**< Collection of Module, with Profiles, i.e. Mix Ports. */
    DeviceVector &mAvailableOutputDevices;
    DeviceVector &mAvailableInputDevices;
    sp<DeviceDescriptor> &mDefaultOutputDevices;
    VolumeCurvesCollection *mVolumeCurves;
    bool &mIsSpeakerDrcEnabled;

也就是需要传递进来进行初始化的变量,解析的作用就是初始化这五个变量。

函数里面有个PolicySerializer类

/
frameworks/
av/
services/
audiopolicy/
common/
managerdefinitions/
include/
Serializer.h

只有这个函数有作用

    status_t deserialize(const char *str, AudioPolicyConfig &config);

来看这个函数的实现

status_t PolicySerializer::deserialize(const char *configFile, AudioPolicyConfig &config)
{
    xmlDocPtr doc;
    doc = xmlParseFile(configFile);
    if (doc == NULL) {
        ALOGE("%s: Could not parse %s document.", __FUNCTION__, configFile);
        return BAD_VALUE;
    }
    xmlNodePtr cur = xmlDocGetRootElement(doc);
    if (cur == NULL) {
        ALOGE("%s: Could not parse %s document: empty.", __FUNCTION__, configFile);
        xmlFreeDoc(doc);
        return BAD_VALUE;
    }
    if (xmlXIncludeProcess(doc) < 0) {
         ALOGE("%s: libxml failed to resolve XIncludes on %s document.", __FUNCTION__, configFile);
    }

    if (xmlStrcmp(cur->name, (const xmlChar *) mRootElementName.c_str()))  {
        ALOGE("%s: No %s root element found in xml data %s.", __FUNCTION__, mRootElementName.c_str(),
              (const char *)cur->name);
        xmlFreeDoc(doc);
        return BAD_VALUE;
    }

    string version = getXmlAttribute(cur, versionAttribute);
    if (version.empty()) {
        ALOGE("%s: No version found in root node %s", __FUNCTION__, mRootElementName.c_str());
        return BAD_VALUE;
    }
    if (version != mVersion) {
        ALOGE("%s: Version does not match; expect %s got %s", __FUNCTION__, mVersion.c_str(),
              version.c_str());
        return BAD_VALUE;
    }
    // Lets deserialize children
    // Modules
    ModuleTraits::Collection modules;
    deserializeCollection<ModuleTraits>(doc, cur, modules, &config);
    config.setHwModules(modules);

    // deserialize volume section
    VolumeTraits::Collection volumes;
    deserializeCollection<VolumeTraits>(doc, cur, volumes, &config);
    config.setVolumes(volumes);

    // Global Configuration
    GlobalConfigTraits::deserialize(cur, config);

    xmlFreeDoc(doc);
    return android::OK;
}

doc是文件节点,cur是文件根节点,可以参考libxml2生成和解析配置树文件文章。这个函数会进一步解析包含的文件

<xi:include href="a2dp_audio_policy_configuration.xml"/> 
<?xml version="1.0" encoding="UTF-8"?>
<!-- A2dp Audio HAL Audio Policy Configuration file -->
<module name="a2dp" halVersion="2.0">
    <mixPorts>
        <mixPort name="a2dp output" role="source">
            <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                     samplingRates="44100"
                     channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
        </mixPort>
        <mixPort name="a2dp input" role="sink">
            <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                     samplingRates="44100,48000"
                     channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO"/>
        </mixPort>
    </mixPorts>
    <devicePorts>
        <devicePort tagName="BT A2DP Out" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP" role="sink">
            <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                     samplingRates="44100"
                     channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
        </devicePort>
        <devicePort tagName="BT A2DP Headphones" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES" role="sink">
            <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                     samplingRates="44100"
                     channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
        </devicePort>
        <devicePort tagName="BT A2DP Speaker" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER" role="sink">
            <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                     samplingRates="44100"
                     channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
        </devicePort>
        <devicePort tagName="BT A2DP In" type="AUDIO_DEVICE_IN_BLUETOOTH_A2DP" role="source">
            <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                     samplingRates="44100,48000"
                     channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO"/>
        </devicePort>
    </devicePorts>
    <routes>
        <route type="mix" sink="BT A2DP Out"
               sources="a2dp output"/>
        <route type="mix" sink="BT A2DP Headphones"
               sources="a2dp output"/>
        <route type="mix" sink="BT A2DP Speaker"
               sources="a2dp output"/>
        <route type="mix" sink="a2dp input"
               sources="BT A2DP In"/>
    </routes>
</module>

可以看到modules的书写规则是需要包括<mixPorts>,<devicePorts>,<routes>几个节点的,解析完成之后会生成树。

下面这句话是获取xml版本号,值为1.0

string version = getXmlAttribute(cur, versionAttribute);

可以看到libxml2已经做好解析的所有事情,接下来就是向参数赋值。

如果觉得这篇文章有用,可以扫免费红包支持。

《Android源码分析--Audio设备文件解析(07)》

    原文作者:Android源码分析
    原文地址: https://blog.csdn.net/WAN_EXE/article/details/79167423
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞