Android 5.1 Audio HAL分析

news/2024/11/28 3:50:14/
  1. 初始化工程
    这里写图片描述
    1) AudioPlicyService被第一次实例化后,将会调用onFirstRef,其中实例化了两个全局变量,一个是mAudioPolicyClient,一个是mAudioPolicyManager。
    2) mAudioPolicyClient是AudioPolicyClient类型的,具体实现在AudioPolicyClientImpl.cpp,该类中保存了AudioPolicyService的指针。
    3) mAudioPolicyManager的类型为AudioPolicyInterface,它被工厂类实例化为AudioPolicyManager。
    AudioPolicyManager被实例化时,将会初始化audio设备的信息。
    首先会查找/vendor/etc/audio_policy.conf中的文件,如果没有此文件,会查找/system/etc/audio_policy.conf,如果仍然没有此文件,将会使用默认的策略文件。
    audio_policy.conf格式类似如下:
    audio_hw_modules {
    primary {
    ……..
    }
    }
    该文件定义了音频设备的信息,如上面就定义了一个audio设备primary,里面的信息会逐一读取,并保存到mHwModules容器中。
    接着,会通过Binder调用audioflinger的loadHwModule逐一加载硬件设备,loadHwModule会返回一个int只,作为每一个设备的唯一号保存在mHwModules容器中的mHandler变量中,同时在audioflinger中作为mAudioHwDevs容器的索引。
  2. 加载硬件过程
    这里写图片描述
    1) loadHwModule中会传进来要加载的硬件的名称,是从audio_policy.conf读取的,比如primary,所以,最后hw_get_module_by_class调用的形参如下:
    hw_get_module_by_class(“audio”, “primary”, &mod);
    2) hw_get_module_by_class是hardware.c的一个函数,hardware.c位于hardware/libhardware/hardware.c中,它根据传进去的两个参数,拼接成audio.primary这种名字,然后在根据手机中的属性值,查找 究竟使用的是哪一个库,实际上也就是一个一个是,比如首先看audio.primary.mt6735.so是否在/vendor/lib64/hw或/system/lib64/hw文件夹中,如果存在,就代表要使用这个动态库,不再查找其他动态库。
    3) Load函数就是在动态加载HAL库即audio.primary.mt6735.so并找到其符号HAL_MODULE_INFO_SYM的地址,HAL_MODULE_INFO_SYM是一个hw_module_t类型的结构,该值是从hw_get_module_by_class中的第三个形参过来的,也就是mod,该值会被传到audioflinger中的mod中去。
    4) audio_hw_device_open实际上是使用的上一步中获得的mod的指针的open函数(根据上一步的操作,open函数最终指向了legacy_adev_open方法),其中仍需注意第二个参数dev,它是一个audio_hw_device_t类型的指针,将会通过open返回到audioflinger中。
    legacy_adev_open将会创建一个legacy_audio_device指针,最后返回audiofliger一个hw_device_t类型的指针给dev。需要注意的一点,dev原来是一个audio_hw_device_t类型,现在变成了hw_device_t,这是不是就是说出了第一个参数common被初始化了,其他的成员函数并没有被初始化?不是!
    *device = &ladev->device.common;
    也就是将ladev的首地址传上去了,剩下的成员都是依次排列的,通过指针可以访问到所有的成员。这是C语言常用的技术。
    legacy_adev_open还创建了一个AudioALSAHardware的实例,这一点也很重要。
    5) AudioALSAHardware中初始化了几个干活的实例,如mStreamManager,它是AudioALSAStreamManager对象的实例。
    6) 最后,将dev保存到AudioHwDevice实例中,并将AudioHwDevice实例放入到mAudioHwDevs容器中。
    audio_hw_hal.cpp: vendor/mediatek/proprietary/platform/common/hardware/audio/aud_drv/audio_hw_hal.cpp
    AudioALSAHardware.cpp:
    vendor/mediatek/proprietary/platform/common/hardware/audio/V3/aud_drv/AudioALSAHardware.cpp
  3. AudioStreamIn指针的建立
    AudioStreamIn代表的是录音时的输入流,所以以AudioRecord为例
    这里写图片描述
    1) openInput_l首先根据唯一的handle值找到AudioHwDevice,这时上章加载硬件是产生的,然后通过由HAL层返回的指针去调用open_input_stream,注意该函数的第5个参数,该值是个指向指针的指针,其类型为audio_stream_in,以后会被广泛使用,其值会通过open_input_stream返回上来。
    2) adev_open_input_stream运行时,会创建一个adev_open_input_stream指针,该指针的首地址即是open_input_stream的第5个参数,会被传送到audioflinger层。该指针中还有一个AudioStreamIn类型的legacy_in指针,该指针最终被实例化为AudioALSAStreamIn,非常重要,最后干活的将是这个对象:
    in->legacy_in = ladev->hwif->openInputStream(devices, (int *) &config->format,
    &config->channel_mask, &config->sample_rate,
    &status, (AudioSystem::audio_in_acoustics)0);
    3) 截止到目前,我们得到了两个重要的指针,一个是audio_hw_device_t类型的指针,通过该指针,我们操作HAL层对我们暴露的基本方法,如get_supported_devices等方法。
    另一个指针是audio_stream_in_t类型的指针,通过此指针,我们可以完成相应的流操作,如读取等。
    这两个指针被传入到AudioStreamIn对象,作为RecordThread的mInput实例保存起来。
  4. RecordThread和HAL的数据交换
    这里写图片描述
    在AudioFlinger::RecordThread::threadLoop中会调用mInput->stream->read读取数据,stream就是audio_stream_in_t类型的指针,在执行open_input_stream时被初始化,先在它其实是一个legacy_stream_in类型的指针。当调用read时,in_read将会被调用。然后真正执行的是AudioStreamIn类中的read函数。
    在该函数中,如果AudioALSACaptureHandlerBase类型的mCaptureHandler指针还没被初始化,将会调用AudioALSAStreamManager中的createCaptureHandler创建一个mCaptureHandle指针。AudioALSAStreamManage使用的是工厂模式,根据不同的设备类型,创建不同的执行类,如果是使用的MIC,将会创建AudioALSACaptureHandlerNormal类型的实例。
  5. Read分析
    这里写图片描述
    在第3步创建AudioStreamIn的指针过程中,AudioFlinger调用open_input_stream会创建一个AudioStreamIn指针,创建过程中,AudioALSAStreamManager是一个单例,但AudioStreamIn并不是单例,只要open_input_stream函数被调用,就会创建一个AudioStreamIn实例,AudioStreamIn创建的获取采集数据的mCaptureHandler也不是单例。
    但是,在创建mCaptureHandler的AudioALSACaptureDataClient实例时,第一个参数为AudioALSACaptureDataProviderBase类型的指针,它是一个单例,是通过AudioALSACaptureDataProviderNormal::getInstance()传进去的。
    创建AudioALSACaptureDataClient实例时,做了几个重要的工作,1个是创建了一个环形缓冲区,buffer大小为32k,用来保存数据,AudioFlinger读取数据时,就是从该缓冲区中读取的,另一个就是向AudioALSACaptureDataProviderNormal注册了一个观察者,当有数据的时候,会将数据拷贝到AudioALSACaptureDataClient的环形buffer中。
    所以这样即使有多个AudioStreamIn,但每个AudioStreamIn实例中有各自的环形buffer,从硬件来的数据会扔到各自的环形buffer中,从而互不影响。

http://www.ppmy.cn/news/494756.html

相关文章

深入理解audio 系统

本章主要内容 详细分析AudioTrack。 详细分析AudioFlinger。 详细分析AudioPolicyService。本章涉及的源代码文件名及位置下面是本章分析的源码文件名及其位置。 AudioTrack.javaframework/base/media/java/com/android/media/AudioTrack.java android_media_track.cppframewor…

html audio加载卡顿,audio 设置了currentTime后为什么会卡顿?

代码如下: methods:{ editprogress(value){ this.demoSlidervalue; this.$store.commit(editProgress,this.demoSlider) } } editProgress(state,progressValue){ const playerBardocument.getElementById("playerBar"); let currentTimeplayerBar.durati…

linux pulseaudio卸载,解决Ubuntu 9.04 下 PulseAudio声音故障

升级系统到Ubuntu 9.04之后,发现系统没声音了,pulseaudio和alsa都不可用,只有oss还能用。 参考了Ubuntu 8.04/8.10 系统无声、音频独占的解决方法解决了这个问题,只是按照文中给出的办法是把pulseaudio干掉,之用alsa,貌似照做一遍之后pulseaudio和alsa都恢复了正常。 做法…

Android audio介绍

转自 https://www.cnblogs.com/hzl6255/p/12173595.html 阅读目录 1. 架构2. Audio HAL3. Native Audio4. Java Audio 开始这篇文章之前&#xff0c;需要先了解<Linux音频编程> 回到顶部 1. 架构 在Android中&#xff0c;audio以分层的方式实现&#xff0c;从上到下…

USB audio调试

androidstudio打印的信息有如下&#xff1a; 07-12 08:27:17.660 2284-2284/? I/AudioFlinger: loadHwModule() Loaded a2dp audio interface from A2DP Audio HW HAL (audio) handle 7 07-12 08:27:17.660 2284-2284/? I/AudioFlinger: loadHwModule() Loaded usb audio int…

Audio Unit

Audio Unit 推荐先阅读Audio Unit Hosting Guide for iOS&#xff0c;部分翻译的文章可参考Audio Unit 基础 Audio Unit在框架中位置 Audio Unit提供了音频快速的模块化处理&#xff0c;在以下的场景中更适合使用AudioUnit&#xff0c;而不是更高层次的音频框架&#xff1a…

Android Qcom Audio入门学习

总结&#xff1a; Android Audio不简单呀&#xff0c;一个人摸索入门不容易的&#xff0c;研究了一段时间&#xff0c;感觉还不是很懂&#xff0c;但以下的知识对入门还是有帮助的。 Audio架构中的名词 FE(Front End) 提供pcm的设备信息&#xff0c;将数据从用户空间传输到音…

android base64.encode 参数,Android Base64音频文件编码/解码(Android Base64 Audio File Encode / Decode)...

Android Base64音频文件编码/解码(Android Base64 Audio File Encode / Decode) 这样做:我目前正在录制语音并将其保存为sdCard中的文件,该文件在MediaPlayer中运行良好。 我想要什么:当我编码这个文件到Base64并发送到服务器,一切都很好。 但是,当我将Base64字符串解码为…