Android AudioFrameWork中device的选择

手机上的音频模块是一个很复杂的系统,为了区分和管理,
android中引入了streamType, routing_strategy和device的概念
应用在播放音乐时,只需要将streamType设置下来,底层根据streamType选择routing_strategy, 再根据routing_strategy选择device,从而决定声音从那里发生,是扬声器,是听筒,还是耳机。

1 streamType简介

针对不同的音频流,有不同的类型
如:
通话中的voice音, 类型为 AUDIO_STREAM_VOICE_CALL
来电的响铃音, 类型为 AUDIO_STREAM_RING
播放视频的媒体音, 类型为 AUDIO_STREAM_MUSIC
闹钟的提示音,类型为 AUDIO_STREAM_ALARM
系统的通知音, 类型为 AUDIO_STREAM_NOTIFICATION 

streamType的枚举值可参考 system/media/audio/include/system/audio-base.h 文件

2 routing_strategy 简介

	通路策略与 streamType一一对应,不同的streamType的音,会采取不同的通路,
	比如,
	通话时,选择的streamType为 AUDIO_STREAM_VOICE_CALL,
		那么根据voice_call,获取的 strategy是 STRATEGY_PHONE。

	闹钟响铃时,选择的streamType为 AUDIO_STREAM_ALARM
		那么根据alarm,获取的 strategy 是 STRATEGY_SONIFICATION

	具体策略可以参考 audiopolicy中的 engine.cpp中的 Engine::getStrategyForStream 函数
	routing_strategy的枚举值可参考frameworks/av/services/audiopolicy/common/include/RoutingStrategy.h文件

3 device简介

audio中针对音频的播放通路,有device这个概念。
比如说打电话时声音从听筒出来,听筒就是一个device:AUDIO_DEVICE_OUT_EARPIECE

如果打开免提的话,会从扬声器出声,扬声器也是一个device:AUDIO_DEVICE_OUT_SPEAKER
如果连接上蓝牙耳机或者有线耳机或者usb耳机,
声音便从耳机出,这又是三个不同的设备:
AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET
AUDIO_DEVICE_OUT_WIRED_HEADSET
AUDIO_DEVICE_OUT_USB_HEADSET

当然,也有采集声音的麦克
打电话时,我们的声音会被手机底部的mic采集,底部mic是一个输入 device:		AUDIO_DEVICE_IN_BUILTIN_MIC
如果打开免提,我们的声音会被背部的mic采集,背部mic也是一个输入device:		AUDIO_DEVICE_IN_BACK_MIC

device的枚举值可参考	system/media/audio/include/system/audio-base.h 文件

4 device的选择策略

首先,一块手机上有固定的device,比如mic, 听筒和扬声器
其次,插上手机后,会有新增的device,比如耳机,音响等。
故,device的来源有两个,一个是固有的,一个的可增删的。

4.1 固有device来源于xml:

audioserver启动时,创建 AudioPolicyManager时,会分别从手机的如下目录
"/odm/etc", "/vendor/etc/audio", "/vendor/etc", "/system/etc"
查找 audio_policy_configuration.xml 文件并解析。
xml中首先有 <attachedDevices> item,列出了所有可能的固有device
其次有 <devicePorts> item,列出了所有的device的特性,
二者求交集,便产生了手机的固有device

4.2 可增删设备来源于手机插拔上报事件

比如,插入一个usb耳机后,usb驱动会上报插拔事件,usbAlasManager解析设备,
如果是音频设备,会间接调用 setDeviceConnectionState,
将新增的device传给底层,底层将新增的设备add到 mAvailableOutputDevices vector中,
选择输出设备时,便从这些可利用的device中,根据一定的策略来获取device,
策略见engine.cpp中的 Engine::getDeviceForStrategy函数。


至此,我们根据应用传递的streamType,选择了deivce.

Android AudioFrameWork中device的选择