应用程序创建的AudioTrack怎么去选择output呢?下面是上小节的图: 首先应用程序传入声音类型,然后根据声音类型会设置一个属性,然后根据声音的属性确定他的组/类别,找到device,最后在根据device找到对应的output(一个device可能对应多个output,但是只选择一个)。一下其调用过程:
a. APP构造AudioTrack时指定了 stream type
b. AudioTrack::set
c. AudioPolicyManager::getStrategyForAttr
d AudioPolicyManager::getDeviceForStrategy
e. AudioPolicyManager::getOutputForDevice
e.1 AudioPolicyManager::getOutputsForDevice
audio_stream_type_t audio_attributes_to_stream_type
e.2 output = selectOutput(outputs, flags, format);
期图上的audio_stream_type_t由AudioTrack::set指定,audio_attributes_to_stream_type函数根据audio_stream_type_t设置audio_stream_type_t ,最终转行成Strategy。可以看到11种audio_stream_type_t最终归为6种Strategy,其就是进行了分类/组。最后要根据Strategy得到播放的设备,这是一个比较复杂的过程,即getDeviceForStrategy函数。我们用一个例子对这个函数进行演示。
在日常生活中,使用android手机打电话: 1.如果接上了蓝牙车载导航,优先使用车载导航播放声音。 2…否则,如果插上了耳机,优先使用耳机播放声音。 3.否则,使用手机扬声器播放声音。 4.可以手工选择扬声器等设备(即使接上蓝牙设备,一可以手工选择其他的播放)
假设播放声音的APP指定audio_stream_type_t为AUDIO_STREAM_VOICE_CALL,那么他的Strategy会被设置为STRATEGY_PHONE,我们看看STRATEGY_PHONE对应的device是什么,
audio_devices_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strategy,bool fromCache)
/*AudioPolicyManagerInterface *mEngine;*/
mEngine->getDeviceForStrategy(strategy);
其实质就是根据优先级,获得对应的device,在获得device之后,我们就需要根据device去获得Output了,即调用getOutputForDevice函数。前面的小节中,我们分析过,在AudioPolicyManager对象中,存在一个moutputs,其对应的是以及打开的output:
sp mPrimaryOutput; // primary output descriptor
// list of descriptors for outputs currently opened
SwAudioOutputCollection mOutputs;
可以看到每个output都存在一个mOutputs,以及相应的一个mPrimaryOutput,其中的SwAudioOutputDescriptor mPrimaryOutput包含有:
const sp mProfile; // I/O profile this output derives from
成员,来自于配置文件,如配置文件中,如开发板下/system/etc/audio_policy.conf文件中存在:
/*描述多个modules*/
audio_hw_modules {
primary { //一个modules对应一个厂家提供的so文件
outputs { //一个modules可以有多个output
primary {//一个output表明他的参数(primary代表默认设备)
sampling_rates 44100|48000 //采样率
channel_masks AUDIO_CHANNEL_OUT_STEREO //通道
formats AUDIO_FORMAT_PCM_16_BIT //格式
/*有哪些device,如喇叭,耳机等等*/
devices AUDIO_DEVICE_OUT_EARPIECE|AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|AUDIO_DEVICE_OUT_ALL_SCO|AUDIO_DEVICE_OUT_AUX_DIGITAL|AUDIO_DEVICE_OUT_SPDIF
flags AUDIO_OUTPUT_FLAG_PRIMARY
}
我们可以看到其存在:
devices AUDIO_DEVICE_OUT_EARPIECE|AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|AUDIO_DEVICE_OUT_ALL_SCO|AUDIO_DEVICE_OUT_AUX_DIGITAL|AUDIO_DEVICE_OUT_SPDIF
即mProfile中表明了该ouput支持哪些Device,现在我们来看看函数getOutputForDevice:
audio_io_handle_t AudioPolicyManager::getOutputForDevice(
non_direct_output:
/*遍历一下已经打开的mOutputs,其中是否有支持device*/
SortedVector outputs = getOutputsForDevice(device, mOutputs);
/*取出outputs中的每一项*/
for (size_t i = 0; i supportedDevices()) == device) {
/*r如果支持,则添加到outputs。最终返回一个或者多个output*/
outputs.add(openOutputs.keyAt(i));
/*从设备所支持的outputs,中选择一个output:*/
setOutputDevice(outputDesc, newDevice, false);
其中setOutputDevice函数中的翻译如下,有可能有多个output,怎么从多个output中选择出最合适的? //1. a.APP创建AudioTrack时会传入flag b.output对应的profile(/system/etc/audio_policy.conf)中也有flag(该文件中每个output节点都存在flag) c.使用上述a,b的flag进行比较,取出吻合度最高的output。
//2. 如果有多个吻合度相同的情况下,同时primar output支持该设备,则选择他
//3. 如果primar output不支持,则选择所有支持的output中的第一个。
现在我们知道了怎么找到output,找到了output则代表找到了播放线程,该线程会创建一个track,其和应用程序的Audio track对应。那么怎么在这个线程中创建对应的track?下小节进行讲解。