赞
踩
在启动AudioPolicyService时,通过EngineBase的loadAudioPolicyEngineConfig函数去解析strategy配置。其调用流程如下
接下来就对loadAudioPolicyEngineConfig展开分析
1,解析volume标签
engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig()
{
//省略
auto result = engineConfig::parse();//1
if (result.parsedConfig == nullptr) {
engineConfig::Config config = gDefaultEngineConfig;//2
android::status_t ret = engineConfig::parseLegacyVolumes(config.volumeGroups);//3
result = {std::make_unique<engineConfig::Config>(config),
static_cast<size_t>(ret == NO_ERROR ? 0 : 1)};
} else {
//省略
}
//省略
}
注释1处,parse函数会去解析/vendor/etc/audio_policy_engine_configuration.xml 文件,我的Android 11 源码环境没有这个文件,所以会进入if分支。注释2处设置默认配置为gDefaultEngineConfig。注释3处调用parseLegacyVolumes去解析audio_policy_configuration.xml文件下的volume标签。
parseLegacyVolumes找到audio_policy_configuration.xml文件后,调用到deserializeLegacyVolumeCollection函数继续解析
//frameworks/av/services/audiopolicy/engine/config/src/EngineConfig.cpp static status_t deserializeLegacyVolumeCollection(_xmlDoc *doc, const _xmlNode *cur, VolumeGroups &volumeGroups, size_t &nbSkippedElement) { std::map<std::string, VolumeCurves> legacyVolumeMap; for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { if (xmlStrcmp(cur->name, (const xmlChar *)legacyVolumecollectionTag)) {//legacyVolumecollectionTag:volumes continue; } const xmlNode *child = cur->xmlChildrenNode; for (; child != NULL; child = child->next) { if (!xmlStrcmp(child->name, (const xmlChar *)legacyVolumeTag)) {//legacyVolumeTag:volume status_t status = deserializeLegacyVolume(doc, child, legacyVolumeMap);//1 if (status != NO_ERROR) { nbSkippedElement += 1; } } } } for (const auto &volumeMapIter : legacyVolumeMap) { //省略 int indexMin = streamType >= AUDIO_STREAM_PUBLIC_CNT ? 0 : -1; int indexMax = streamType >= AUDIO_STREAM_PUBLIC_CNT ? 100 : -1; volumeGroups.push_back({ volumeMapIter.first, indexMin, indexMax, volumeMapIter.second });//2 } return NO_ERROR; }
注释1处,对volumes标签下的每个volume,调用deserializeLegacyVolume处理,解析的结果放在legacyVolumeMap这个容器中。注释2处将map容器的内容保存到volumeGroups中
deserializeLegacyVolume
//frameworks/av/services/audiopolicy/engine/config/src/EngineConfig.cpp status_t deserializeLegacyVolume(_xmlDoc *doc, const _xmlNode *cur, std::map<std::string, VolumeCurves> &legacyVolumes) { std::string streamTypeLiteral = getXmlAttribute(cur, "stream");//解析stream std::string deviceCategoryLiteral = getXmlAttribute(cur, "deviceCategory");//解析deviceCategory std::string referenceName = getXmlAttribute(cur, "ref");//引用其它文件的内容,解析过程是一样的 const xmlNode *ref = NULL; if (!referenceName.empty()) { getReference(xmlDocGetRootElement(doc), ref, referenceName, legacyVolumecollectionTag); } CurvePoints curvePoints; for (const xmlNode *child = referenceName.empty() ? cur->xmlChildrenNode : ref->xmlChildrenNode; child != NULL; child = child->next) { if (!xmlStrcmp(child->name, (const xmlChar *)VolumeTraits::volumePointTag)) { xmlCharUnique pointXml(xmlNodeListGetString(doc, child->xmlChildrenNode, 1), xmlFree); std::vector<int> point; collectionFromString<DefaultTraits<int>>( reinterpret_cast<const char*>(pointXml.get()), point, ","); curvePoints.push_back({point[0], point[1]});//将解析point标签的结果保存在curvePoints中 } } legacyVolumes[streamTypeLiteral].push_back({ deviceCategoryLiteral, curvePoints });//保存到legacyVolumes中 return NO_ERROR; }
以以下内容场景为例
<volumes> <volume stream="AUDIO_STREAM_VOICE_CALL" deviceCategory="DEVICE_CATEGORY_HEADSET"> <point>0,-4200</point> <point>33,-2800</point> <point>66,-1400</point> <point>100,0</point> </volume> <volume stream="AUDIO_STREAM_VOICE_CALL" deviceCategory="DEVICE_CATEGORY_SPEAKER"> <point>0,-2400</point> <point>33,-1600</point> <point>66,-800</point> <point>100,0</point> </volume> <volume stream="AUDIO_STREAM_SYSTEM" deviceCategory="DEVICE_CATEGORY_HEADSET"> <point>1,-3000</point> <point>33,-2600</point> <point>66,-2200</point> <point>100,-1800</point> </volume> //省略 <volumes>
最后的解析结果为
再来看一下图中各结构体的定义。源码路径:frameworks/av/services/audiopolicy/engine/config/include/EngineConfig.h
VolumeCurve
struct VolumeCurve {
std::string deviceCategory;//volume标签下的deviceCategory字段
CurvePoints curvePoints;//volume标签下的point字段的集合
};
VolumeGroup
struct VolumeGroup {
std::string name;//来自于volume标签下的stream字段
int indexMin;
int indexMax;
VolumeCurves volumeCurves;//VolumeCurve 的集合
};
2,遍历volumeGroups,结果保存到EngineBase的mVolumeGroups集合中
engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig()
{
//省略
for (auto &volumeConfig : result.parsedConfig->volumeGroups) {//遍历
// save default volume config for streams not defined in configuration
if (volumeConfig.name.compare("AUDIO_STREAM_MUSIC") == 0) {
defaultVolumeConfig = volumeConfig;
}
if (volumeConfig.name.compare("AUDIO_STREAM_PATCH") == 0) {
defaultSystemVolumeConfig = volumeConfig;
}
loadVolumeConfig(mVolumeGroups, volumeConfig);
}
//省略
}
loadVolumeConfig
engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig() { auto loadVolumeConfig = [](auto &volumeGroups, auto &volumeConfig) { //省略 sp<VolumeGroup> volumeGroup = new VolumeGroup(volumeConfig.name, volumeConfig.indexMin, volumeConfig.indexMax);//创建VolumeGroup对象 volumeGroups[volumeGroup->getId()] = volumeGroup;//放入mVolumeGroups集合中 for (auto &configCurve : volumeConfig.volumeCurves) { device_category deviceCat = DEVICE_CATEGORY_SPEAKER; //省略 sp<VolumeCurve> curve = new VolumeCurve(deviceCat);//创建VolumeCurve对象 for (auto &point : configCurve.curvePoints) { curve->add({point.index, point.attenuationInMb}); } volumeGroup->add(curve);//添加到volumeGroup对象中 } return volumeGroup; };
可以看出,最后,EngineBase的mVolumeGroups保存了配置文件中volume字段的信息。
3,解析ProductStrategies,保存在EngineBase的mProductStrategies集合中
在分析之前,需要先了解几个结构体
ProductStrategy
struct ProductStrategy {
std::string name;
AttributesGroups attributesGroups;
};
AttributesGroup
struct AttributesGroup {
std::string name;
audio_stream_type_t stream;
std::string volumeGroup;
AttributesVector attributesVect;//using AttributesVector = std::vector<audio_attributes_t>;
};
audio_attributes_t
typedef struct {
audio_content_type_t content_type;
audio_usage_t usage;
audio_source_t source;
audio_flags_mask_t flags;
char tags[AUDIO_ATTRIBUTES_TAGS_MAX_SIZE]; /* UTF8 */
} __attribute__((packed)) audio_attributes_t; // sent through Binder;
gDefaultEngineConfig
//frameworks/av/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
const engineConfig::Config gDefaultEngineConfig = {
1.0,
gOrderedStrategies,
{},
{},
{}
};
接着来看解析ProductStrategies的过程
engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig() { //省略 for (auto& strategyConfig : result.parsedConfig->productStrategies) {//1,,result.parsedConfig指向前面说的默认配置gDefaultEngineConfig sp<ProductStrategy> strategy = new ProductStrategy(strategyConfig.name);//1,创建ProductStrategy类对象 for (const auto &group : strategyConfig.attributesGroups) {//遍历 const auto &iter = std::find_if(begin(mVolumeGroups), end(mVolumeGroups), [&group](const auto &volumeGroup) { return group.volumeGroup == volumeGroup.second->getName(); });//3,根据名字查找 sp<VolumeGroup> volumeGroup = nullptr; if (iter == end(mVolumeGroups)) {//没有找到的 //省略 } else { volumeGroup = iter->second;//找到了 } addSupportedAttributesToGroup(group, volumeGroup, strategy);//4,将支持的属性添加到volumeGroup和strategy中 } product_strategy_t strategyId = strategy->getId(); mProductStrategies[strategyId] = strategy;//5,保存在mProductStrategies中 }
注释1处遍历的就是gOrderedStrategies 集合。注释2处,创建ProductStrategy对象时,传入的名字就是gOrderedStrategies中各元素的名字,如:“STRATEGY_PHONE”,“STRATEGY_SONIFICATION” 。注释3处,遍历前面得到的mVolumeGroups集合,根据名字进行匹配(用volumeGroup 的名字和“AUDIO_STREAM_VOICE_CALL”,“AUDIO_STREAM_BLUETOOTH_SCO”等进行匹配),找到匹配的volumeGroup 。注释4处将支持的属性添加到volumeGroup和strategy中,注释5处将该strategy保存到EngineBase的mProductStrategies集合中
//frameworks/av/services/audiopolicy/engine/common/src/EngineDefaultConfig.h const engineConfig::ProductStrategies gOrderedStrategies = { {"STRATEGY_PHONE", { {"phone", AUDIO_STREAM_VOICE_CALL, "AUDIO_STREAM_VOICE_CALL", {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_SOURCE_DEFAULT, 0, ""}}, }, {"sco", AUDIO_STREAM_BLUETOOTH_SCO, "AUDIO_STREAM_BLUETOOTH_SCO", {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_SCO, ""}}, } }, }, {"STRATEGY_SONIFICATION", { {"ring", AUDIO_STREAM_RING, "AUDIO_STREAM_RING", {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE, AUDIO_SOURCE_DEFAULT, 0, ""}} }, {"alarm", AUDIO_STREAM_ALARM, "AUDIO_STREAM_ALARM", {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ALARM, AUDIO_SOURCE_DEFAULT, 0, ""}}, } }, }, //省略
继续来看一下addSupportedAttributesToGroup函数
engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig()
{
//省略
auto addSupportedAttributesToGroup = [](auto &group, auto &volumeGroup, auto &strategy) {
for (const auto &attr : group.attributesVect) {
strategy->addAttributes({group.stream, volumeGroup->getId(), attr});//保存在strategy的mAttributesVector中
volumeGroup->addSupportedAttributes(attr);//保存在volumeGroup中
}
};
//省略
}
总结一下上面得到的结果
除了保存在ProductStrategy中之外,还会将attr保存到匹配的volumeGroup中(根据名字匹配)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。