Audiopolicyservice的路由实现:
Audiopolicyservice作为音频策略的制定者,功能的实现跟audiotrack(使用者)有较大关联,所以在紧接着audiotrack看下路由的过程。
路由,就要有发送方,接收方,这个场景中发送发就是Audiotrack,接收方就是audioflinger(策略的执行者),audiopolicyservice是这两者的桥梁,它内部拥有当前系统中所有音频设备的信息,实现音频策略的算法也不是固定的,是可以由厂商定制的。
依据前面的分析,在audiotrack中的set方法,调用audiosystem:: getOutputForAttr()来分析策略的实现:
status_t AudioTrack::createTrack_l()@AudioTrack.cpp{
status = AudioSystem::getOutputForAttr(attr, &output,…);
}
status_t AudioSystem::getOutputForAttr(…)@ AudioSystem.cpp {
const sp& aps = AudioSystem::get_audio_policy_service();
return aps->getOutputForAttr(…);
}
AudioSystem是一个中介,实现是由AudioPolicyService完成的。
audio_io_handle_t AudioPolicyService::getOutput(…)@ AudioPolicyInterfaceImplLegacy.cpp{
return mpAudioPolicy->get_output(…);
}
前面分析过,mpAudioPolicy就是lap (类型:legacy_audio_policy)中的policy(类型:audio_policy),根据其相应函数指针的实现:
static int create_legacy_ap(…)@ audio_policy_hal.cpp {
struct legacy_audio_policy *lap;
lap->policy.get_output = ap_get_output;
}
static audio_io_handle_t ap_get_output(…) @ audio_policy_hal.cpp {
lap->apm->getOutput(…);
}
Getoutput最终的实现在AudioPolicyManagerBase中。
audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type stream,
uint32_t samplingRate,
audio_format_t format,
audio_channel_mask_t channelMask,
AudioSystem::output_flags flags,
const audio_offload_info_t *offloadInfo)@ AudioPolicyManagerBase.cpp {
//step1,获取stream音频类型对应的strategy。
routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream);
audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/);
//step2,依据策略,判断哪些output符合传入的stream类型。
SortedVector outputs = getOutputsForDevice(device, mOutputs);
//step3,选择最优的output
output = selectOutput(outputs, flags);
}
Step1,每种stream类型,都有对应的路由策略routing_strategy,stream type和routing_strategy的对应关系:
不同的stream类型,可能使用同一个strategy,可以通过重载getStrategy定制策略。
找到stream类型对应的strategy后,getDeviceForStrategy将为strategy匹配最佳的音频设备。
audio_devices_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy,
bool fromCache){
switch (strategy) {
case STRATEGY_MEDIA: {
uint32_t device2 = AUDIO_DEVICE_NONE;
if ((device2 == AUDIO_DEVICE_NONE) &&
mHasA2dp && (mForceUse[AudioSystem::FOR_MEDIA] != AudioSystem::FORCE_NO_BT_A2DP) &&
(getA2dpOutput() != 0) && !mA2dpSuspended) {
device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
if (device2 == AUDIO_DEVICE_NONE) {
device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
}
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_WIRED_HEADSET;
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_ACCESSORY;
}
if (device2 == AUDIO_DEVICE_NONE) {
device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_DEVICE;
}
}
device |= device2;
//如果匹配到合适的device,跳出switch。
if (device) break;
//否则,使用默认的device
device = mDefaultOutputDevice;
}
}
以上匹配的过程是有优先级的,从上到下依次匹配,优先级递减,前一个优先级匹配成功,device2就不为AUDIO_DEVICE_NONE了,所以下面的就不在判断了。
Step2,上一步找到匹配的device,这一步为device选择合适的output通道。
SortedVector AudioPolicyManagerBase::getOutputsForDevice(audio_devices_t device,
DefaultKeyedVector openOutputs){
SortedVector outputs;
for (size_t i = 0; i < openOutputs.size(); i++) {
if ((device & openOutputs.valueAt(i)->supportedDevices()) == device) {
outputs.add(openOutputs.keyAt(i));
}
}
}
所有支持device设备的output都被添加到outputs中,这里的output就是前面AudioFlinger::openOutput的执行结果,因为每个output通常支持若干种音频设备,不同的output支持的音频设备类型没有限制,所以可能存在多个支持同一个device的output。
Step3,既然符合要求的output不止一个,就选择一个最合适的。
audio_io_handle_t AudioPolicyManagerBase::selectOutput(
const SortedVector& outputs,
AudioSystem::output_flags flags)){
//如果没有output存在,只能返回0,如果只有一个output,就直接返回这个output。
if (outputs.size() == 0) {
return 0;
}
if (outputs.size() == 1) {
return outputs[0];
}
//选择最优的一个,针对每个output循环计算:outputDesc->mProfile->mFlags & flags的最大值,也就是计算其中的1的个数。
for (size_t i = 0; i < outputs.size(); i++) {
AudioOutputDescriptor *outputDesc = mOutputs.valueFor(outputs[i]);
if (!outputDesc->isDuplicated()) {
int commonFlags = (int)AudioSystem::popCount(outputDesc->mProfile->mFlags & flags);
if (commonFlags > maxCommonFlags) {
outputFlags = outputs[i];
maxCommonFlags = commonFlags;
}
if (outputDesc->mProfile->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) {
outputPrimary = outputs[i];
}
}
}
}
这个择优判断的规则,也是有优先级的:
首先:请求策略的flags,值最大的那个output,也就是:outputDesc->mProfile->mFlags和flags的值最大的那个。
然后:the primaryoutput
最后:the first output in thelist。