audiopolicy分析

来源:互联网 发布:linux select c代码 编辑:程序博客网 时间:2024/06/05 00:56
本章节,大体介绍一下AudioPolicyService
手机的Audio输入源很多,例如放电影,放音乐,通话,铃声,提示音等
输出也很多,例如蓝牙,耳机,喇叭,听筒等
那么什么声音输出到什么地方呢?
这就是AudioPolicyService干的事情了。

首先明确几个概念:
1,Audio interfaces
安卓手机上目前支持三类音频播放设备,这个主要是根据声音播放端和CPU的通信关系来划分的。
static const char * const audio_interfaces[] = {    AUDIO_HARDWARE_MODULE_ID_PRIMARY, //手机板载的主设备    AUDIO_HARDWARE_MODULE_ID_A2DP, //蓝牙音频    AUDIO_HARDWARE_MODULE_ID_USB, //USB音频};

2,Audio Devices ,是指具体的音频播放设备。比Audio interfaces的粒度要细一些
见表格



3, StreamType, 是指PCM的生成类型。是播放电影产生的?还是通话产生的?
  enum stream_type {        DEFAULT          =-1,        VOICE_CALL       = 0,        SYSTEM           = 1,        RING             = 2,        MUSIC            = 3,        ALARM            = 4,        NOTIFICATION     = 5,        BLUETOOTH_SCO    = 6,        ENFORCED_AUDIBLE = 7,         DTMF             = 8,        TTS              = 9,        NUM_STREAM_TYPES    };
4, STRATEGY, 是指针对某一中stream,该采用的策略。在策略里面,会根据其他信息来具体选定某一个具体的Audio Devices
enum routing_strategy {            STRATEGY_MEDIA,            STRATEGY_PHONE,            STRATEGY_SONIFICATION,            STRATEGY_SONIFICATION_RESPECTFUL,            STRATEGY_DTMF,            STRATEGY_ENFORCED_AUDIBLE,            NUM_STRATEGIES        };
所以,APS干的事情,实际上就是根据这一路AudioTrack的StreamType,找到他要遵循的STRATEGY,根据这个STRATEGY,在目前设备上可以获得的Audio Devices里面查找到最优的Audio Devices,
然后使用这个Audio Device来播放声音 。


下面我们来分析一下APS的启动过程
在AF章节中,我们介绍过,mediaserver进程启动时,会启动APS进程,
然后APS的构造函数被被调用到
AudioPolicyService::AudioPolicyService()    : BnAudioPolicyService() , mpAudioPolicyDev(NULL) , mpAudioPolicy(NULL){    rc = hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module);  //获得HAL层的so lib    rc = audio_policy_dev_open(module, &mpAudioPolicyDev);   //打开上面获得的policy 设备    rc = mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this,&mpAudioPolicy); //创建一个策略    rc = mpAudioPolicy->init_check(mpAudioPolicy);  //初始化检测}

AudioPolicyService::AudioPolicyService()    : BnAudioPolicyService() , mpAudioPolicyDev(NULL) , mpAudioPolicy(NULL){    rc = hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module);  //获得HAL层的so lib    rc = audio_policy_dev_open(module, &mpAudioPolicyDev);   //打开上面获得的policy 设备    rc = mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this,&mpAudioPolicy); //创建一个策略    rc = mpAudioPolicy->init_check(mpAudioPolicy);  //初始化检测}

下面针对这个构造函数具体介绍一下
和AF一样,也APS需要打开一个HAL层的so lib库。
只不过AF中的HAL 库,会调用实际的硬件。而这里的HAL库一般不调用硬件,只是为了方便厂家定义自己的策略,独立出来一个模块而已。
这里实际上打开的就是Audio_policy_hal.cpp这个so lib。并且返回一个hw_module_t作为handle.
然后audio_policy_dev_open调用Audio_policy_hal.cpp中的legacy_ap_dev_open,这主要是为一个hw_device_t结构挂钩子函数,填充信息。并且把hw_device_t返回给上层。
后面调用的create_audio_policy,实际上就是这里挂到hw_device_t上面的create_legacy_ap。
create_legacy_ap主要作用就是创建一个struct audio_policy结构体,当中挂了很多Audio_policy_hal.cpp中的钩子函数。如下:
   
 lap->policy.set_phone_state = ap_set_phone_state;    lap->policy.set_ringer_mode = ap_set_ringer_mode;    lap->policy.set_force_use = ap_set_force_use;    lap->policy.get_force_use = ap_get_force_use;    lap->policy.set_can_mute_enforced_audible = ap_set_can_mute_enforced_audible;    lap->policy.init_check = ap_init_check;    lap->policy.get_output = ap_get_output;    lap->policy.start_output = ap_start_output;    lap->policy.stop_output = ap_stop_output;    lap->policy.release_output = ap_release_output;    lap->policy.get_input = ap_get_input;    lap->policy.start_input = ap_start_input;    lap->policy.stop_input = ap_stop_input;    lap->policy.release_input = ap_release_input;    lap->policy.init_stream_volume = ap_init_stream_volume;    lap->policy.set_stream_volume_index = ap_set_stream_volume_index;    lap->policy.get_stream_volume_index = ap_get_stream_volume_index;    lap->policy.set_stream_volume_index_for_device = ap_set_stream_volume_index_for_device;    lap->policy.get_stream_volume_index_for_device = ap_get_stream_volume_index_for_device;    lap->policy.get_strategy_for_stream = ap_get_strategy_for_stream;    lap->policy.get_devices_for_stream = ap_get_devices_for_stream;    lap->policy.get_output_for_effect = ap_get_output_for_effect;

这些钩子函数,都是后面APS实际发挥作用时要用到的。
例如最后一步调用的init_check,就是这里挂上去的。
而这些钩子函数,例如ap_init_check,最终都是调用的AudioPolicyManagerBase中的函数来发挥实际作用。
例如status_t AudioPolicyManagerBase::initCheck()
所以,APS只是一个接口而已,APS实际发挥作用,依赖的就是AudioPolicyManagerBase类。
是不是很绕?
可以说mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this,&mpAudioPolicy)这个函数,是APS构造函数里面最重要的函数
返回的mpAudioPolicy,当中挂接了各种操作接口,后续APS实际发挥作用,全靠他。

在AudioPolicyManagerBase的构造函数中,会进行非常多的初始化操作
<pre name="code" class="cpp">AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clientInterface){    if (loadAudioPolicyConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE) != NO_ERROR) {        if (loadAudioPolicyConfig(AUDIO_POLICY_CONFIG_FILE) != NO_ERROR) {      //读取配置文件            ALOGE("could not load audio policy configuration file, setting defaults");            defaultAudioPolicyConfig();        }    }AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clientInterface){    if (loadAudioPolicyConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE) != NO_ERROR) {        if (loadAudioPolicyConfig(AUDIO_POLICY_CONFIG_FILE) != NO_ERROR) {      //读取配置文件            ALOGE("could not load audio policy configuration file, setting defaults");            defaultAudioPolicyConfig();        }    }    for (size_t i = 0; i < mHwModules.size(); i++) {        mHwModules[i]->mHandle = mpClientInterface->loadHwModule(mHwModules[i]->mName);  //根据配置文件加载 所有audio interface的so lib        for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++)        {            const IOProfile *outProfile = mHwModules[i]->mOutputProfiles[j];   //根据配置文件加载 所有output audio device            if ((outProfile->mSupportedDevices & mAttachedOutputDevices) &&                    ((outProfile->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) == 0)) {                AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor(outProfile);                outputDesc->mDevice = (audio_devices_t)(mDefaultOutputDevice &  outProfile->mSupportedDevices);                audio_io_handle_t output = mpClientInterface->openOutput(  //打开output                                                outProfile->mModule->mHandle,                                                &outputDesc->mDevice,                                                &outputDesc->mSamplingRate,                                                &outputDesc->mFormat,                                                &outputDesc->mChannelMask,                                                &outputDesc->mLatency,                                                outputDesc->mFlags);                    mAvailableOutputDevices = (audio_devices_t)(mAvailableOutputDevices | //记录所有可用的output device                                            (outProfile->mSupportedDevices & mAttachedOutputDevices));                        }        }    }}
通过对AudioPolicyManagerBase构造函数的简化,我们可以知道其干了以下事情:
1,读取配置文件
#define AUDIO_POLICY_VENDOR_CONFIG_FILE  "/vendor/etc/audio_policy.conf"
#define AUDIO_POLICY_CONFIG_FILE"/system/etc/audio_policy.conf"
如下所示:
audio_hw_modules {   primary {  //有哪些audio interface     outputs {       primary { //有哪些output audio device         sampling_rates 48000         channel_masks AUDIO_CHANNEL_OUT_STEREO         formats AUDIO_FORMAT_PCM_16_BIT         devices AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|AUDIO_DEVICE_OUT_ALL_SCO          flags AUDIO_OUTPUT_FLAG_PRIMARY       }       deep_buffer { //有哪些output audio device         sampling_rates 48000         channel_masks AUDIO_CHANNEL_OUT_STEREO         formats AUDIO_FORMAT_PCM_16_BIT         devices AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE         flags AUDIO_OUTPUT_FLAG_DEEP_BUFFER       }     }     inputs {       primary { //有哪些input audio device         sampling_rates 8000|11025|12000|16000|22050|24000|32000|44100|48000         channel_masks AUDIO_CHANNEL_IN_MONO|AUDIO_CHANNEL_IN_STEREO         formats AUDIO_FORMAT_PCM_16_BIT         devices AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET|AUDIO_DEVICE_IN_WIRED_HEADSET|AUDIO_DEVICE_IN_VOICE_CALL       }     }   }   a2dp {   //有哪些audio interface     outputs {       a2dp { //有哪些output audio device         sampling_rates 44100         channel_masks AUDIO_CHANNEL_OUT_STEREO         formats AUDIO_FORMAT_PCM_16_BIT         devices AUDIO_DEVICE_OUT_ALL_A2DP       }     }   }}

配置文件记录了有哪些audio interface, 每个audio interface里面有哪些input,output audio device,每个设备的属性。
  通过读取配置文件,就知道了系统中有哪些audio interface 例如(“primary”、“a2dp”、“usb”),
  每个audio interface 中有哪些input,output audio device, 例如 (primary,deep_buffer)
  每个audio device中的属性 ,例如sampling_rates,channel_masks,formats
  
 2,配置文件读取完毕之后,利用两层循环, 
 外层循环调用mpClientInterface->loadHwModule,遍历所有的 audio interface,
 内层循环调用mpClientInterface->openOutput,遍历所有的output audio device,打开这些output audio device。
 并且记录下可用的outputDevice
  那么mpClientInterface->loadHwModule,mpClientInterface->openOutput具体是如何实现的呢?
  AudioPolicyService::AudioPolicyService中,我们强调了mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this, &mpAudioPolicy); 
 这个函数传入了aps_ops数组,这个数组在create_legacy_ap中,被挂到了mpClientInterface中。
 所以,mpClientInterface调用的函数,就是aps_ops的函数。
 struct audio_policy_service_ops aps_ops = {        open_output           : aps_open_output,        open_duplicate_output : aps_open_dup_output,        close_output          : aps_close_output,        suspend_output        : aps_suspend_output,        restore_output        : aps_restore_output,        open_input            : aps_open_input,        close_input           : aps_close_input,        set_stream_volume     : aps_set_stream_volume,        set_stream_output     : aps_set_stream_output,        set_parameters        : aps_set_parameters,        get_parameters        : aps_get_parameters,        start_tone            : aps_start_tone,        stop_tone             : aps_stop_tone,        set_voice_volume      : aps_set_voice_volume,        move_effects          : aps_move_effects,        load_hw_module        : aps_load_hw_module,        open_output_on_module : aps_open_output_on_module,        open_input_on_module  : aps_open_input_on_module,    };

其中:
static audio_module_handle_t  aps_load_hw_module(void*service,const char *name){    sp<IAudioFlinger> af= AudioSystem::get_audio_flinger();    …    returnaf->loadHwModule(name);}

static audio_io_handle_t  aps_open_output(…){    sp<IAudioFlinger> af= AudioSystem::get_audio_flinger();    …    return  af->openOutput((audio_module_handle_t)0,pDevices, pSamplingRate, pFormat, pChannelMask,                         pLatencyMs, flags);}

也就是说mpClientInterface->loadHwModule,mpClientInterface->openOutput最终调用了AF中的函数。
这就是我们在AF章节中提到的”在audio播放之前,AP还会调用AF的openOutput函数来打开一个输出“ ”AP会调用AF的函数AudioFlinger::loadHwModule完成对应SO的加载“
到目前为止,我们介绍完了APS的初始化部分。
那么APS具体是怎么工作的呢?让我们回到AT部分
AT章节中,我们提到了AudioTrack::set函数,经过如下层层调用:
AudioTrack::set--->AudioSystem::getOutput--->AudioPolicyService::getOutput--->ap_get_output--->AudioPolicyManagerBase::getOutput 

AudioPolicyManagerBase::getOutput里面完成audio policy的选取
audio_io_handle_t AudioPolicyManagerBase::getOutput(){    routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream);  //根据stream_type来确定这个AT应该遵循的strategy    audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/); //根据这个strategy,在当前可用设备中,找到优先级最高的设备   if (audio_is_linear_pcm((audio_format_t)format)) {        SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(device, mOutputs); //在output playbackThread中,找到所有支持这个选中的设备的output playbackThread        output = selectOutput(outputs, flags);  //在找到的所有的playback中,选择一个最优的output playbackThread    }    return output;}

通过对代码的简化,我们可以看到,
首先要根据AT传过来的stream_type来决定AT应该遵循的策略,比如AudioSystem::TTS 和AudioSystem::MUSIC对应的是STRATEGY_MEDIA,AudioSystem::NOTIFICATION对应的是STRATEGY_SONIFICATION_RESPECTFUL。
具体下图所示:
然后根据这个策略,查询当前可用设备,在可用设备里找一个优先级最高的,逻辑如下:
    case STRATEGY_MEDIA: {        uint32_t device2 = AUDIO_DEVICE_NONE;        if (strategy != STRATEGY_SONIFICATION) {            device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_REMOTE_SUBMIX;        }        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;        }

代码逻辑很简单。谁在前面,谁就优先级高。
因为要写入实际硬件,是要通过AF中的output的概念写入的,也就是通过playbackThread来写入硬件。
所以不仅要完成device的选择,还要完成playbackThread的选择
这里要找到所有支持这个最高优先级audio device的playbackThread,这就是getOutputsForDevice完成的工作。
当然,找到的playbackThread可能有多个,这时就要选取最合适的。这就是selectOutput函数干的事情。
那么何谓最合适呢?
audio_io_handle_t AudioPolicyManagerBase::selectOutput(const SortedVector<audio_io_handle_t>& outputs,                                                       AudioSystem::output_flags flags){    int maxCommonFlags = 0;    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 (outputFlags != 0) {        return outputFlags;    }}

可以看到,这里想做的,就是拿AT传过来的output_flags和outputDesc->mProfile->mFlags做比较,相似度最高的(maxCommonFlags值最大),就会被选中。
outputDesc->mProfile->mFlags 则是在AudioPolicyManagerBase构造函数中,读取配置文件获得。

这样,就根据AT传过来的信息,为这个AT的找到了对应的playbackThread, 并且通过调用AF的代码,在playbackThread中完成了Track的创建。
之后,AT写入playbackThread中的代码,就会写到对应的硬件中。






1 0
原创粉丝点击