Android Audio音量设置

Android 音量设置流程解析

常用API方法

setStreamVolume

java 复制代码
public void setStreamVolume(int streamType, int index, int flags)
功能:直接设置指定音频流的音量
参数:
streamType:音频流类型(如AudioManager.STREAM_MUSIC)
index:音量级别(0到最大音量之间)
flags:标志位(如AudioManager.FLAG_SHOW_UI)
示例:

adjustStreamVolume

java 复制代码
-public void adjustStreamVolume(int streamType, int direction, int flags)
功能:按照direction,音量+1-1这种
参数:
streamType:音频流类型
direction:调整方向(如AudioManager.ADJUST_RAISE、AudioManager.ADJUST_LOWER等)
flags:标志位
参数值 常量名 描述
1 ADJUST_RAISE 提高音量
-1 ADJUST_LOWER 降低音量
0 ADJUST_SAME 保持当前音量
16 ADJUST_MUTE 静音
32 ADJUST_UNMUTE 取消静音
64 ADJUST_TOGGLE_MUTE 切换静音状态

adjustStreamVolume解析

AudioManager.java中adjustStreamVolume做了哪些操作

  • direction、streamtype的类型检查然后判断当前direction和stream_tpye是否是静音 如果是return
  • 如果direction是静音,stream_type是STREAM_VOICE_CALL or STREAM_BLUETOOTH_SCO 检查app是否有MODIFY_PHONE_STATE权限、如果 stream is STREAM_ASSISTANT,那么检查app是否有MODIFY_AUDIO_ROUTING权限
  • 通过stream_type获取当前合适的device,并且获取VolumeStreamState对象,这个对象是根据stream_type创建的,并且对象里面包含了各种device的默认音量大小
    静音调整处理:
  • 如果是静音调整(ADJUST_MUTE或ADJUST_TOGGLE_MUTE),会设置系统音频静音状态
  • 遍历所有音频流,对匹配的音频流进行静音/取消静音操作
  • 特殊处理了STREAM_SYSTEM_ENFORCED流(如相机快门声)
    音量增大处理:
  • 检查安全音量限制,如果超出安全音量会显示警告
  • 对于非全音量设备,调整音量索引
  • 如果当前是静音状态,会根据方向立即取消静音或延迟取消静音
  • 如果是蓝牙设备就要把消息发给蓝牙的service postSetAvrcpAbsoluteVolumeIndex
  • 如果是HDMI设备就调用 HdmiTvClient.java setSystemAudioVolume

是 否 App调用adjustStreamVolume AudioManager.java adjustStreamVolume AudioService.java adjustStreamVolume 静音调整? mute setAllVolumes applyAllVolumes setStreamVolumeIndex adjustIndex setDeviceVolume applyDeviceVolume_syncVSS

目前java层的代码已经分析完了,接下来要看native层的代码了

直接来看AudioPolicyManager.cppsetStreamVolumeIndex主要功能如下:

  • 根据stream_type获取attibutes

ProductStrategyMap ProductStrategy 1 ProductStrategy ... AudioAttributesVector AudioAttributesVector AudioAttributes 1 AudioAttributes ... AudioAttributes 1 AudioAttributes ...

ProductStrategyMap中的数据是通过解析audio_policy_engine_configuration.xml获取的如果没有配置则使用默认配置。

xml 复制代码
<ProductStrategy name="STRATEGY_PHONE">
    <AttributesGroup streamType="AUDIO_STREAM_VOICE_CALL" volumeGroup="voice_call">
        <Attributes> <Usage value="AUDIO_USAGE_VOICE_COMMUNICATION"/> </Attributes>
    </AttributesGroup>
    <AttributesGroup streamType="AUDIO_STREAM_BLUETOOTH_SCO" volumeGroup="bluetooth_sco">
        <Attributes> <Flags value="AUDIO_FLAG_SCO"/> </Attributes>
    </AttributesGroup>
</ProductStrategy>

比如上述xml配置中,可以看出这个ProductStrategy包含了两种stream_type分别是AUDIO_STREAM_VOICE_CALL和AUDIO_STREAM_BLUETOOTH_SCO。然后这个ProductStrategy包含了两个AudioAttributes。

audio_policy_engine_stream_volumes.xml

xml 复制代码
    <volumeGroup>
        <name>voice_call</name>
        <indexMin>1</indexMin>
        <indexMax>7</indexMax>
        <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
            <point>0,-4200</point>
            <point>33,-2800</point>
            <point>66,-1400</point>
            <point>100,0</point>
        </volume>
        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
            <point>0,-2400</point>
            <point>33,-1600</point>
            <point>66,-800</point>
            <point>100,0</point>
        </volume>
        <volume deviceCategory="DEVICE_CATEGORY_EARPIECE">
            <point>0,-2700</point>
            <point>33,-1800</point>
            <point>66,-900</point>
            <point>100,0</point>
        </volume>
        <volume deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
        <volume deviceCategory="DEVICE_CATEGORY_HEARING_AID" ref="DEFAULT_HEARING_AID_VOLUME_CURVE"/>
    </volumeGroup>

上述xml作用是解释音量相关的信息,比如在不同设备的voice_call类型的音量曲线 最大、最小index等。 可以看出来AudioAttributes中的AttributesGroup和volumeGroup是一一对应,根据name可以看出。并且从下图可以看出AudioAttributesVector和VolumeGroup一一对应。通过mId链接。

-调用setVolumeIndexForAttributes

调用setVolumeIndexForAttributes,这个函数主要功能如下:

  • 根据Attributes获取对应的VolumeGroup、音量曲线、VolumeSource、strategy
  • setVolumeCurveIndex (根据index device 设置curves)
  • 获取与音量曲线相关的输出设备。
  • 遍历所有输出描述符(SwAudioOutputDescriptor),检查并应用音量调整。checkAndSetVolume
  • 通知客户端音量组已发生变化。onAudioVolumeGroupChanged

checkAndSetVolume功能如下:

  • 检查音量源是否被静音。静音直接返回NO_ERROR(这里检查的是volumeSources是否是静音状态,这个状态在adjustStreamVolume流程并不会被设置)
  • 检查通话和蓝牙 SCO 音量冲突。
  • 获取设备类型。
  • 计算音量分贝值。(eswin在这一步把计算出来的volumeDb = 0.0f)
  • 设置音量。(SwAudioOutputDescriptor::setVolume)
  • 处理主输出设备的通话音量。(如果是主输出设备,并且在通过状态或者音量源是蓝牙,最终会调用到audio_hw.c中的setVoiceVolume,目的是提高实时性、硬件依赖性强)

接下来看一下setVolume的功能:

  • 调用基类的 setVolume 方法进行基础设置。改变mVolumeActivities[vs].setVolume(volumeDb)
  • 处理空音频流类型,默认使用 AUDIO_STREAM_MUSIC。
  • 遍历设备,检查设备类型和增益控制,设置设备增益,并且把软件层的增益设置为0。(前提是当前设备硬件支持音量增益,最后调用到hal的setAudioPortConfig,配置硬件是否支持增益需要更改audio_policy_configuration.xml添加useForVolume="true"即可)
  • 将分贝值换算成振幅
  • 处理蓝牙 SCO 设备的通话音量。setStreamVolume
  • 设置音频流音量。调用到SF中的setStreamVolume,然后调用Thread.cpp中在指定的playbacktrhead中设置 mStreamTypes[stream].volume = value;

音量设置流程总结

是 否 Java层调用adjustStreamVolume AudioManager.java adjustStreamVolume AudioService.java adjustStreamVolume 静音调整? mute setAllVolumes applyAllVolumes setStreamVolumeIndex adjustIndex setDeviceVolume applyDeviceVolume_syncVSS AudioPolicyManager.cpp setStreamVolumeIndex AudioPolicyManager.cpp setVolumeIndexForAttributes checkAndSetVolume SwAudioOutputDescriptor.cpp setVolume Thread.cpp setVolume

setStreamVolume解析

在AudioService.java中 setStreamVolume 功能如下:

  • 如果device是蓝牙并且是绝对音量那么就调用蓝牙音量设置postSetAvrcpAbsoluteVolumeIndex
  • 如果是助听器调用ostSetHearingAidVolumeIndex
  • 如果是HDMI设备调用setSystemAudioVolume
  • 如果当前音频流类型为 STREAM_MUSIC,并且设备是固定音量设备,设置 FLAG_FIXED_VOLUME 标志位。如果音量值不为 0,则根据设备的安全音量状态,将音量值设置为安全音量值或最大音量值。
  • 调用onSetStreamVolume
    onSetStreamVolume功能如下:
    -调用setStreamVolumeInt

AudioService.java setStreamVolume onSetStreamVolume setStreamVolumeInt 发送消息 MSG_SET_DEVICE_VOLUME Handler.handleMessage setDeviceVolume applyDeviceVolume_syncVSS

相关推荐
鸿蒙布道师8 小时前
鸿蒙NEXT开发Base64工具类(ArkTs)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
jiet_h9 小时前
Android adb 的功能和用法
android·adb
美狐美颜sdk10 小时前
美颜SDK兼容性挑战:如何让美颜滤镜API适配iOS与安卓?
android·深度学习·ios·美颜sdk·第三方美颜sdk·视频美颜sdk
居然是阿宋10 小时前
深入理解 YUV 颜色空间:从原理到 Android 视频渲染
android·音视频
KevinWang_11 小时前
DialogFragment 不适合复用
android
古鸽1008611 小时前
Audio Hal 介绍
android
小叶不焦虑12 小时前
关于 Android 系统回收站的实现
android
木西12 小时前
从0到1搭建一个RN应用从开发测试到上架全流程
android·前端·react native
小橙子207713 小时前
一条命令配置移动端(Android / iOS)自动化环境
android·ios·自动化
和煦的春风13 小时前
案例分析 | SurfaceFlinger Binder RT 被降级到CFS
android