- 初始化工程
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容器的索引。 - 加载硬件过程
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 - 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实例保存起来。 - 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类型的实例。 - 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中,从而互不影响。