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

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.dtcms.com/a/344128.html

相关文章:

  • Mysql InnoDB 底层架构设计、功能、原理、源码系列合集【四、事务引擎核心 - MVCC与锁机制】
  • prompt提示词2
  • 【思考】什么是服务器?什么是服务?什么是部署?
  • MongoDB 完整指南
  • 机器人爆发、汽车换代,速腾聚创开始讲新故事
  • 线性规划在数学建模中的应用
  • MyCAT高可用
  • Go语言实战案例-使用SQLite实现本地存储
  • Codeforces1043 A至F 题解
  • 【基础-判断】合理的动效可以帮助引导、取悦用户,减少等待时间,更能增加产品识别度,让用户舒适的的使用产品
  • 【序列晋升】12 Spring Boot 约定优于配置
  • 基于 Docker 的高可用 WordPress 集群部署:分布式 Nginx + Keepalived、MySQL 主从复制与 ProxySQL 读写分离
  • 行缓存(line buffer)在图像卷积中的工作方式
  • 【iOS】YYModel第三方库源码
  • 飞机起落架减震筒的深孔检测方法探究 - 激光频率梳 3D 轮廓检测
  • 用户登录Token缓存Redis实践:提升SpringBoot应用性能
  • Flutter学习笔记(七)---主题
  • 嵌入式学习day34-网络-tcp/udp
  • 如何判断是否应该为了一个小功能而引入一个大体积的库
  • 配电网重构优化:以减小网损为目标的智能算法实现
  • GitLab CI :深入剖析 gl-sbom-report.cdx.json 解码“数字身份证”
  • 云蝠智能 VoiceAgent:重构售后服务场景
  • 岭回归算法拉索回归
  • LeeCode 40.组合总和II
  • 数据结构之深入探索归并排序
  • 西门子S7-1200系列基本组态常见问题
  • 【C++】多态(详解)
  • Debezium监听MySQL binlog并实现有状态重启
  • 工业环境电缆火灾预防的分布式光纤在线监测
  • 质谱数据解读