Android Audio音量设置

Android 音量设置流程解析

常用API方法

setStreamVolume

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

adjustStreamVolume

-public void adjustStreamVolume(int streamType, int direction, int flags)
功能:按照direction,音量+1-1这种
参数:
streamType:音频流类型
direction:调整方向(如AudioManager.ADJUST_RAISE、AudioManager.ADJUST_LOWER等)
flags:标志位
参数值常量名描述
1ADJUST_RAISE提高音量
-1ADJUST_LOWER降低音量
0ADJUST_SAME保持当前音量
16ADJUST_MUTE静音
32ADJUST_UNMUTE取消静音
64ADJUST_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获取的如果没有配置则使用默认配置。

<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

    <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
### 实现音频音量的控制与调整 在 Android 系统中,可以通过多种方法来实现音频音量的控制与调整。这些方法不仅限于物理按钮的操作,还包括通过应用程序接口(APIs)编程的方式。 #### 使用设置模块中的滑动条控件 对于用户来说,在图形界面上最直观的方法就是利用设置应用内的音量模块。该模块提供了一个可交互式的滑动条(seekbar),允许用户直接拖拽以改变不同场景下的音量水平[^1]: ```xml <SeekBar android:id="@+id/volume_seek_bar" android:layout_width="match_parent" android:layout_height="wrap_content"/> ``` 此组件能够响应用户的触摸事件,并实时更新对应的音量等级。 #### 调整特定类型的系统音量 针对不同的应用场景,Android 定义了几种类别的音量类型,比如媒体播放、电话通话以及闹钟提醒等。每种类型都有独立的调节机制,其中也涵盖了控制系统级声音的功能[^2]。例如,当需要降低报警声时,可以执行如下操作: ```java AudioManager audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE); audioManager.adjustStreamVolume(AudioManager.STREAM_ALARM, AudioManager.ADJUST_LOWER, 0); ``` 这段代码展示了如何借助 `AudioManager` 类提供的 API 来减少指定流(这里是 STREAM_ALARM 流)的响度。 #### 编程方式修改音量级别 从底层架构上看,所有的音量更改最终都会被转发给 AudioFlinger 组件处理。因此,无论是硬件还是软件层面发起的变化请求,都需要遵循一定的消息传递路径才能生效[^3]。下面是一个简单的例子说明怎样通过发送自定义的消息来间接影响当前正在使用的音频流的音量状态: ```java if ((adjustVolume && direction != AudioManager.ADJUST_SAME)) { mAudioHandler.removeMessages(MSG_UNMUTE_STREAM); } ``` 此处展示的是一个条件判断语句片段,用于决定是否清除未静音指令队列中的待处理项,从而达到动态管理各音频通道的目的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值