众(搞音频的(此处应该有个笑哭的表情)所周知的,要播放一个声音,创建AudioTrack之后,set函数设置参数的时候,会调用createTrack_l函数。
第一步:获取output
createTrack_l用binder去调用AudioFlinger的createTrack创建AudioFlinger::Track之前,首先会去调用getOutputForAttr:
status = AudioSystem::getOutputForAttr(attr, &output,
mSessionId, &streamType, mClientUid,
&config,
mFlags, &mRoutedDeviceId, &mPortId);
根据传入的audio_attributes_t等参数,带回output(这是个出参)!
这一调用,在AudioPolicyManager中得到落实。
AudioPolicyManager::getOutputForAttr:
//准备设置好attributes
...
//根据attributes选中Strategy
routing_strategy strategy = (routing_strategy) getStrategyForAttr(&attributes);
...
//根据Strategy选中device
audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/);
...
//根据选定的device获取Output
*output = getOutputForDevice(device, session, *stream,
config->sample_rate,
config->format,
config->channel_mask,
flags,
&config->offload_info);
这个名字取得很有意思哈,一步步往下推进的感觉。
getOutputForAttr: attr>>strategy>>device>>output
其中,getDeviceForStrategy这一步真正决定了使用什么设备.
比如说,下面的例子是播放音乐(AUDIO_STREAM_MUSIC)的时候选中的Strategy:
//代码节选自Engine::getDeviceForStrategyInt
case STRATEGY_MEDIA: {
uint32_t device2 = AUDIO_DEVICE_NONE;
...
//device2在前面没有被选中,而且没有设置这个setForceUse(setBluetoothA2dpOn(false)的时 候,会设置
//AudioSystem.FOR_MEDIA,AudioSystem.FORCE_NO_BT_A2DP标记)
if ((device2 == AUDIO_DEVICE_NONE) &&
(mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
(outputs.getA2dpOutput() != 0)) {
//第一个优先项出现了.如果此时a2dp可用,直接到下面我用****标记的特殊情况
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
}
}
//这次轮到了AudioSystem.FOR_MEDIA,AudioSystem.FORCE_SPEAKER这种情况,speaker胜出
if ((device2 == AUDIO_DEVICE_NONE) &&
(mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] == AUDIO_POLICY_FORCE_SPEAKER)) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
}
//接下来就是依据优先级去选择设备了.规则就是
//选中一个就结束,直接去和特殊设备做共存
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_LINE;
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADSET;
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_HEADSET;
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_LINE;
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADSET;
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_HEADSET;
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_ACCESSORY;
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE;
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
}
if ((device2 == AUDIO_DEVICE_NONE) && (strategy != STRATEGY_SONIFICATION)) {
// no sonification on aux digital (e.g. HDMI)
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL;
}
if ((device2 == AUDIO_DEVICE_NONE) &&
(mForceUse[AUDIO_POLICY_FORCE_FOR_DOCK] == AUDIO_POLICY_FORCE_ANALOG_DOCK)) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
}
***********************************************************************************
//特殊情况
int device3 = AUDIO_DEVICE_NONE;
if (strategy == STRATEGY_MEDIA) {
//如果arc,spdif,aux_line可用,赋值给device3
// ARC, SPDIF and AUX_LINE can co-exist with others.
device3 = availableOutputDevicesType & AUDIO_DEVICE_OUT_HDMI_ARC;
device3 |= (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPDIF);
device3 |= (availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_LINE);
}
//device2和arc,spdif,aux_line做一个共存
device2 |= device3;
// 一般情况下,在这之前device还是AUDIO_DEVICE_NONE
device |= device2;
// If hdmi system audio mode is on, remove speaker out of output list.
if ((strategy == STRATEGY_MEDIA) &&
(mForceUse[AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO] ==
AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED)) {
device &= ~AUDIO_DEVICE_OUT_SPEAKER;
}
} break;
根据上面的代码,简单做个总结吧:
播放音乐选设备优先级如下
AUDIO_DEVICE_OUT_BLUETOOTH_A2DP
AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES(普通蓝牙耳机)
AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER(蓝牙小音箱)
//此处属于setForceUse的强制插队
(if FORCE_SPEAKER)AUDIO_DEVICE_OUT_SPEAKER(扬声器)
AUDIO_DEVICE_OUT_WIRED_HEADPHONE(普通耳机,只能听,不能操控播放)
AUDIO_DEVICE_OUT_LINE
AUDIO_DEVICE_OUT_WIRED_HEADSET(线控耳机)
AUDIO_DEVICE_OUT_USB_HEADSET(USB耳机)
...
AUDIO_DEVICE_OUT_SPEAKER(扬声器)
选好设备就返回device,然后getOutputForDevice
AudioPolicyManager::getOutputForDevice
//处理入参flags
if ((flags & AUDIO_OUTPUT_FLAG_XXX) != 0) {
flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_XXX);
}
//咱一般不是AUDIO_OUTPUT_FLAG_DIRECT,当然是
goto non_direct_output;
...
//播放音乐什么之类的,mediaplayer已经做完decodec.这里一般都是pcm
if (audio_is_linear_pcm(format)) {
//根据指定的stream类型获取匹配的output.实际的路由改变需要等到startOutput被调用的时候
//注意这个函数是getOutputsForDevice,要获取的是一些output,而我们当前讨论的函数是获取一个output.这些outputs从mOutputs中来.那么mOutputs来自哪里?
SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(device, mOutputs);
// 从匹配到的outputs(请注意,是复数)中选出一个output
output =