audiopolicy分析

本章节,大体介绍一下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中的代码,就会写到对应的硬件中。






  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值