Android 5.1 Android音频系统之音量控制详解

一、引言:
的音量控制是典型的和协作的例子,博文针对音量调节进行详细的解析.音量控制主要分成两大部分,一部分是java层完成的操作,用于响应音量调节,记录音量值,更新UI等操作,另一部分是层完成,用于计算音量并执行 。需要提一句的是,音量控制是设备厂商的适配重点,通常分为软音量和硬件音量,所谓软音量,就是原生针对中的数据进行设置,而硬件音量则是设置对应芯片的寄存器,两者结合为音量的最终体现,博文最后为原生音量设置的概括图,嫌代码麻烦的可先看博文最后的总结图 。
二、代码分析:
1. java层分析:
我们按下音量键或者触屏音量调节之后,会由系统响应按键,由于不同系统和每个公司的策略做的不一样,所以,在响应上逻辑上,不尽相同,但是,最终都会调入到.java中:
handleKeyDown@AudioManager.javapublic void handleKeyDown(KeyEvent event, int stream) {...switch (keyCode) {case KeyEvent.KEYCODE_VOLUME_UP:case KeyEvent.KEYCODE_VOLUME_DOWN:...adjustSuggestedStreamVolume(...);...}}
响应的函数是,首先会获取java层的服务,然后调入到.java中:
adjustStreamVolume@AudioService.javaprivate void adjustStreamVolume(int streamType, int direction, int flags,String callingPackage, int uid) {.../* 确定streamType对应的Alias组别 */int streamTypeAlias = mStreamVolumeAlias[streamType];.../* 获取对应的device */final int device = getDeviceForStream(streamTypeAlias);.../* java层消息机制:调节音量 */sendMsg(mAudioHandler,MSG_SET_DEVICE_VOLUME,SENDMSG_QUEUE,device,0,streamState,0);.../* UI更新相关 */int index = mStreamStates[streamType].getIndex(device);sendVolumeUpdate(streamType, oldIndex, index, flags); }
因为不同的可能有相同的策略,所以,这里要先去匹配Alias组别,然后去获取到,之后我们看到是使用了java中的消息机制,通知需要调节音量,代码最后跟UI更新相关,这里不去重点关注,我们主要看消息机制这里,发送了消息之后,处理是在中,调用的是方法:
private void setDeviceVolume(VolumeStreamState streamState, int device) {...synchronized (VolumeStreamState.class) {streamState.applyDeviceVolume_syncVSS(device);...}}
这里可以看到继续调用的ncVSS,需要注意在调节了当前的音量之后,还会去调节其他的类型,因此在调试中,会看到很多类型的打印,我们只关注 == 3,ncVSS会去计算index值,这个index值指UI的刻度值,比如music的话共15个进度,不同的码流类型进度总值可能不一样,方法重点是去调用了.(, index, );
三个参数,参数一为流类型,参数二为index(因为也需要记录这个值),参数三为输出的设备,这是个方法,接下来,将正式进入分析 。
2.层分析:
层的策略是首先根据index计算出真正的音量值,然后再去调用执行,先看:
status_t AudioSystem::setStreamVolumeIndex(audio_stream_type_t stream,int index,audio_devices_t device){const sp& aps = AudioSystem::get_audio_policy_service();if (aps == 0) return PERMISSION_DENIED;return aps->setStreamVolumeIndex(stream, index, device);}
之前的博文已经分析了,这里是通过去进一步调用,的Bn端在Impl.cpp中:
status_t AudioPolicyService::setStreamVolumeIndex(audio_stream_type_t stream,int index,audio_devices_t device){...return mAudioPolicyManager->setStreamVolumeIndex(stream,index,device); }
前面博文说过,是的持有者,APS不会直接与AF交互,我们看下APM中做了什么: