此篇博文是上一篇文章 《Android 7.1 系统裁剪、定制化实践 snd-aloop 内录音》 的延续. 链接如下:
早期验证 ALSA 声卡内录音的功能,是在 android7.0 系统上,待向 android8.1 系统上移植时,我尴尬了 -
因为硬件驱动 HIDL 的接口在 android8.0 版本的引入,致使我只能在梳理声卡驱动启动过程以及安卓系统调用过程,
因此就有了这篇文章的产生,也分享出来、供有此需求朋友参考。
android_build 是 imx8mq的安卓源码根
android8.1 与 adroid7 的 audio_policy_configuration.xml 配置文件,属于兼容。
android8.0 系统驱动采用 HIDL 方式,驱动作为独立服务在系统中存在,安卓系统调用驱动是采用 STUB 服务绑定
方式, 获取驱动的代理句柄、来使用驱动相关的api接口功能。
声卡 hidl 实现相关代码路径及内容如下
首先看 Android.mk 内容如下:
此部分是声卡服务程序 service.cpp 的编译文件,此部分是实现 AUDIO_HARDWARE_MODULE_ID_STUB 模式,
即声卡 HIDL 绑定模式代码,如果采用直通模式、兼容以前版本声卡模式,是如何实现的呢?
我们先看一下 DevicesFactory.cpp 和 DevicesFactory.h 源码,内容如下:
@ aosp8.1/hardware/interfaces/audio/2.0/default/DevicesFactory.h
文件中开启 audio 的 passthrough 模式,
extern “C” IDevicesFactory* HIDL_FETCH_IDevicesFactory(const char* name);
此函数导出到 C 语音空间,可以通过c语音调用此函数;
函数实现如下:
@ aosp8.1/hardware/interfaces/audio/2.0/default/DevicesFactory.cpp
函数 HIDL_FETCH_IDevicesFactory() 只是简单创建声卡设备对象,也由此开启声卡驱动加载和应用过程。
由头文件看到,对象构建时调用的函数是 openDevice() 函数,兼容早期版本声卡驱动是通过 deviceToString()
函数,把设备转化成对应驱动名称,然后通过名称获取不同声卡驱动实例、来使用驱动.
如:AUDIO_HARDWARE_MODULE_ID_PRIMARY、AUDIO_HARDWARE_MODULE_ID_A2DP、AUDIO_HARDWARE_MODULE_ID_USB
、AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX 和 AUDIO_HARDWARE_MODULE_ID_STUB,早期版本是PRIMARY、A2DP、
USB、REMOTE_SUBMIX 几类声卡模式. STUB 是 android8.0 扩展模式,通过此方法实现两个版本驱动兼容。
前面博文中有描述安卓系统声卡 audioFlinger 相关文章,参考链接.
简单回顾一下:
安卓系统在启动时将启动 audioService 服务,该服务会创建
audioFlinger、AudioPolicyService、SoundTriggerHwService和IPCThreadState线程池线程,由此处开始引入 audioFlinger 启动.
接下来我们走读一下这块代码。
@aosp8.1/frameworks/av/services/audioflinger/AudioFlinger.cpp 和 .h 文件,调用如下接口
3.2.1). stub hal 模式
此接口内容如下:
@ aosp8.1/frameworks/av/media/libaudiohal/DevicesFactoryHalHidl.cpp 和 .h 文件.
STUB HAL模式 DevicesFactoryHalHidl 继承 DevicesFactoryHalInterface 类,由此我们基本可以推断应该还有一个
早期版本 HAL 类也继承 DevicesFactoryHalInterface 类,以此方法实现兼容两个版本驱动的目的。
DevicesFactoryHalHidl构建方法如下:
3.2.2). lagecy hal 模式 ( PASSTHROUGH模式)
@aosp8.1/frameworks/av/media/libaudiohal/DevicesFactoryHalLocal.h
@aosp8.1/frameworks/av/media/libaudiohal/DevicesFactoryHalHybrid.h
@aosp8.1/frameworks/av/media/libaudiohal/DevicesFactoryHalHybrid.cpp
至此,我们做简短总结,由上面几段源码可以看出,安卓声卡驱动版本兼容、是通过 DevicesFactoryHalInterface 类的智能指针,
指向不同声卡驱动实例实现。此处代码逻辑关系笔者未详细梳理、谨通过基本特征进行类推。
3.3). DevicesFactoryHalInterface 类
@aosp8.1/frameworks/av/media/libaudiohal/include/media/audiohal/DevicesFactoryHalHidlInterface.h
此类再次继承基类 Refbase 类.
@aosp8.1/system/core/libutils/include/utils/Refbase.h
@aosp8.1/system/core/libutils/Refbase.cpp:
至此、我们把 audioflinger 启动和驱动匹配过程源码粗略走读一遍。
在 @ aosp8.1/hardware/libhardware/modules/ 路径中,有各种声卡模块驱动代码.
我们修改的是 audio.primary.${TARGET_BOARD_HARDWARE} 声卡驱动,在 AudioPolicyService 选择驱动中是首选与
TARGET_BOARD_HARDWARE 目标板匹配的声卡驱动,如果没有才会匹配 audio.primary.default 驱动。
把 android8.1 的alsa驱动移植后,编译内核烧入mek8q开发板中,通过实际录音验证,文章对HIDL接口驱动兼容方法,分析
基本是正确的。
android8.1 的驱动移植参考 hidl 参考