【Android Audio】5、EngineBase加载音量曲线和策略 【基于Android Q 】

本文详细介绍了Android Q中音频引擎加载音量曲线的过程,包括mVolumeGroups的加载,音量设置,如默认音量和最大音量的设定。同时,探讨了策略加载,特别是mProductStrategies的10个不同策略。内容涵盖了音量曲线配置文件、设备类型曲线、以及AudioPolicy的策略配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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:字段
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值