赞
踩
frameworks\base\media\java\android\media\AudioManager.java
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进行通信;
应用层AudioManager和AudioService之间通过Binder通信来完成调用关系,到了library层的AudioSystem就可以直接获取AudioFlinger,AudioPolicyService服务。
android p的音量调节跟之前的版本源码改动很多,记录从AudioManager开始的音量调节过程。
ps:结束部分可能有点问题,暂时没有分析出更深入的流程,以后接触的更深入在修改。
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获得。
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。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。