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

一、引言:
Android的音量控制是典型的audiopolicy和audioflinger协作的例子,博文针对音量调节进行详细的解析.音量控制主要分成两大部分,一部分是java层完成的操作,用于响应音量调节,记录音量值,更新UI等操作,另一部分是native层完成,用于计算音量并执行。需要提一句的是,音量控制是设备厂商的适配重点,通常分为软音量和硬件音量,所谓软音量,就是Android原生针对audiotrack中的数据进行设置,而硬件音量则是设置对应芯片的寄存器,两者结合为Android音量的最终体现,博文最后为Android原生音量设置的概括图,嫌代码麻烦的可先看博文最后的总结图。

二、代码分析:
1. java层分析:
我们按下音量键或者触屏音量调节之后,会由Android系统响应按键,由于不同系统和每个公司的策略做的不一样,所以,在响应上逻辑上,不尽相同,但是,最终都会调入到AudioManager.java中:

handleKeyDown@AudioManager.java
public void handleKeyDown(KeyEvent event, int stream) {
   
	...
	switch (keyCode) {
   
	            case KeyEvent.KEYCODE_VOLUME_UP:
	            case KeyEvent.KEYCODE_VOLUME_DOWN:
	            ...
	            adjustSuggestedStreamVolume(...);
	            ...
	}
}

响应的函数是adjustSuggestedStreamVolume,首先会获取java层的binder服务,然后调入到AudioService.java中:

adjustStreamVolume@AudioService.java
private 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);	
}

因为不同的streamtype可能有相同的策略,所以,这里要先去匹配Alias组别,然后去获取到device,之后我们看到是使用了java中的消息机制,通知需要调节音量,代码最后跟UI更新相关,这里不去重点关注,我们主要看消息机制这里,handler发送了消息之后,处理是在handleMessage中,调用的是setDeviceVolume方法:

private void setDeviceVolume(VolumeStreamState streamState, int device) {
   
	...
	synchronized (VolumeStreamState.class) {
   
		streamState.applyDeviceVolume_syncVSS(device);
		...
	}
}

这里可以看到继续调用的applyDeviceVolume_syncVSS,需要注意在调节了当前streamtype的音量之后,还会去调节其他的类型,因此在调试中,会看到很多类型的打印,我们只关注streamType == 3,applyDeviceVolume_syncVSS会去计算index值,这个index值指UI的刻度值,比如music的话共15个进度,不同的码流类型进度总值可能不一样,方法重点是去调用了AudioSystem.setStreamVolumeIndex(mStreamType, index, device);
三个参数,参数一为流类型,参数二为index(因为native也需要记录这个值),参数三为输出的设备,这是个native方法,接下来,将正式进入native分析。

2.native层分析:
native层的策略是首先根据index计算出真正的音量值,然后再去调用audioflinger执行,先看AudioSystem:

status_t AudioSystem::setStreamVolumeIndex(audio_stream_type_t stream,
                                           int index,
                                           audio_devices_t device)
{
   
    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
    i
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值