javaee论坛

普通会员

225648

帖子

334

回复

348

积分

楼主
发表于 2019-10-30 14:58:32 | 查看: 137 | 回复: 3

在上小节中,分析了android音频系统中,HAL代码的框架,该小节我们根据源代码查看一下流程,加深一下理解。在分析源代码之前,我们先俩看看HAL在整个音频系统中,他处于什么位置,下面是一个框图,相关知识点,在前面的小节中,都已经讲解过:

现在我们来回顾一下,假设有一个android手机,他上面有喇叭,我们在听音乐的时候,声音会中喇叭中播放出来,当插上耳机的时候,声音就从耳机中播放出来,那么这整个过程会涉及什么东西?1.优先从耳机播放,其由AudioPolicyService决定2.如果有多个APP要播放声音,AudioFlinger负责混合多个APP的声音,当然除此之外还有其他的许多功能。3.最终要操作硬件,有多种声卡,可以动态的拔插(USB声卡,蓝牙声卡),对于每一种声卡由一个模块(so文件)来操控他,即HAL4.为简化声卡的操作,有一个tinyalsa库。只需要pcm_open,pcm_wirte,pcm_read就能进行播放录音。5.pcm_open,pcm_wirte,pcm_read通过标准的open,wirte,read访问驱动,进而控制驱动访问硬件。

现在我们来看看HAL的代码是怎么被调用的,其又是怎么调用tinyalsa的。下面是流程图:我们先来看下HAL的操作流程:1.从/system/etc/audio_policy.conf配置文件中确定so文件的名字。2.加载so文件3.HAL文件中的open函数构造并且返回一个audio_hw_device_t结构体,其中包含了adev_open_output_stream,adev_open_input_stream。然后AudioFlinger使用audio_hw_device_t构造成AudioHwDevice对象,每个声卡对应一个audio_hw_device_t与AudioHwDevice。放入数组mAudioHwDeviceS中。4.调用hal文件中audio_hw_device_t结构体中的adev_open_output_stream会构建一个audio_stream_out结构体,返回给AudioFlinger,AudioFlinger使用根据他创建一个MixerThread线程。

根据图示,最终会调用到adev_open_output_stream。

5.write写入给声卡,

以上步骤的对应函数都已经和流程图连接,之前讲解过的函数,就不再次进行讲解了,我们知道每个module中都有一个,如audio_hw_hal.cpp中:

staticintlegacy_adev_open(consthw_module_t*module,constchar*name,hw_device_t**device){*device=&ladev->device.common;}staticstructhw_module_methods_tlegacy_audio_module_methods={open:legacy_adev_open};structlegacy_audio_moduleHAL_MODULE_INFO_SYM={module:{common:{tag:HARDWARE_MODULE_TAG,module_api_version:AUDIO_MODULE_API_VERSION_0_1,hal_api_version:HARDWARE_HAL_API_VERSION,id:AUDIO_HARDWARE_MODULE_ID,name:"LEGACYAudioHWHAL",author:"TheAndroidOpenSourceProject",methods:&legacy_audio_module_methods,dso:NULL,reserved:{0},},},};

这个module中有一个方法methodslegacy_audio_module_methods,methods中包含了open函数,那么他是在什么时候被调用呢?从流程图可以知道load_audio_interface,打开AudioFlinger.cpp:

staticintload_audio_interface(constchar*if_name,audio_hw_device_t**dev)/*获得一个audio_hw_device_t**dev结构体指针*/rc=audio_hw_device_open(mod,dev);

audio_hw_device_t最终在AudioFlinger中被构建成一个AudioHwDevice对象,

现在我们看看最终调用到的adev_open_output_stream函数:

staticintadev_open_output_stream(structaudio_hw_device*dev,audio_io_handle_thandle,audio_devices_tdevices,audio_output_flags_tflags,structaudio_config*config,structaudio_stream_out**stream_out,constchar*address__unused)out->stream.write=out_write;*stream_out=&out->stream;

可以知道其返回一个audio_stream_out结构体。其中的out_write函数又对应谁呢?其对应AudioHardware.cpp(厂家提供)中的write函数。当然,引起该函数的调用流程如下:也就是说MixerThread线程被创建之后,一直在等待数据,当接受到数据之后最终引起AudioHardware.cpp(厂家提供)中的write函数被调用。

下面是该小节的要点总结:

HAL之调用流程源码分析a.确定HAL文件的名字:AudioPolicyManager的构造函数读取配置文件/system/etc/audio_policy.conf确定名字b.加载HAL对应的so文件c.打开HAL文件中的open函数在HAL中会构造audio_hw_device结构体,该结构体中有各类函数,特别是open_output_stream/open_input_streamAudioFlinger根据audio_hw_device结构体构造一个AudioHwDev对象并放入mAudioHwDevsd.openoutputstream:调用hal结构体audio_hw_device的open_output_stream,它会构造出一个audio_stream_out结构体,里面有write函数AudioFlinger根据audio_stream_out结构体构造一个MixerThreade.播放声音(这时才真正打开声卡驱动):thread->threadLoopg_write=>stream.write==>pcm_open,pcm_write

普通会员

0

帖子

300

回复

308

积分
沙发
发表于 2021-04-20 19:27:24

百因必有果你的报应就是我

普通会员

0

帖子

310

回复

321

积分
板凳
发表于 2022-05-11 02:11:45

好好好

普通会员

0

帖子

291

回复

298

积分
地板
发表于 2023-08-03 16:30:09

楼主听话,快到碗里来!

您需要登录后才可以回帖 登录 | 立即注册

触屏版| 电脑版

技术支持 历史网 V2.0 © 2016-2017