当前位置:   article > 正文

Android Audio:setStreamVolume()音量调节过程

setstreamvolume

音量调节过程中的重要的几个Java文件:

AudioManager:

frameworks\base\media\java\android\media\AudioManager.java

  • Android为我们提供的(音量大小控制)的API: AudioManager(音频管理器),提供了音量控制与铃声模式相关操作。

AudioService:

frameworks\base\services\core\java\com\android\server\audio\AudioService.java

  • 音频系统在java层中基本上不参与数据流(描述了音频数据从数据源流向目的地的流程,AudioTrack,AudioFlinger就是数据流)的,AudioService这个系统服务包含或者使用了几乎所有与音频有关的内容,所以说AudioService是音频系统在java层的大本营;

  • AudioManager拥有AudioService的Bp端,是AudioService在客户端的一个代理,几乎所有客户端对AudioManager进行的请求,最终都会交由AudioService实现;

  • AudioService的功能实现依赖于AudioSystem类,AudioSystem无法实例化,它是java层到native层的代理,AudioService通过它与AudioPolicyService以及AudioFlinger进行通信;

AudioSystem:

在这里插入图片描述
应用层AudioManager和AudioService之间通过Binder通信来完成调用关系,到了library层的AudioSystem就可以直接获取AudioFlinger,AudioPolicyService服务。

android p的音量调节跟之前的版本源码改动很多,记录从AudioManager开始的音量调节过程。

ps:结束部分可能有点问题,暂时没有分析出更深入的流程,以后接触的更深入在修改。

Android Audio:setStreamVolume()音量调节过程

在这里插入图片描述

android\frameworks\base\media\java\android\media\AudioManager.java

设置相应流的音量,不同的流index的范围不一样。
在这里插入图片描述
通过IBinder和ServiceManager获得服务。
在这里插入图片描述
android\frameworks\base\services\core\java\com\android\server\audio\AudioService.java

setStreamVolume(int streamType, int index, int flags, String callingPackage),判断音量类型是否是以下类型,然后打印日志。
在这里插入图片描述
接下来调用6参的setStreamVolume()。通过ensureValidStreamType()函数来确保声音类型的合法性,不合法抛异常。跳过a2dp绝对音量控制请求,如果系统调用我们(例如硬件密钥),请检查当前用户。
在这里插入图片描述
通过同步函数来获取之前的index并通过rescaleIndex()重新赋值index。
在这里插入图片描述
checkSafeMediaVolume(streamTypeAlias,index,device)
经过一系列的设备、flags、index的判断设置后,如果通过checkSafeMediaVolume(streamTypeAlias,index,device)来检查当前是否可设置音量,检查媒体音量是否处于SAFE_MEDIA_VOLUME_ACTIVE并且音量大于安全范围的音量,返回false,否则为true。

如果前面验证都没有问题,直接sendVolumeUpdate()发送更新音量的信息。
在这里插入图片描述
postDisplaySafeVolumeWarning(int flags)

如果不可以,调用postDisplaySafeVolumeWarning(int flags),显示音量警告并生成PendingCommand,等待合适的时机。
在这里插入图片描述
否则,继续往下设置音量。

onSetStreamVolume(int streamType, int index, int flags, int device,String caller)
通过setStreamVolumeInt()设置音量,设置音量的声音流类型也控制静音模式,并判断音量是否为0,调节模式静音或者响铃。
在这里插入图片描述
setStreamVolumeInt(int streamType,int index,int device,boolean force,String caller)
设置音量,并发布一条消息来设置系统音量,streamType流类型,index期望音量值,device必须改变其音量的设备,force如果为真,即使需要改变的音量相同,也要设置音量。

通过sendMsg()发布消息来设置,它将依次发布消息来保存。
在这里插入图片描述
handleMessage(Message msg)

当消息类型为MSG_SET_DEVICE_VOLUME时,调用setDeviceVolume()设置系统音量。
在这里插入图片描述
setDeviceVolume(VolumeStreamState streamState, int device)

通过applyDeviceVolume_syncVSS()设置应用音量,接着将更改应用于所有使用此别名的流,确保音量在A2DP设备上也达到最大。
在这里插入图片描述
applyDeviceVolume_syncVSS(int device)

通过传入设备号来设置应用音量,如果是静音,index为0,否则根据设备类型来设置index。最后调用设置setStreamVolumeIndex()来设置音量。
在这里插入图片描述

android\frameworks\base\media\java\android\media\AudioSystem.java

setStreamVolumeIndex(),调用AudioSystem.java中的setStreamVolumeIndex(),是个native函数,从这里到跳到c++代码。
在这里插入图片描述
android\frameworks\base\core\jni\android_media_AudioSystem.cpp

JNINativeMethod gMethods[],拿到JNI的接口
在这里插入图片描述
android_media_AudioSystem_setStreamVolumeIndex()

JNI通过setStreamVolumeIndex()转发给c++层的AudioSystem。
在这里插入图片描述
android\frameworks\av\media\libaudioclient\AudioSystem.cpp

setStreamVolumeIndex(audio_stream_type_t stream,int index,audio_devices_t device)
在这里插入图片描述
get_audio_policy_service(),通过Binder机制,获取service对象。
在这里插入图片描述
android\frameworks\av\services\audiopolicy\service\AudioPolicyInterfaceImpl.cpp

这里主要是因为Binder机制走到这个文件,然后走setStreamVolumeIndex(audio_stream_type_t stream,int index,audio_devices_t device)

做了些权限和参数检查,转发给AudioPolicyManager。
在这里插入图片描述
android\frameworks\av\services\audiopolicy\managerdefault\AudioPolicyManager.cpp

判断音量及设备是否为输出设备。
在这里插入图片描述
通过checkAndSetVolume设置每个输出设备的音量
在这里插入图片描述
volumeDb计算音量。
在这里插入图片描述
设置输出设备的声音和通话音量
在这里插入图片描述
frameworks\av\services\audiopolicy\common\managerdefinitions\src\AudioOutputDescriptor.cpp

bool AudioOutputDescriptor::setVolume()
设置输出设备音量AudioOutputDescriptor是音频设备描述符,outputDesc是SwAudioOutputDescriptor类型。
在这里插入图片描述
changed由AudioOutputDescriptor获得。
在这里插入图片描述

  • 走到这里是因为SwAudioOutputDescriptor中的changed的if条件语句,这里的派生关系是这样来的:
    在这里插入图片描述
    frameworks\av\services\audiopolicy\service\AudioPolicyService.h
    在构造函中被调用,因此走AudioPolicyService中的函数。
    在这里插入图片描述

android\frameworks\av\services\audiopolicy\service\AudioPolicyService.cpp
在这里插入图片描述
封装一下data跟command
在这里插入图片描述
接着下一个函数
在这里插入图片描述
因为在volumeCommend中,得到了command->mCommand = SET_VOLUME;所以会走到这里,会转到AudioSystem的setStreamVolume。
在这里插入图片描述
android\frameworks\av\media\libaudioclient\AudioSystem.cpp

在此处取得af的服务,转到AudioFlinger.cpp
在这里插入图片描述
android\frameworks\av\services\audioflinger\AudioFlinger.cpp

status_t AudioFlinger::setStreamVolume(audio_stream_type_t,stream,float value,audio_io_handle_t output)
进行权限参数检查。
在这里插入图片描述
frameworks\av\services\audioflinger\Threads.h
在这里插入图片描述
派生关系:
在这里插入图片描述
android\frameworks\av\services\audioflinger\Threads.cpp

void AudioFlinger::PlaybackThread::setStreamVolume(audio_stream_type_t stream, float value)

设置mStreamTypes类型并唤醒PlaybackThreads.
在这里插入图片描述
PlaybackThread 中有个极为重要的函数 threadLoop(),当 PlaybackThread 被强引用时,threadLoop() 会真正运行起来进入循环主体,处理音频流数据相关事务。
在这里插入图片描述
threadLoop() 循环的条件是 exitPending() 返回 false。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/988831
推荐阅读
相关标签