Android AudioPolicy策略的实现过程分析(一):音量调节

本文深入探讨了Android音频策略中的音量控制,包括软硬件音量曲线的加载和修改,音量调节流程,以及音频流类型与其别名。详细分析了AudioPolicyManager如何加载音频策略配置文件,音量曲线的XML配置,以及软硬件音量调节的实现步骤。此外,还介绍了音频流类型与AudioAttributes的对应关系。
摘要由CSDN通过智能技术生成

摘要:
Android音频策略中的音量控制方面主分为以下几点:
1.软件音量曲线和硬件音量曲线的加载过程及修改方法
2.音量调节过程的实现
3.音频流类型与其别名的对照关系

一、软音量曲线的加载及修改

概述:
在运行AudioPolicyManager的构造函数时会解析音频策略配置文件:audio_policy_configuration.xml,得到大部分音频策略信息,其中包括硬件模块、输入/输出设备及音量曲线等,这些信息会被保存在AudioPolicyConfig中

关键类及说明:

类名 作用
AudioPolicyConfig 保存音频策略信息,包括硬件模块,输入/输出设备,音量曲线等
IVolumeCurvesCollection 音频曲线类的基类,规定了音频曲线类需要实现的一些基本方法
VolumeCurvesCollection 音频曲线功能的实现者,继承了KeyedVector,保存audio_stream_type_t和VolumeCurvesForStream的对应关系
VolumeCurvesForStream 继承了KeyedVector,保存device_category和VolumeCurve的对应关系
VolumeCurve 用于描述解析出的音频曲线的具体数值

在AudioPolicyManager.cpp的构造函数中会执行两个方法:

AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
        : AudioPolicyManager(clientInterface, false /*forTesting*/)
{
   
    loadConfig();
    initialize();
}

其中loadConfig方法会先判断宏USE_XML_AUDIO_POLICY_CONF的值,如果这个宏被定义则说明要从音频策略配置文件读取音频策略信息(基本都会定义),之后便会去解析配置文件audio_policy_configuration.xml:

void AudioPolicyManager::loadConfig() {
   
#ifdef USE_XML_AUDIO_POLICY_CONF
    if (deserializeAudioPolicyXmlConfig(getConfig()) != NO_ERROR) {
   
#else
    if ((ConfigParsingUtils::loadConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE, getConfig()) != NO_ERROR)
           && (ConfigParsingUtils::loadConfig(AUDIO_POLICY_CONFIG_FILE, getConfig()) != NO_ERROR)) {
   
#endif
        ALOGE("could not load audio policy configuration file, setting defaults");
        getConfig().setDefault();
    }
}

调用deserializeAudioPolicyXmlConfig(getConfig())方法去解析配置文件时,使用getConfig()方法传入一个参数,这个参数的类型是AudioPolicyConfig
在AudioPolicyConfig.h中:

class AudioPolicyConfig
{
   
public:
    AudioPolicyConfig(HwModuleCollection &hwModules,
                      DeviceVector &availableOutputDevices,
                      DeviceVector &availableInputDevices,
                      sp<DeviceDescriptor> &defaultOutputDevices,
                      VolumeCurvesCollection *volumes = nullptr)
        : mHwModules(hwModules),
          mAvailableOutputDevices(availableOutputDevices),
          mAvailableInputDevices(availableInputDevices),
          mDefaultOutputDevices(defaultOutputDevices),
          mVolumeCurves(volumes),
          mIsSpeakerDrcEnabled(false)
          ......

可以看到AudioPolicyConfig类中包含了很多信息,其中mVolumeCurves就是音频曲线

接着看deserializeAudioPolicyXmlConfig方法的实现:

#ifdef USE_XML_AUDIO_POLICY_CONF
// Treblized audio policy xml config will be located in /odm/etc or /vendor/etc.
static const char *kConfigLocationList[] =
        {
   "/odm/etc", "/vendor/etc", "/system/etc"};
static const int kConfigLocationListSize =
        (sizeof(kConfigLocationList) / sizeof(kConfigLocationList[0]));

static status_t deserializeAudioPolicyXmlConfig(AudioPolicyConfig &config) {
   
    char audioPolicyXmlConfigFile[AUDIO_POLICY_XML_CONFIG_FILE_PATH_MAX_LENGTH];
    std::vector<const char*> fileNames;
    status_t ret;

    if (property_get_bool("ro.bluetooth.a2dp_offload.supported", false) &&
        property_get_bool("persist.bluetooth.a2dp_offload.disabled", false)) {
   
        // A2DP offload supported but disabled: try to use special XML file
        fileNames.push_back(AUDIO_POLICY_A2DP_OFFLOAD_DISABLED_XML_CONFIG_FILE_NAME);
    }
    fileNames.push_back(AUDIO_POLICY_XML_CONFIG_FILE_NAME);

    for (const char* fileName : fileNames) {
   
        for (int i = 0; i < kConfigLocationListSize; i++) {
   
            PolicySerializer serializer;
            snprintf(audioPolicyXmlConfigFile, sizeof(audioPolicyXmlConfigFile),
                     "%s/%s", kConfigLocationList[i], fileName);
            ret = serializer.deserialize(audioPolicyXmlConfigFile, config);
            if (ret == NO_ERROR) {
   
                return ret;
            }
        }
    }
    return ret;
}
#endif

这段代码做了一个循环,解析了”/odm/etc”, “/vendor/etc”, “/system/etc”这三个路径和AUDIO_POLICY_XML_CONFIG_FILE_NAME拼接的文件,而AUDIO_POLICY_XML_CONFIG_FILE_NAME就是audio_policy_configuration.xml

#define AUDIO_POLICY_XML_CONFIG_FILE_NAME "audio_policy_configuration.xml"

在audio_policy_configuration.xml中,通过include的方式包含了两个xml文件:

	......
    <!-- Volume section -->

    <xi:include href="audio_policy_volumes.xml"/>
    <xi:include href="default_volume_tables.xml"/>
    ......

在audio_policy_volumes.xml中,规定了音频流、输出设备和音量曲线的关系:
因为不同的音频流使用不同的音频曲线,而同一音频流在输出设备不同时也采用不同的音频曲线,所以必须规定这三者的对应关系,xml中的这种对应关系被serializer.deserialize方法解析后,在代码中体现为VolumeCurvesCollection-VolumeCurvesForStream-VolumeCurve的对应关系
audio_policy_volumes.xml:

     <volume stream="音频类型" deviceCategory="输出设备"
                                        ref="音频曲线"/>
     <volume stream="AUDIO_STREAM_RING" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA"
                                        ref="DEFAULT_DEVICE_CATEGORY_EXT_MEDIA_VOLUME_CURVE"/>
     <volume stream="AUDIO_STREAM_RING" deviceCategory="DEVICE_CATEGORY_HEARING_AID"
                                        ref="DEFAULT_HEARING_AID_VOLUME_CURVE"/>
     <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_HEADSET"
                                         ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
     <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_SPEAKER"
                                         ref="DEFAULT_DEVICE_CATEGORY_SPEAKER_VOLUME_CURVE"/>
     <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_EARPIECE"
                                         ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
     <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA"
                                         ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
	......

在default_volume_tables.xml中规定了具体音频曲线的值,如DEFAULT_MEDIA_VOLUME_CURVE曲线上点的xy值:

	......
     <reference name="DEFAULT_MEDIA_VOLUME_CURVE">
     <!-- Default Media reference Volume Curve -->
         <point>1,-5800</point>
         <point>20,-4000</point>
         <point>60,-1700</point>
         <point>100,0</point>
     </reference>
     <re
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值