赞
踩
在AudioPolicyService的启动过程中,会去创建AudioPolicyManager对象,进而去解析配置文件
//frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
: AudioPolicyManager(clientInterface, false /*forTesting*/)
{
loadConfig();
}
loadConfig
//frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
void 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) { char audioPolicyXmlConfigFile[AUDIO_POLICY_XML_CONFIG_FILE_PATH_MAX_LENGTH]; std::vector<const char*> fileNames; status_t ret; //省略 fileNames.push_back(AUDIO_POLICY_XML_CONFIG_FILE_NAME);//AUDIO_POLICY_XML_CONFIG_FILE_NAME:audio_policy_configuration.xml for (const char* fileName : fileNames) { for (const auto& path : audio_get_configuration_paths()) { snprintf(audioPolicyXmlConfigFile, sizeof(audioPolicyXmlConfigFile), "%s/%s", path.c_str(), fileName); ret = deserializeAudioPolicyFile(audioPolicyXmlConfigFile, &config);//1 if (ret == NO_ERROR) { config.setSource(audioPolicyXmlConfigFile); return ret; } } } return ret; }
audio_get_configuration_paths返回的路径为“/odm/etc”, “/vendor/etc”,“/system/etc” 。然后遍历这些路径,找到audio_policy_configuration.xml文件,然后调用注释1处的deserializeAudioPolicyFile来解析这个文件
deserializeAudioPolicyFile
//frameworks/av/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
status_t deserializeAudioPolicyFile(const char *fileName, AudioPolicyConfig *config)
{
PolicySerializer serializer;
return serializer.deserialize(fileName, config);
}
PolicySerializer::deserialize
//frameworks/av/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp status_t PolicySerializer::deserialize(const char *configFile, AudioPolicyConfig *config) { auto doc = make_xmlUnique(xmlParseFile(configFile)); xmlNodePtr root = xmlDocGetRootElement(doc.get()); //省略:对文件的合法性进行效验 // Lets deserialize children // Modules ModuleTraits::Collection modules; status_t status = deserializeCollection<ModuleTraits>(root, &modules, config);//1 if (status != NO_ERROR) { return status; } //设置mHwModules config->setHwModules(modules); //省略 return android::OK; }
注释1处,开始解析配置文件中的modules标签。注意modules类型为 ModuleTraits::Collection
//frameworks/av/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp template <class Trait> status_t deserializeCollection(const xmlNode *cur, typename Trait::Collection *collection, typename Trait::PtrSerializingCtx serializingContext) { for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { const xmlNode *child = NULL; if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(Trait::collectionTag))) { child = cur->xmlChildrenNode; } else if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(Trait::tag))) { child = cur; } for (; child != NULL; child = child->next) { if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>(Trait::tag))) { auto element = Trait::deserialize(child, serializingContext);//1 if (element.isOk()) { status_t status = Trait::addElementToCollection(element, collection);//添加元素 } else { return BAD_VALUE; } } } } return NO_ERROR; }
注释1处,针对不同的Trait类型,就调用不同的子类的deserialize处理。对于modules标签,调用ModuleTraits的deserialize处理。
ModuleTraits::deserialize
//frameworks/av/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp Return<ModuleTraits::Element> ModuleTraits::deserialize(const xmlNode *cur, PtrSerializingCtx ctx) { std::string name = getXmlAttribute(cur, Attributes::name);//得到名字,如:primary Element module = new HwModule(name.c_str(), versionMajor, versionMinor);//创建HwModule对象 //开始解析mixPorts标签 MixPortTraits::Collection mixPorts; status_t status = deserializeCollection<MixPortTraits>(cur, &mixPorts, NULL); module->setProfiles(mixPorts); //开始解析devicePorts标签 DevicePortTraits::Collection devicePorts; status = deserializeCollection<DevicePortTraits>(cur, &devicePorts, NULL); module->setDeclaredDevices(devicePorts); //开始解析routes标签 RouteTraits::Collection routes; status = deserializeCollection<RouteTraits>(cur, &routes, module.get()); module->setRoutes(routes); //开始解析attachedDevices标签 for (const xmlNode *children = cur->xmlChildrenNode; children != NULL; children = children->next) { if (!xmlStrcmp(children->name, reinterpret_cast<const xmlChar*>(childAttachedDevicesTag))) { for (const xmlNode *child = children->xmlChildrenNode; child != NULL; child = child->next) { if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>(childAttachedDeviceTag))) { auto attachedDevice = make_xmlUnique(xmlNodeListGetString( child->doc, child->xmlChildrenNode, 1)); if (attachedDevice != nullptr) { sp<DeviceDescriptor> device = module->getDeclaredDevices(). getDeviceFromTagName(std::string(reinterpret_cast<const char*>( attachedDevice.get()))); ctx->addDevice(device); } } } } //开始解析defaultOutputDevice标签 if (!xmlStrcmp(children->name,reinterpret_cast<const xmlChar*>(childDefaultOutputDeviceTag))) { auto defaultOutputDevice = make_xmlUnique(xmlNodeListGetString( children->doc, children->xmlChildrenNode, 1)); if (defaultOutputDevice != nullptr) { sp<DeviceDescriptor> device = module->getDeclaredDevices().getDeviceFromTagName( std::string(reinterpret_cast<const char*>(defaultOutputDevice.get()))); if (device != 0 && ctx->getDefaultOutputDevice() == 0) { ctx->setDefaultOutputDevice(device); } } } }
解析mixPorts标签
//vendor/etc/audio_policy_configuration.xml <mixPorts> <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="44100,48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> </mixPort> <mixPort name="spdif_passthrough" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="32000,44100,48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> <profile name="" format="AUDIO_FORMAT_IEC61937" samplingRates="32000,44100,48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> </mixPort> <mixPort name="hdmi" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="32000,44100,48000,96000,176400,192000" channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_QUAD,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_7POINT1"/> <profile name="" format="AUDIO_FORMAT_IEC61937" samplingRates="32000,44100,48000,96000,176400,192000" channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_QUAD,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_7POINT1"/> <profile name=""/> </mixPort> <mixPort name="primary input" role="sink"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000" channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO"/> </mixPort> </mixPorts>
对于mixPorts标签,会循环调用MixPortTraits的deserialize方法解析其子标签,也就是mixPort
//frameworks/av/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp Return<MixPortTraits::Element> MixPortTraits::deserialize(const xmlNode *child, PtrSerializingCtx /*serializingContext*/) { std::string name = getXmlAttribute(child, Attributes::name);//得到名字:primary output,spdif_passthrough,hdmi,primary input std::string role = getXmlAttribute(child, Attributes::role);//sink或者source audio_port_role_t portRole = (role == Attributes::roleSource) ? AUDIO_PORT_ROLE_SOURCE : AUDIO_PORT_ROLE_SINK; Element mixPort = new IOProfile(name, portRole);//创建IOProfile对象 AudioProfileTraits::Collection profiles; status_t status = deserializeCollection<AudioProfileTraits>(child, &profiles, NULL);//解析mixPort标签下的profile // The audio profiles are in order of listed in audio policy configuration file. // Sort audio profiles accroding to the format. sortAudioProfiles(profiles); mixPort->setAudioProfiles(profiles);//添加到mProfiles链表中 //省略
根据解析mixPort得到的name和role 创建IOProfile对象,然后开始解析mixPort标签下的profile ,最后将解析结果添加到mProfiles链表中。来看一下profile 的解析
//frameworks/av/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp Return<AudioProfileTraits::Element> AudioProfileTraits::deserialize(const xmlNode *cur, PtrSerializingCtx /*serializingContext*/) { std::string samplingRates = getXmlAttribute(cur, Attributes::samplingRates);//采样率 std::string format = getXmlAttribute(cur, Attributes::format);//采样位数 std::string channels = getXmlAttribute(cur, Attributes::channelMasks);//通道 Element profile = new AudioProfile(formatFromString(format, gDynamicFormat), channelMasksFromString(channels, ","), samplingRatesFromString(samplingRates, ","));//创建AudioProfile对象 profile->setDynamicFormat(profile->getFormat() == gDynamicFormat); profile->setDynamicChannels(profile->getChannels().empty()); profile->setDynamicRate(profile->getSampleRates().empty()); return profile; }
该部分解析完成后,可得到以下结果:每个mixPort标签都会转化成IOProfile对象,mixPort标签下的profile,都会转化成AudioProfile对象,并将该对象添加到对应IOProfile的mProfiles链表。
回到modules的解析方法中,mixPorts标签解析完成后,调用HwModule的setProfiles保存解析的结果
//frameworks/av/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp void HwModule::setProfiles(const IOProfileCollection &profiles) { for (size_t i = 0; i < profiles.size(); i++) {//遍历得到的IOProfile addProfile(profiles[i]); } } status_t HwModule::addProfile(const sp<IOProfile> &profile) { switch (profile->getRole()) { case AUDIO_PORT_ROLE_SOURCE: return addOutputProfile(profile); case AUDIO_PORT_ROLE_SINK: return addInputProfile(profile); case AUDIO_PORT_ROLE_NONE: return BAD_VALUE; } return BAD_VALUE; }
可以看出,对于role为sink的IOProfile,则添加到HwModule的mInputProfiles中,比如上面场景的primary input。对于role为source的IOProfile,则是添加到mOutputProfiles中,比如上面场景的primary output,hdmi等。比如针对上面的场景,经过解析之后可以得到以下信息
解析devicePorts标签
<devicePorts> <devicePort tagName="Speaker" type="AUDIO_DEVICE_OUT_SPEAKER" role="sink"> </devicePort> <devicePort tagName="Wired Headset" type="AUDIO_DEVICE_OUT_WIRED_HEADSET" role="sink"> </devicePort> <devicePort tagName="Wired Headphones" type="AUDIO_DEVICE_OUT_WIRED_HEADPHONE" role="sink"> </devicePort> <devicePort tagName="BT SCO" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO" role="sink"> </devicePort> <devicePort tagName="BT SCO Headset" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET" role="sink"> </devicePort> <devicePort tagName="BT SCO Car Kit" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT" role="sink"> </devicePort> <devicePort tagName="HDMI Out" type="AUDIO_DEVICE_OUT_AUX_DIGITAL" role="sink"> </devicePort> <devicePort tagName="SPDIF Out" type="AUDIO_DEVICE_OUT_SPDIF" role="sink"> </devicePort> <devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source"> </devicePort> <devicePort tagName="Wired Headset Mic" type="AUDIO_DEVICE_IN_WIRED_HEADSET" role="source"> </devicePort> <devicePort tagName="BT SCO Headset Mic" type="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET" role="source"> </devicePort> <devicePort tagName="HDMIIn" type="AUDIO_DEVICE_IN_HDMI" role="source"> </devicePort> </devicePorts>
对于devicePorts标签,循环调用DevicePortTraits的deserialize来解析其子标签
Return<DevicePortTraits::Element> DevicePortTraits::deserialize(const xmlNode *cur, PtrSerializingCtx /*serializingContext*/) { std::string name = getXmlAttribute(cur, Attributes::tagName);//得到名字:Speaker,Wired Headset等 std::string typeName = getXmlAttribute(cur, Attributes::type);//得到类型 std::string role = getXmlAttribute(cur, Attributes::role);//sink或者source audio_port_role_t portRole = (role == Attributes::roleSource) ? AUDIO_PORT_ROLE_SOURCE : AUDIO_PORT_ROLE_SINK; //省略 Element deviceDesc = new DeviceDescriptor(type, name, address, encodedFormats);//创建DeviceDescriptor对象 AudioProfileTraits::Collection profiles; status_t status = deserializeCollection<AudioProfileTraits>(cur, &profiles, NULL);//解析devicePort标签下的profile标签 // The audio profiles are in order of listed in audio policy configuration file. // Sort audio profiles accroding to the format. sortAudioProfiles(profiles); deviceDesc->setAudioProfiles(profiles); //省略
首先解析得到name和type,然后创建DeviceDescriptor对象,最后也是解析profile标签并将得到的AudioProfile添加到对应的DeviceDescriptor对象的mProfiles链表中。解析完成后,回到ModuleTraits::deserialize函数中,调用HwModule的setDeclaredDevices保存解析的结果
//frameworks/av/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
void HwModule::setDeclaredDevices(const DeviceVector &devices)
{
mDeclaredDevices = devices;//保存到mDeclaredDevices中
for (size_t i = 0; i < devices.size(); i++) {
mPorts.add(devices[i]);//保存到mPorts中
}
}
最后将结果保存在HwModule的mDeclaredDevices和mPorts中。针对上面的场景,可以得到以下解析结果
解析routes标签
<routes> <route type="mix" sink="Speaker" sources="primary output"/> <route type="mix" sink="Wired Headset" sources="primary output"/> <route type="mix" sink="Wired Headphones" sources="primary output"/> <route type="mix" sink="BT SCO" sources="primary output"/> <route type="mix" sink="BT SCO Headset" sources="primary output"/> <route type="mix" sink="BT SCO Car Kit" sources="primary output"/> <route type="mix" sink="HDMI Out" sources="primary output,hdmi"/> <route type="mix" sink="SPDIF Out" sources="primary output,spdif_passthrough"/> <route type="mix" sink="primary input" sources="Built-In Mic,Wired Headset Mic,BT SCO Headset Mic,HDMIIn"/> </routes>
对于routes下的子标签,调用RouteTraits的deserialize解析处理
Return<RouteTraits::Element> RouteTraits::deserialize(const xmlNode *cur, PtrSerializingCtx ctx) { std::string type = getXmlAttribute(cur, Attributes::type);//解析type audio_route_type_t routeType = (type == Attributes::typeMix) ? AUDIO_ROUTE_MIX : AUDIO_ROUTE_MUX; Element route = new AudioRoute(routeType);//创建AudioRoute对象 std::string sinkAttr = getXmlAttribute(cur, Attributes::sink);//解析sink sp<PolicyAudioPort> sink = ctx->findPortByTagName(sinkAttr);//根据解析得到的sink的名字,从ports链表中找到DeviceDescriptor route->setSink(sink);//将找到的DeviceDescriptor添加到AudioRoute的mSink中 std::string sourcesAttr = getXmlAttribute(cur, Attributes::sources);//解析sources PolicyAudioPortVector sources; std::unique_ptr<char[]> sourcesLiteral{strndup( sourcesAttr.c_str(), strlen(sourcesAttr.c_str()))}; char *devTag = strtok(sourcesLiteral.get(), ","); while (devTag != NULL) { if (strlen(devTag) != 0) { sp<PolicyAudioPort> source = ctx->findPortByTagName(devTag);//根据source,可以找到对应的IOProfile sources.add(source); } devTag = strtok(NULL, ","); } sink->addRoute(route);//将该route添加到sink的mRoutes链表中 for (size_t i = 0; i < sources.size(); i++) { sp<PolicyAudioPort> source = sources.itemAt(i); source->addRoute(route);//将该route添加到source的mRoutes链表中 } route->setSources(sources);//将source添加到AudioRoute的mSources中 return route; }
该方法主要是解析sink和source,然后根据其名字,分别找到对应的PolicyAudioPort,设置AudioRoute的mSink和mSources。回到ModuleTraits::deserialize函数中,调用HwModule的setRoutes保存解析的结果
//frameworks/av/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
void HwModule::setRoutes(const AudioRouteVector &routes)
{
mRoutes = routes;//将结果保存在mRoutes 中
// Now updating the streams (aka IOProfile until now) supported devices
refreshSupportedDevices();
}
主要是将解析的结果,保存在HwModule的mRoutes 中。针对以上场景,可以得到如下结果
解析attachedDevices标签
<attachedDevices>
<item>Speaker</item>
<item>Built-In Mic</item>
<item>HDMIIn</item>
</attachedDevices>
attachedDevices标签的解析,就在ModuleTraits::deserialize函数中
for (const xmlNode *children = cur->xmlChildrenNode; children != NULL; children = children->next) { if (!xmlStrcmp(children->name, reinterpret_cast<const xmlChar*>(childAttachedDevicesTag))) { ALOGV("%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))) { auto attachedDevice = make_xmlUnique(xmlNodeListGetString( child->doc, child->xmlChildrenNode, 1)); if (attachedDevice != nullptr) { sp<DeviceDescriptor> device = module->getDeclaredDevices(). getDeviceFromTagName(std::string(reinterpret_cast<const char*>( attachedDevice.get())));//从mDeclaredDevices 链表中根据名字找到DeviceDescriptor ctx->addDevice(device);//更加type类型,分别添加到AudioPolicyConfig的mOutputDevices和mInputDevices中 } } } }
来看一下addDevice方法
///frameworks/av/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
void addDevice(const sp<DeviceDescriptor> &device)
{
if (audio_is_output_device(device->type())) {
mOutputDevices.add(device);
} else if (audio_is_input_device(device->type())) {
mInputDevices.add(device);
}
}
解析defaultOutputDevice标签
<defaultOutputDevice>Speaker</defaultOutputDevice>
对于该标签的解析比较简单,主要从mDeclaredDevices 链表中根据名字找到对应的DeviceDescriptor,然后将其赋值给AudioPolicyConfig的mDefaultOutputDevice成员
回到PolicySerializer::deserialize方法,当moudles解析完成后,会将解析得到的HwModule保存在AudioPolicyConfig的mHwModules中
//frameworks/av/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
void setHwModules(const HwModuleCollection &hwModules)
{
mHwModules = hwModules;
}
总结
HwModuleCollection &mHwModules; /**< Collection of Module, with Profiles, i.e. Mix Ports. */
DeviceVector &mOutputDevices;
DeviceVector &mInputDevices;
sp<DeviceDescriptor> &mDefaultOutputDevice;
其中mHwModules保存的是modules标签下的每个HwModule,解析attachedDevices标签时,会根据其名字找到对应的DeviceDescriptor,然后根据这些DeviceDescriptor的type,分别放入mOutputDevices和mInputDevices中。解析defaultOutputDevice标签时,根据名字找到对应的DeviceDescriptor,然后保存在mDefaultOutputDevice中
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。