我是靠谱客的博主 缓慢热狗,最近开发中收集的这篇文章主要介绍Android音频子系统,Audiopolicyservice音频策略的制定(五),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

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<IAudioPolicyService>& 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<audio_io_handle_t> 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<audio_io_handle_t> AudioPolicyManagerBase::getOutputsForDevice(audio_devices_t device,
    DefaultKeyedVector<audio_io_handle_t, AudioOutputDescriptor *> openOutputs){
	SortedVector<audio_io_handle_t> 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<audio_io_handle_t>& 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。

最后

以上就是缓慢热狗为你收集整理的Android音频子系统,Audiopolicyservice音频策略的制定(五)的全部内容,希望文章能够帮你解决Android音频子系统,Audiopolicyservice音频策略的制定(五)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(55)

评论列表共有 0 条评论

立即
投稿
返回
顶部