5、EngineBase加载音量曲线和策略 【基于Android Q 】
5.1、音量曲线
5.1.1、mVolumeGroups音量曲线加载
frameworks/av/services/audiopolicy/managerdefault/engine/common/src/EngineBase.cpp
engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig(){
...
auto loadVolumeGroups = [](auto &volumeConfigs, auto &volumeGroups) {
for (auto &volumeConfig : volumeConfigs) {
sp<VolumeGroup> volumeGroup = new VolumeGroup(volumeConfig.name, volumeConfig.indexMin, volumeConfig.indexMax);
/* 小编的打印 */
ALOGI("hippo id:%d, name:%s, min:%d, max:%d volumeConfig.volumeCurves:%d",
volumeGroup->getId(), volumeConfig.name.c_str(), volumeConfig.indexMin,
volumeConfig.indexMax, volumeConfig.volumeCurves.size());
volumeGroups[volumeGroup->getId()] = volumeGroup;
for (auto &configCurve : volumeConfig.volumeCurves) {
device_category deviceCat = DEVICE_CATEGORY_SPEAKER;
/* 小编的打印 */
ALOGI("APM configCurve:%s", configCurve.deviceCategory.c_str());
if (!DeviceCategoryConverter::fromString(configCurve.deviceCategory, deviceCat)) {
ALOGE("%s: Invalid %s", __FUNCTION__, configCurve.deviceCategory.c_str());
continue;
}
sp<VolumeCurve> curve = new VolumeCurve(deviceCat);
for (auto &point : configCurve.curvePoints) {
/* 小编的打印 */
ALOGI("APM index:%d, attenuationInMb:%d", point.index, point.attenuationInMb);
curve->add({point.index, point.attenuationInMb});
}
volumeGroup->add(curve);
}
}
};
auto result = engineConfig::parse();
if (result.parsedConfig == nullptr) {
ALOGW("%s: No configuration found, using default matching phone experience.", __FUNCTION__);
engineConfig::Config config = gDefaultEngineConfig;
/* 将audio_policy_volumes.xml中的所有值加载到volumeGroups */
android::status_t ret = engineConfig::parseLegacyVolumes(config.volumeGroups);
result = {std::make_unique<engineConfig::Config>(config),
static_cast<size_t>(ret == NO_ERROR ? 0 : 1)};
}
ALOGE_IF(result.nbSkippedElement != 0, "skipped %zu elements", result.nbSkippedElement);
/* 回调上面的Lambda 表达式loadVolumeGroups */
loadVolumeGroups(result.parsedConfig->volumeGroups, mVolumeGroups);
...
}
音量曲线的定义在/vendor/etc/audio_policy_volumes.xml文件中,所有的相关参数都是从该文件加载。
- 共13个volume group
AUDIO_STREAM_ACCESSIBILITY
AUDIO_STREAM_ALARM
AUDIO_STREAM_BLUETOOTH_SCO
AUDIO_STREAM_DTMF
AUDIO_STREAM_ENFORCED_AUDIBLE
AUDIO_STREAM_MUSIC
AUDIO_STREAM_NOTIFICATION
AUDIO_STREAM_PATCH
AUDIO_STREAM_REROUTING
AUDIO_STREAM_RING
AUDIO_STREAM_SYSTEM
AUDIO_STREAM_TTS
AUDIO_STREAM_VOICE_CALL - 每个group有4个设备类型曲线(实际的设备对应的曲线根据策略选择以下4中设备类型曲线)
- getDeviceCategory函数中有设备type和这个设备类型的对应关系
switch(getDeviceForVolume(deviceTypes)) {
case AUDIO_DEVICE_OUT_EARPIECE:
return DEVICE_CATEGORY_EARPIECE;
case AUDIO_DEVICE_OUT_WIRED_HEADSET:
case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
case AUDIO_DEVICE_OUT_BLUETOOTH_SCO:
case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
case AUDIO_DEVICE_OUT_USB_HEADSET:
return DEVICE_CATEGORY_HEADSET;
case AUDIO_DEVICE_OUT_HEARING_AID:
return DEVICE_CATEGORY_HEARING_AID;
case AUDIO_DEVICE_OUT_LINE:
case AUDIO_DEVICE_OUT_AUX_DIGITAL:
case AUDIO_DEVICE_OUT_USB_DEVICE:
return DEVICE_CATEGORY_EXT_MEDIA;
case AUDIO_DEVICE_OUT_SPEAKER:
case AUDIO_DEVICE_OUT_SPEAKER_SAFE:
case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
case AUDIO_DEVICE_OUT_USB_ACCESSORY:
case AUDIO_DEVICE_OUT_REMOTE_SUBMIX:
default:
return DEVICE_CATEGORY_SPEAKER;
DEVICE_CATEGORY_HEADSET
DEVICE_CATEGORY_SPEAKER
DEVICE_CATEGORY_EARPIECE
DEVICE_CATEGORY_EXT_MEDIA
参考音量曲线配置文件:
/vendor/etc/audio_policy_volumes.xml
/vendor/etc/default_volume_tables.xml
对应dumpsys media.audio_policy:
Volume Groups dump:字段
5.1.2、音量设置
单板目录 /product/build.prop (Android R)
5.1.2.1、默认音量
开机起来AUDIO_STREAM_MUSIC的默认音量prop设置为,见上图
ro.config.media_vol_default
5.1.2.2、最大音量
AUDIO_STREAM_MUSIC的UI可设置的最大音量prop为,见上图
ro.config.media_vol_steps
根据UI的index值,以及UI的min和max值,将UI index值印射到audio_policy_volumes.xml中定义的音量曲线点,这样换算出音量曲线中对应的mAttenuationInMb值。
- 如果该stream是在AudioFlinger的Direct 线程上的,则将该Mb值设置到audio hal;
audio hal将Mb值除以100,得到Db值,然后再将Db值换算为(0-1)之间的 float值应用。
static inline float DbToAmpl(float decibels)
{
if (decibels <= VOLUME_MIN_DB) {
return 0.0f;
}
return exp(decibels * 0.115129f); // exp( dB * ln(10) / 20 )
}
- 如果该stream是AudioFlinger上的Mixer的一个pcm的AudioTrack,则直接在AudioFlinger的线程里面对该track的音量进行处理。
例如: UI音量为10,UI配置最大音量为20,音量曲线中配置了101个点(0-100, 每个点对应一个Mb值)。当UI设置音量为1时,印射到音量曲线为第5个点,对应的Mb为-5000。
<reference name="SPEAKER_CURVE">
<point>0,-10000</point>
<point>1,-7200</point>
<point>2,-6300</point>
<point>3,-5800</point>
<point>4,-5300</point>
<point>5,-5000</point>
<point>6,-4700</point>
<point>7,-4550</point>
.
.
.
<point>96,-200</point>
<point>97,-100</point>
<point>98,-100</point>
<point>99,-50</point>
<point>100,0</point>
5.2、mProductStrategies策略加载
frameworks/av/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
frameworks/av/services/audiopolicy/managerdefault/engine/common/src/EngineBase.cpp
engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig()
{
auto loadProductStrategies =
[](auto& strategyConfigs, auto& productStrategies, auto& volumeGroups) {
for (auto& strategyConfig : strategyConfigs) {
sp<ProductStrategy> strategy = new ProductStrategy(strategyConfig.name);
/* 小编的打印 */
ALOGI("[%s:%d] strategyConfig name:%s, mId:%d -------->", __func__, __LINE__,
strategyConfig.name.c_str(), strategy->getId());
for (const auto &group : strategyConfig.attributesGroups) {
const auto &iter = std::find_if(begin(volumeGroups), end(volumeGroups),
[&group](const auto &volumeGroup) {
/* 返回将AttributesGroup中stream名称跟VolumeGroup匹配的VolumeGroup iter*/
return group.volumeGroup == volumeGroup.second->getName(); });
ALOG_ASSERT(iter != end(volumeGroups), "Invalid Volume Group Name %s",
group.volumeGroup.c_str());
if (group.stream != AUDIO_STREAM_DEFAULT) {
/* 将AttributesGroup中stream的audio_stream_type_t给VolumeGroup */
iter->second->addSupportedStream(group.stream);
}
/* 小编的打印 */
ALOGI("[%s:%d] group name:%s, stream:%d", __func__, __LINE__, group.name.c_str(), group.stream);
for (const auto &attr : group.attributesVect) {
/* 小编的打印 */
ALOGI("[%s:%d] getId:%d, usage:%d", __func__, __LINE__, iter->second->getId(), attr.usage);
strategy->addAttributes({group.stream, iter->second->getId(), attr});
/* 将AttributesGroup中stream名称跟VolumeGroup匹配的audio_attributes_t添加到对应的VolumeGroup */
iter->second->addSupportedAttributes(attr);
}
}
product_strategy_t strategyId = strategy->getId();
productStrategies[strategyId] = strategy;
}
};
...
auto result = engineConfig::parse();
if (result.parsedConfig == nullptr) {
ALOGW("%s: No configuration found, using default matching phone experience.", __FUNCTION__);
/* 这里只对Config类对象config的成员productStrategies赋值,EngineDefaultConfig.h*/
engineConfig::Config config = gDefaultEngineConfig;
/* 对Config类对象config的成员volumeGroups赋值*/
android::status_t ret = engineConfig::parseLegacyVolumes(config.volumeGroups);
result = {std::make_unique<engineConfig::Config>(config),
static_cast<size_t>(ret == NO_ERROR ? 0 : 1)};
}
ALOGE_IF(result.nbSkippedElement != 0, "skipped %zu elements", result.nbSkippedElement);
loadVolumeGroups(result.parsedConfig->volumeGroups, mVolumeGroups);
/* 回调上面的Lambda 表达式loadProductStrategies */
loadProductStrategies(result.parsedConfig->productStrategies, mProductStrategies,
mVolumeGroups);
mProductStrategies.initialize();
return result;
}
共10个strategy
STRATEGY_PHONE
STRATEGY_SONIFICATION
STRATEGY_ENFORCED_AUDIBLE
STRATEGY_ACCESSIBILITY
STRATEGY_SONIFICATION_RESPECTFUL
STRATEGY_MEDIA
STRATEGY_DTMF
STRATEGY_TRANSMITTED_THROUGH_SPEAKER
STRATEGY_REROUTING
STRATEGY_PATCH
默认加载/vendor/etc/audio_policy_engine_configuration.xml,如果该文件不存在则使用默认code文件的定义,frameworks/av/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
对应dumpsys media.audio_policy:
Product Strategies dump:字段