当前位置: 首页 > ai >正文

Android音频学习(十四)——加载音频设备

1.加载流程         

在之前的章节中有提到,在Android系统启动时会启动两个服务,AudioFlinger和AudioPolicyService, 在AudioPolicyService初始化时,调用createAudioPolicyManger创建AudioPolicyManager以及进行初始化操作,总体流程如下:

loadConfig()功能是分析加载音频配置文件audio_policy_config.xml文件,在第十二节有详细的介绍。

apm->initialize中的加载Engine流程在第十三章有详细的介绍,这节我们主要分析onNewAudioModulesAvailableInt中一个重要的流程——加载硬件设备,调用流程如下:

af->loadHwModule调用到audioFlinger服务中的loadHwModule函数,然后再调用到mDevicesFactoryHal->openDevice, loadHwModule最终的目标是openDevice。

具体来说,loadHwModule加载的是实现了audio_hw_device_t结构体的动态共享库(.so文件)。每个硬件模块代表一种音频设备类型,例如:

- primary:主音频设备(通常对应设备内置的扬声器、听筒、麦克风等)

- a2dp:蓝牙A2DP设备

- usb:USB音频设备

- remote_submix:用于模拟音频输出/输入,常用于Wifi Display或Android模拟器

      在解析配置文件(audio_policy_configuration.xml)时,会为每个<module>标签创建一个HwModule对象,并指定其名称(如"primary")和HAL版本。然后,在初始化过程中,APM会调用loadHwModule来加载对应的HAL库。举个例子:假设配置文件中有一个模块名为"primary",那么APM会尝试加载名为"audio.primary.<device>.so"的库,其中<device>是设备名称(由ro.product.board(这个值代表cpu型号)等属性决定)。

例如,在Pixel设备上,可能会加载"audio.primary.sailfish.so"。具体过程如下:

(1) APM在初始化时(loadConfig)解析配置文件,创建HwModule对象。

(2)当调用loadHwModule时,会通过HAL的hw_get_module_by_class()函数利用HAL层注册信息id和name,获取相应的模块函数根据模块名,主要用于id相同、name不同,即获取相同功能但厂家不同的硬件库。如"AUDIO_HARDWARE_MODULE_ID_PRIMARY"即"primary",获取对应的HAL模块。

3. 然后调用audio_hw_device_open找到对应的open函数打开该模块,得到audio_hw_device_t结构体,用于后续操作(如打开音频流)。

例如,加载的音频库有:

- 主音频模块:/vendor/lib/hw/audio.primary.sdm660.so(qcom)

- 蓝牙A2DP模块:/vendor/lib/hw/audio.a2dp.default.so

所以,loadHwModule加载的是音频硬件抽象层(HAL)的模块,这些模块以动态库的形式存在,并实现了音频硬件的操作接口(如打开/关闭流、设置参数等)。

2.加载内容

(1) 硬件模块对象

在加载音频配置文件时创建 HwModule 对象,包含:

  • HAL 接口audio_hw_device_t 结构体指针

  • 设备描述DeviceDescriptor 集合(扬声器/麦克风等)

  • I/O 能力IOProfile 列表(输入/输出端口配置)

  • 路由策略AudioRoute 拓扑关系

(2)HAL 动态库

实际加载的共享库文件,命名规则:

# 示例路径
/vendor/lib/hw/audio.primary.${platform}.so
# 如高通平台
/vendor/lib/hw/audio.primary.msm8998.so

3. HAL层源码示例

// audio.primary.msm8998.c
static struct hw_module_methods_t hal_module_methods = {.open = adev_open
};struct audio_module HAL_MODULE_INFO_SYM = {.common = {.tag = HARDWARE_MODULE_TAG,.version_major = 7,.id = AUDIO_HARDWARE_MODULE_ID,.name = "QCOM Primary Audio HAL",.methods = &hal_module_methods,}
};static int adev_open(const hw_module_t* module, const char* name,hw_device_t** device) {struct primary_audio_dev *adev;adev = calloc(1, sizeof(struct primary_audio_dev));// 填充HAL操作函数adev->device.common.close = adev_close;adev->device.init_check = adev_init_check;adev->device.set_voice_volume = adev_set_voice_volume;// ...其他音频操作函数*device = &adev->device.common;return 0;
}

4. 调试技巧

(1)检查加载状态

adb shell dumpsys media.audio_policy | grep "HW Modules"

输出示例:

HW Modules:
- Module primary: handle 42
- Output profiles: primary output
- Devices: Speaker (AUDIO_DEVICE_OUT_SPEAKER)

(2)查看 HAL 版本

// 在HAL实现中打印版本
ALOGI("HAL version: %d.%d", 
module->halVersionMajor, 
module->halVersionMinor);

(3)加载失败排查

常见错误日志

loadHwModule() error 0xfffffffe opening HAL "a2dp"

排查步骤:

  1. 检查 /vendor/lib/hw/audio.a2dp.default.so 是否存在

  2. 验证 SELinux 权限:avc: denied 相关日志

  3. 确认 HAL 符号导出:nm -D audio.primary.so | grep HAL_MODULE_INFO_SYM

总结:

loadHwModule 是 Android 音频系统的核心初始化函数,负责加载音频硬件抽象层(HAL)的模块实现。它建立 AudioPolicyService 与底层硬件的桥梁,将配置文件(audio_policy_config.xml)中的 标签<module>定义转化为可操作的硬件对象,加载的是音频硬件模块(HAL实现),每个模块对应一种音频设备类型,以动态库的形式存在,负责与底层音频硬件交互。

http://www.xdnf.cn/news/18349.html

相关文章:

  • 什么是Jmeter?Jmeter使用的原理步骤是什么?
  • day38-HTTP
  • 第41周——人脸图像生成
  • 携程旅游的 AI 网关落地实践
  • 计算机网络技术-第七章
  • Ingress控制器深度解析:Nginx与Traefik实战指南
  • Java的运行时数据区
  • ICMP 协议分析
  • 从零到一:RAGFlow 本地部署全攻略
  • JeeSite V5.13.0 发布,升级 Spring Boot 3.5,Cloud 2025,AI 1.0,Vite 7
  • 数据结构-HashMap
  • Vue2+Vue3前端开发_Day5
  • 【neo4j】安装使用教程
  • lesson44:Redis 数据库全解析:从数据类型到高级应用
  • 计算机网络:网络基础、TCP编程
  • 如何自定义一个SpringBoot Starter
  • 密码管理中明文密码与空密码的危害与预防
  • 继承(Inheritance)
  • 机器学习集成算法与K-means聚类
  • Pytest 插件怎么写:从0开发一个你自己的插件
  • 14. 多线程(进阶1) --- 常见的锁策略和锁的特性
  • 【Protues仿真】基于AT89C52单片机的数码管驱动事例
  • Windows下,将本地视频转化成rtsp推流的方法
  • strcasecmp函数详解
  • AI模型部署 - 大语言模型(LLM)部署技术与框架
  • js来比较两个对象内容有误差异
  • mysql数据库学习
  • 想在手机上操作服务器?cpolar让WaveTerminal终端随身携带,效率倍增
  • 【Springboot进阶】Java切面编程对性能的影响深度分析
  • 【Ruoyi解密-02.登录流程:】登录-找密码不抓瞎