https://blog.youkuaiyun.com/we1less/article/details/156362906?spm=1001.2014.3001.5502
继续分析上文中提到的 dumpsys media.audio_policy
streamType 是如何从老版本转向新版本的 mContentType 和 mUsage
这个方法就是使用 LegacyStreamType 根据传进来的 streamType 参数获取 mUsage
这里的策略可以使用 dumpsys media.audio_policy 查看
dumpsys media.audio_policy
主要分析两部分
Product Strategies dump:产品策略
Volume Groups dump:音频曲线
Policy Engine dump:
Product Strategies dump:
-STRATEGY_PHONE (id: 0)
Selected Device: {AUDIO_DEVICE_OUT_EARPIECE, @:}
Group: 13 stream: AUDIO_STREAM_VOICE_CALL
Attributes: { Content type: AUDIO_CONTENT_TYPE_UNKNOWN Usage: AUDIO_USAGE_VOICE_COMMUNICATION Source: AUDIO_SOURCE_INVALID Flags: 0x0 Tags: }
Group: 3 stream: AUDIO_STREAM_BLUETOOTH_SCO
Attributes: { Content type: AUDIO_CONTENT_TYPE_UNKNOWN Usage: AUDIO_USAGE_UNKNOWN Source: AUDIO_SOURCE_INVALID Flags: 0x4 Tags: }
//...
Volume Groups dump:
-AUDIO_STREAM_ACCESSIBILITY (id: 1)
Volume Curves Streams/Attributes, Curve points Streams for device category (index, attenuation in millibel)
Streams: AUDIO_STREAM_ACCESSIBILITY(10)
Attributes: { Content type: AUDIO_CONTENT_TYPE_UNKNOWN Usage: AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY Source: AUDIO_SOURCE_DEFAULT Flags: 0x0 Tags: }
DEVICE_CATEGORY_HEADSET : { ( 0, -5800), ( 20, -4000), ( 60, -1700), (100, 0) }
DEVICE_CATEGORY_SPEAKER : { ( 0, -5800), ( 20, -4000), ( 60, -1700), (100, 0) }
DEVICE_CATEGORY_EARPIECE : { ( 0, -5800), ( 20, -4000), ( 60, -1700), (100, 0) }
DEVICE_CATEGORY_EXT_MEDIA : { ( 0, -5800), ( 20, -4000), ( 60, -1700), (100, 0) }
DEVICE_CATEGORY_HEARING_AID : { ( 0, -12700), ( 20, -8000), ( 60, -4000), (100, 0) }
Can be muted Index Min Index Max Index Cur [device : index]...
true 01 15 0002 : 06, 0080 : 02, 0100 : 02, 4000000 : 05, 20000000 : 02, 20000002 : 02, 40000000 : 06,
//...
这些信息是如何被装载的呢
产品策略 Product Strategies
av/services/audiopolicy/engine/common/src/EngineBase.cpp
这个函数的 xmlFilePath 入参为空,
engineConfig::DEFAULT_PATH 这个在设备中也没有
constexpr char DEFAULT_PATH[] = "/vendor/etc/audio_policy_engine_configuration.xml";
所以使用的是 gDefaultEngineConfig
engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig(
const std::string& xmlFilePath, bool isConfigurable)
{
//...
const std::string filePath = xmlFilePath.empty() ? engineConfig::DEFAULT_PATH : xmlFilePath;
engineConfig::ParsingResult result =
fileExists(filePath.c_str()) ?
engineConfig::parse(filePath.c_str(), isConfigurable) : engineConfig::ParsingResult{};
if (result.parsedConfig == nullptr) {
ALOGD("%s: No configuration found, using default matching phone experience.", __FUNCTION__);
engineConfig::Config config = gDefaultEngineConfig;
android::status_t ret = engineConfig::parseLegacyVolumes(config.volumeGroups);
result = {std::make_unique<engineConfig::Config>(config),
static_cast<size_t>(ret == NO_ERROR ? 0 : 1)};
} else {
//...
}
//...
return processParsingResult(std::move(result));
}
av/services/audiopolicy/engine/common/src/EngineDefaultConfig.h gDefaultEngineConfig
可以看到产品策略的信息 Product Strategies 是在代码里面写死的
可以使用 xml 进行配置,参考
av/services/audiopolicy/enginedefault/config/example/phone/audio_policy_engine_configuration.xml
const engineConfig::Config gDefaultEngineConfig = {
1.0,
gOrderedStrategies,
{},
{},
{}
};
const engineConfig::ProductStrategies gOrderedStrategies = {
{"STRATEGY_PHONE", STRATEGY_PHONE,
{
{AUDIO_STREAM_VOICE_CALL, "AUDIO_STREAM_VOICE_CALL",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_SOURCE_DEFAULT,
AUDIO_FLAG_NONE, ""}},
},
{AUDIO_STREAM_BLUETOOTH_SCO, "AUDIO_STREAM_BLUETOOTH_SCO",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_SCO,
""}},
}
},
},
//...
//...
};
av/services/audiopolicy/engine/config/include/EngineConfig.h ProductStrategies
是一个链表类型,是 ProductStrategy 的集合
using ProductStrategies = std::vector<ProductStrategy>;
struct ProductStrategy {
std::string name;
int id;
AttributesGroups attributesGroups;
};
using AttributesGroups = std::vector<AttributesGroup>;
struct AttributesGroup {
audio_stream_type_t stream;
std::string volumeGroup;
AttributesVector attributesVect;
};
using AttributesVector = std::vector<audio_attributes_t>;
// audio_attributes_t 定义
// media/audio/include/system/audio.h
static const audio_attributes_t AUDIO_ATTRIBUTES_INITIALIZER = {
/* .content_type = */ AUDIO_CONTENT_TYPE_UNKNOWN,
/* .usage = */ AUDIO_USAGE_UNKNOWN,
/* .source = */ AUDIO_SOURCE_DEFAULT,
/* .flags = */ AUDIO_FLAG_NONE,
/* .tags = */ ""
};
// #### 对应关系
// ProductStrategies 对应 ProductStrategies = std::vector<ProductStrategy>;
const engineConfig::ProductStrategies gOrderedStrategies = {
// 这一层元素对应 ProductStrategy 结构体
// ProductStrategy::name 对应 "STRATEGY_MEDIA"
// ProductStrategy::id 对应 STRATEGY_MEDIA
{"STRATEGY_MEDIA", STRATEGY_MEDIA,
{ // ProductStrategy::AttributesGroups 集合
// 这一层元素对应 AttributesGroup 结构体
// AttributesGroup::audio_stream_type_t 对应 AUDIO_STREAM_MUSIC
// AttributesGroup::volumeGroup 对应 "AUDIO_STREAM_MUSIC"
{AUDIO_STREAM_MUSIC, "AUDIO_STREAM_MUSIC",
{ // ProductStrategy::AttributesGroups 集合
// 这一层元素对应 audio_attributes_t 结构体
{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_MEDIA, AUDIO_SOURCE_DEFAULT,
AUDIO_FLAG_NONE, ""},
{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_GAME, AUDIO_SOURCE_DEFAULT,
AUDIO_FLAG_NONE, ""},
},
},
{AUDIO_STREAM_SYSTEM, "AUDIO_STREAM_SYSTEM",
{
{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ASSISTANCE_SONIFICATION,
AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""}
},
}
},
},
//...
}
// ProductStrategy::id 参考路径
// av/services/audiopolicy/common/include/policy.h
#define AUDIO_LEGACY_STRATEGY_LIST_DEF(V) \
V(STRATEGY_NONE, -1) \
V(STRATEGY_PHONE, 0) \
V(STRATEGY_SONIFICATION, 1) \
V(STRATEGY_ENFORCED_AUDIBLE, 2) \
V(STRATEGY_ACCESSIBILITY, 3) \
V(STRATEGY_SONIFICATION_RESPECTFUL, 4) \
V(STRATEGY_MEDIA, 5) \
V(STRATEGY_DTMF, 6) \
V(STRATEGY_CALL_ASSISTANT, 7) \
V(STRATEGY_TRANSMITTED_THROUGH_SPEAKER, 8) \
V(STRATEGY_REROUTING, 9) \
V(STRATEGY_PATCH, 10)
音频曲线 Volume Groups
av/services/audiopolicy/engine/config/src/EngineConfig.cpp
调用 audio_get_audio_policy_config_file
android::status_t parseLegacyVolumes(VolumeGroups &volumeGroups) {
if (std::string audioPolicyXmlConfigFile = audio_get_audio_policy_config_file();
!audioPolicyXmlConfigFile.empty()) {
return parseLegacyVolumeFile(audioPolicyXmlConfigFile.c_str(), volumeGroups);
} else {
ALOGE("No readable audio policy config file found");
return BAD_VALUE;
}
}
media/audio/include/system/audio_config.h
vendor/etc/audio_policy_configuration.xml
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;
}
vendor/etc/audio_policy_configuration.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
<!-- Volume section -->
<xi:include href="/vendor/etc/audio_policy_volumes.xml"/>
<xi:include href="/vendor/etc/default_volume_tables.xml"/>
<!-- End of Volume section -->
</audioPolicyConfiguration>
vendor/etc/audio_policy_volumes.xml
<?xml version="1.0" encoding="UTF-8"?>
<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_TTS" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA"
ref="SILENT_VOLUME_CURVE"/>
<!-- ... -->
</volumes>
/vendor/etc/default_volume_tables.xml
<?xml version="1.0" encoding="UTF-8"?>
<volumes>
<!-- ... -->
<reference name="SILENT_VOLUME_CURVE">
<point>0,-9600</point>
<point>100,-9600</point>
</reference>
<!-- ... -->
</volumes>
av/services/audiopolicy/engine/config/src/EngineConfig.cpp parseLegacyVolumeFile
android::status_t parseLegacyVolumeFile(const char* path, VolumeGroups &volumeGroups) {
//...
return deserializeLegacyVolumeCollection(doc.get(), cur, volumeGroups, nbSkippedElements);
}
// 入参 装载 volumeGroups
static status_t deserializeLegacyVolumeCollection(_xmlDoc *doc, const _xmlNode *cur,
VolumeGroups &volumeGroups,
size_t &nbSkippedElement)
{
//填充的legacyVolumeMap
std::map<std::string, VolumeCurves> legacyVolumeMap;
for (...) {
for (...) {
if (!xmlStrcmp(child->name, (const xmlChar *)legacyVolumeTag)) {
status_t status = deserializeLegacyVolume(doc, child, legacyVolumeMap);
}
}
}
VolumeGroups tempVolumeGroups = volumeGroups;
for (legacyVolumeMap) {
audio_stream_type_t streamType;
// 对应第一个元素 stream
StreamTypeConverter::fromString(volumeMapIter.first, streamType)
int indexMin = streamType >= AUDIO_STREAM_PUBLIC_CNT ? 0 : -1;
int indexMax = streamType >= AUDIO_STREAM_PUBLIC_CNT ? 100 : -1;
// 把结果装载到 tempVolumeGroups
tempVolumeGroups.push_back(
{ volumeMapIter.first, indexMin, indexMax, volumeMapIter.second });
}
return NO_ERROR;
}
//入参 根据 xml 装载 legacyVolumeMap
status_t deserializeLegacyVolume(_xmlDoc *doc, const _xmlNode *cur,
std::map<std::string, VolumeCurves> &legacyVolumes)
{
std::string streamTypeLiteral = getXmlAttribute(cur, "stream");
std::string deviceCategoryLiteral = getXmlAttribute(cur, "deviceCategory");
CurvePoints curvePoints;
for (...) {
curvePoints.push_back({point[0], point[1]});
}
}
// legacyVolumes 类型 std::map<std::string, VolumeCurves> &legacyVolumes
legacyVolumes[streamTypeLiteral].push_back({ deviceCategoryLiteral, curvePoints });
return NO_ERROR;
}
// VolumeCurves 参考
// av/services/audiopolicy/engine/config/include/EngineConfig.h
using VolumeGroups = std::vector<VolumeGroup>;
struct VolumeGroup {
std::string name;
int indexMin;
int indexMax;
VolumeCurves volumeCurves;
};
using VolumeCurves = std::vector<VolumeCurve>;
struct VolumeCurve {
std::string deviceCategory;
CurvePoints curvePoints;
};
using CurvePoints = std::vector<CurvePoint>;
struct CurvePoint {
int index;
int attenuationInMb;
};
// /vendor/etc/audio_policy_volumes.xml
<volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_SPEAKER">
<point>1,-6600</point>
<point>30,-2000</point>
<point>85,-800</point>
<point>100,0</point>
</volume>
现在两个结构体都被填充完毕了,回到最开始解析的地方
av/services/audiopolicy/engine/common/src/EngineBase.cpp
首先看入参是怎么装载的
engineConfig::Config config = gDefaultEngineConfig; 这里面包含了 Product Strategies
config.volumeGroups 这里面包含了 Volume Groups
调用 processParsingResult 入参 config
engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig(
const std::string& xmlFilePath, bool isConfigurable)
{
engineConfig::Config config = gDefaultEngineConfig;
engineConfig::parseLegacyVolumes(config.volumeGroups);
result = {std::make_unique<engineConfig::Config>(config),
static_cast<size_t>(ret == NO_ERROR ? 0 : 1)};
return processParsingResult(std::move(result));
}
loadVolumeConfig 函数,将上述装载的 config.volumeGroups 结构体结合转换为 VolumeGroup 类,将音频曲线转换成 VolumeCurve 装进 volumeGroup 中,最终放在 volumeGroups 中
执行 loadVolumeConfig 装载到 mVolumeGroups
找到 name 一样的,ProductStrategy::AttributesGroup::volumeGroup == volumeGroup::name
addSupportedAttributesToGroup 函数,将 Attributes 关联到 volumeGroup
将关联好后的 ProductStrategy 装载到 mProductStrategies
engineConfig::ParsingResult EngineBase::processParsingResult(
engineConfig::ParsingResult&& rawResult)
{
auto loadVolumeConfig = [](auto &volumeGroups, auto &volumeConfig) {
sp<VolumeGroup> volumeGroup = new VolumeGroup(volumeConfig.name, volumeConfig.indexMin,
volumeConfig.indexMax);
// 将上述装载的 config.volumeGroups 结构体转换为 VolumeGroup 类,最终放在 volumeGroups 中
volumeGroups[volumeGroup->getId()] = volumeGroup;
for (auto &configCurve : volumeConfig.volumeCurves) {
sp<VolumeCurve> curve = new VolumeCurve(deviceCat);
for (auto &point : configCurve.curvePoints) {
curve->add({point.index, point.attenuationInMb});
}
//将音频曲线转换成 VolumeCurve 塞进 volumeGroup 中
volumeGroup->add(curve);
}
return volumeGroup;
};
auto addSupportedAttributesToGroup = [](auto &group, auto &volumeGroup, auto &strategy) {
// 将 Attributes 关联到 volumeGroup
};
// 执行 loadVolumeConfig 装载到 mVolumeGroups
// 参考 av/services/audiopolicy/engine/common/include/EngineBase.h
// VolumeGroupMap mVolumeGroups;
for (auto &volumeConfig : result.parsedConfig->volumeGroups) {
loadVolumeConfig(mVolumeGroups, volumeConfig);
}
// 构造 ProductStrategy
for (auto& strategyConfig : result.parsedConfig->productStrategies) {
sp<ProductStrategy> strategy = new ProductStrategy(strategyConfig.name, strategyConfig.id);
// 找到name一样的
// ProductStrategy::AttributesGroup::volumeGroup == volumeGroup::name
// <volume stream="AUDIO_STREAM_MUSIC"> == {AUDIO_STREAM_MUSIC, "AUDIO_STREAM_MUSIC",
const auto &iter = std::find_if(begin(mVolumeGroups), end(mVolumeGroups),
[&group](const auto &volumeGroup) {
return group.volumeGroup == volumeGroup.second->getName(); });
if (iter == end(mVolumeGroups)) {
//找不到
} else {
// 这样根据这个 name 就能锁定音频曲线了
volumeGroup = iter->second;
}
addSupportedAttributesToGroup(group, volumeGroup, strategy);
// 参考 av/services/audiopolicy/engine/common/include/EngineBase.h
// ProductStrategyMap mProductStrategies;
mProductStrategies[strategyId] = strategy;
}
mProductStrategies.initialize();
return result;
}
1448

被折叠的 条评论
为什么被折叠?



