android AudioFlinger的启动流程

              最近要负责android音频这块的任务,看了一些大神们的分享,然后自己结合代码进行了整理总结:

         Android系统一般播放音频主要是通过Mediaplayer和Soundpool这2中方式,当然还有一些功能不走系统通道的如: 带Radio功能, 它硬件设计Radio单独走一个通道,这种情况不做分析,一般驱动提供切换接口,然后在进入radio时把通道切过去就行.

        Soundpool:比较简单,就是播放一段短音频文件,之前在做OBD倒车时需要提示滴滴的警示铃声时用到过,据说Soundpool只能播放1M以内的音频文件(没试过),感兴趣的朋友可以试试.

        MediaPlayer:我们来看看MediaPlayer,我们都知道Android的音频播放都是通过MediaPlayerService来控制,相当于一个控制器一样去控制播放和暂停,那它是怎样启动的呢? 

        Android的初始化进程是在/system/core/init/init.c的main函数中:

接着就启动Init.rc文件(这个地方通过宏 MTK_INIT来做兼容,不同的厂商可能不一样,很明显,我这里是MTK的方案大笑 )在/system/core/rootdir目录下,我们看到了MediaServer的启动:


因为init.rc是整个android系统启动的进程所以不仅有MediaServer,还有servicemanager, surfaceflinger等等都在这里启动, 另外这里面可以添加第三方模块的服务启动,如: 要增加外挂蓝牙功能,蓝牙服务商会提供.so文件,我们这里面可以添加蓝牙服务,提醒一下,增加后别忘记添加权限.

       MediaServer服务在/framework/av/media/mediaserver/Main_mediaserver.cpp的main()中定义:


看到了吧,几个比较重要的音频服务,像AudioFlinger,MediaPlayerService,AudioPolicyService都是在这里启动的,

我们来看看AudioFlinger的启动,AudioFlinger::instantiate();对AudioFlinger初始化后进入到了AudioFlinger.cpp,在framework/av/service/目录下,AudioFlinger的构造函数(只截取了一部分):


AudioFlinger.cpp里面有个比较重要的操作就是加载HAL硬件抽象层的音频接口 loadHwModule()



真正对HAL层音频模块的操作在load_audio_interface()这个函数里面, 

hw_get_module_by_class():加载HAL音频设备.

audio_hw_device_open():打开音频设备. 

还有关闭HAL层的音频设备的操作,在AudioFlinger.cpp的析构函数中:



hw_get_module_by_class(),  audio_hw_device_open(), audio_hw_device_close(), 这几个都是HAL硬件抽象层比较核心的API.我们接着往下看,在 hw_get_module_by_class()加载音频模块的时候跟了一个AUDIO_HARDWARE_MODULE_ID的参数,很明显这个参数是音频模块的ID号,全盘搜索下 grep -rn "AUDIO_HARDWARE_MODULE_ID":


可以看到AUDIO_HARDWARE_MODULE_ID定义的地方在/hardware/libhardware/include/hardware/audio.h

具体实现的地方在hardware/libhardware_legacy/audio/audio_hw_hal.cpp中(可能不同的方案商所在的路径可能会有点不一样),继续看audio_hw_hal.cpp里AUDIO_HARDWARE_MODULE_ID实现的地方


我们看到了 id: AUDIO_HARDWARE_MODULE_ID,它的methods:方法实现是调用到了 legacy_adev_open

再看legacy_adev_open的函数体实现



这个地方主要是对legacy_audio_device *ladev做了一些初始化的操作,我们主要看createAudioHardware()

还是笨方法全盘搜索createAudioHardware(),在hardware/qcom/audio/legacy/alsa_sound/AudioHardwareALSA.cpp

里看到了createAudioHardware()的实现,



可以看到它创建一个AudioHardwareALSA的对象,AudioHardwareALSA()的构造函数里面就调用了HAL层的API -> hw_get_module()获取了ID号为ALSA_HARDWARE_MODULE_ID的ALSA硬件模块, OK, 这时候就开始进到android的ALSA音频系统了.

         继续往下看,搜索ID为ALSA_HARDWARE_MODULE_ID的HAL硬件抽象层的实现方法,可以看到ALSA_HARDWARE_MODULE_ID在hardware/qcom/audio/legacy/alsa_sound/AudioHardwareALSA.h头文件中定义,其实现方法在hardware/qcom/audio/legacy/alsa_sound/alsa_default.cpp中


看到了吧 它的methods方法去调用 s_device_open


这部分就是ID号为 ALSA_HARDWARE_MODULE_ID -> s_module_methods(Method方法) -> s_device_open(对ALSA的HAL层初始化)的实现过程,到这里AudioFlinger服务就已经启动了.

以上就是AudioFlinger -> AudioHardwareALSA 子音频系统 -> open HAL层音频设备的过程,那么问题来了,谁来告诉AudioFlinger来打开音频模块的呢? 通过上面分析我们知道打开的入口是在AudioFlinger的loadHwModule()它会调到load_audio_interface()开始执行打开,那么谁来调用loadHwModule()这个呢? 我刚开始在AudioFlinger.cpp中去搜索一下这个函数,结果没有地方调用,还是全盘搜索下吧,发现在 framework/av/services/audiopolicy/AudioPolicyManager.cpp的构造函数中调用到了


再看下它的定义是在framework/av/services/audiopolicy/AudioPolicyClientInterface.h头文件中


是一个虚函数,传的参数就是要打开的音频设备名,这个设备名是从容器mHwModules循环取出来的,那么问题又来了,这些音频设备名称又是怎么存放到mHwModules这个容器中呢?我们接着看AudioPolicyManager.cpp的构造函数,


搜索AUDIO_POLICY_VENDOR_CONFIG_FILE 


原来是通过加载audio_policy.conf文件来获取音频设备接口名称,来看看loadAudioPolicyConfig()具体的实现方法,






最终在loadHwModule()函数里把module加入到mHwModules容器中.

我们再回头看AudioPolicyManager.cpp的构造函数它的流程是先从audio_policy.conf这个配置文件读取到音频设备接口名称加入到mHwModules容器,然后通过循环去加载对应名称的音频设备模块,到这里我想大家都应该明白了AudioFlinger()中的loadHwModule()是怎么启动的了吧.


总结:通过以上的整个流程,我们可以知道,其实AudioFlinger负责执行加载打开HAL层的音频模块接口,而AudioPolicyManager则负责告诉AudioFlinger去打开那个音频模块,其实说白了AudioFlinger就是一个执行操作者,而

AudioPolicyManager就是管理者.(就像我们这些苦逼的程序猿们,老大就是管理者,底下的小弟们就是执行者,分别负责不同的项目不同的模块,开个玩笑!大笑),第一次写博客,语言貌似有些生硬,望见谅,希望能对大家有帮助,有不对的地方,欢迎留言指正.






  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值