Android音频框架相关概念理解
1. 音频驱动设备
底层相关背景知识,主要是pcm设备和mix设备:
其中pcm设备是音频数据的采集/输出设备,mix设备是音频通道,音量增益控制相关的设备,所有的音频相关的逻辑最终都是在和这两个设备打交道。因此从系统设计角度来说,不可能让每个应用都自己去操作这些音频设备。自然地,Android框架层会去承担这个管理者的角色,然后每个应用都去和框架打交道即可。另一方面,应用开发者并不需要理解这些底层设备,那么Android就抽象了一些更容易懂的概念,比如有了stream, strategy等。下文主要是讲Android Audio模块里的一些知识点。
音频设备-Device
音频设备泛指音频的输入/输出设备。在GS产品中,音频设备一般包括手柄,扬声器,3.5mm耳机,usb耳机,蓝牙耳机,RJ9/EHS耳机等。设备有两个重要作用:a.音频通道的切换;b.音频音量的调整;音频设备是由框架管理和维护的,典型的管理者就是AudioPolicyService。从应用开发角度来看,音频设备几乎是透明的,不用太关心音频设备这个东西。比如用户插上耳机,系统声音自然就切换到耳机;此时用户再调节音量,那么调节的也是耳机的音量。在整个过程中,应用程序完全不用关心耳机的状态。但是App还是可以人为地干预音频通道的切换,用户总有自己的特殊需求,Android也预留了相关的接口,相关接口都在AudioManager中:
音频流-Stream
Stream是Android Audio中最知名的概念了,基本上大多数的开发都接触和使用过Stream.具体的流类型有:
如何理解流?流的作用:
.STREAM和使用场景相关,如音乐播放,各种通知音,通话等各种场景。
STREAM和音量相关,每个流都有自己的音量。
关于音量:对于AudioFlinger来说,音量永远只有一个,在混音的时候才用到。但是在Android框架中,音量有很多值,每个stream的音量都不同。这样对比也看出了stream的意义,虽然底层AudioFlinger只能设置一个音量值,但是框架层在逻辑上抽象出很多的场景stream,并维护各stream的音量。这样就提供了更好,更丰富的用户体验。如下图所示:
从接口角度来理解上面的两种作用:
.应用在使用播放类的接口时候,都可以指定流类型,主要来表明当前的播放算什么场景,如使用MediaPlayer播放时:
一般地,比如在播放音乐时,使用MUSIC流;在播放提示音的时候,使用NOTIFICATION流等。
使用Ringtone播放时:
.应用在调节/设置音量的时候,都可以指定流类型,主要来表明当前调节的是哪个流的音量,此类接口依然封装在AudioManager中:
音频策略-Strategy
Strategy是Android内部的一个音频概念,相信很多同学都听说过,但是几乎都接触不到。首先音频策略是完全由framework管理的,应用层根本不用关心;其次音频策略是只有C层的定义,普通APP也访问不到,也没必要访问。
具体的Stategy类型有:
看它的定义名称,和使用场景很有联系,如媒体播放,通话中,通知音等。看起来和STREAM很接近,那么它们的区别是什么?
.策略的主要作用是设备路由,即音频通路选择,和音频设备打交道;而流的主要作用是和音量相关的。
.一个策略往往对应至少一个流,或者说多个流可以共用一个策略。这两者的具体关系参考下图:
多个流共用一个策略的意思?
首先策略的作用是选出音频设备,比如当前话机有手柄,扬声器,甚至连接了耳机。那么该选什么设备来输出声音,是完全由策略决定的。也就是说通过策略,话机的音频通路就选好了。多个流共用一个策略,就表明它们选择音频设备的策略是一致的。
话机模式-mode
最近有好几个同学都在问mode的作用,其实这个mode一般App很少用到。其主要表示话机的一些状态,特别是通话状态的,如下图的定义所示:
一般话机处于idle时候对应normal,来电振铃的时候对应ringtone,通话中对应in_call。而in_communication则一般对应的是第三方应用的通话状态,如skype建立通话的时候。这种状态的变化,主要的作用是更新音频通道,更新音频流。通话中,音频流肯定要变更到STREAM_VOICE_CALL,音频通道也要更新。以手机为例,默认情况下,声音都是从扬声器出来的。但是,在通话中的时候,音频通道由扬声器切换到了听筒。这一切换时机就需要App告知框架层,主要就是通过setMode来实现的。大家可以再想想,在手机idle状态,调节音量,调的是notification流的音量;在通话的时候,再调节音量就变成了voice_call