Android音频学习(十九)——音频HAL层简介
1. 功能
1.1设备管理
- 控制音频设备(如扬声器、耳机、蓝牙)的打开/关闭、参数配置(采样率、声道数)。
- 处理设备状态变化(如耳机插入检测)。
1.2音频数据传输
- 提供 PCM 数据的读写接口(audio_stream_out 和 audio_stream_in)。
- 管理 DMA 缓冲区,实现硬件与系统之间的高效数据传输。
1.3音效处理
- 支持硬件加速的音效(如杜比全景声、均衡器)。
- 通过 Effects HAL 接口应用音效链。
1.4低延迟支持
实现 AAudio 的 mmap(内存映射)接口,支持零拷贝低延迟播放/录音。
1.5策略执行
响应 AudioPolicyManager 的路由决策,切换输出/输入设备。
2. 处理流程
以下以 音频播放 为例,展示 Audio HAL 在完整流程中的角色:
2.1初始化阶段
- 加载 HAL 模块:
AudioFlinger 通过 hw_get_module(AUDIO_HARDWARE_MODULE_ID) 加载厂商实现的 HAL 动态库(如 audio.primary.[platform].so)。 - 创建设备实例:
调用 audio_hw_device_open(),返回 audio_hw_device 结构体,包含设备操作函数指针。
2.2配置音频流
- 打开输出流:
调用 open_output_stream(),创建 audio_stream_out 对象,初始化 PCM 参数(采样率、位深、声道数)。 - 设置硬件参数:
通过 set_parameters() 配置设备(如 sampling_rate=48000)。
2.3数据传输阶段
- 写入数据:
AudioFlinger 调用 audio_stream_out->write(),将混合后的 PCM 数据传递给 HAL。 - 硬件交互:
HAL 将数据写入 DMA 缓冲区,触发硬件中断驱动音频播放。
2.4设备切换与释放
- 写入数据:
AudioFlinger 调用 audio_stream_out->write(),将混合后的 PCM 数据传递给 HAL。 - 硬件交互:
HAL 将数据写入 DMA 缓冲区,触发硬件中断驱动音频播放。
3. 关键代码
3.1HAL接口定义
核心结构体
audio_hw_device,定义设备级操作接口,如设置参数,打开/关闭输出/输入流等,结构体定义路径:libhardware/include/hardware/audio.h
struct audio_hw_device {
....../* set/get global audio parameters */int (*set_parameters)(struct audio_hw_device *dev, const char *kv_pairs);/** Returns a pointer to a heap allocated string. The caller is responsible* for freeing the memory for it using free().*/char * (*get_parameters)(const struct audio_hw_device *dev,const char *keys);
......int (*open_output_stream)(struct audio_hw_device *dev,audio_io_handle_t handle,audio_devices_t devices,audio_output_flags_t flags,struct audio_config *config,struct audio_stream_out **stream_out,const char *address);void (*close_output_stream)(struct audio_hw_device *dev,struct audio_stream_out* stream_out);/** This method creates and opens the audio hardware input stream */int (*open_input_stream)(struct audio_hw_device *dev,audio_io_handle_t handle,audio_devices_t devices,struct audio_config *config,struct audio_stream_in **stream_in,audio_input_flags_t flags,const char *address,audio_source_t source);void (*close_input_stream)(struct audio_hw_device *dev,struct audio_stream_in *stream_in);
......}
3.2厂商接口定义
以高通为例,代码路径:hardware/qcom/audio/hal/audio_hw.c,部分代码实现如下:
static int adev_open_output_stream(struct audio_hw_device *dev,audio_io_handle_t handle,audio_devices_t devices,audio_output_flags_t flags,struct audio_config *config,struct audio_stream_out **stream_out,const char *address __unused)
{
......out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;out->config = pcm_config_voip;out->config.rate = out->sample_rate;out->config.format = pcm_format_from_audio_format(out->format);buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,out->sample_rate,out->format,out->config.channels,false /*is_low_latency*/);frame_size = audio_bytes_per_sample(out->format) * out->config.channels;out->config.period_size = buffer_size / frame_size;out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;out->af_period_multiplier = 1;
......
}
该函数主要是设置硬件参数。
3.3HAL与AudioFlinger的交互
在之前得章节中已经介绍过,在此简单的回顾下:
- HAL 模块加载
AudioFlinger 在初始化时通过 loadHwModule() 加载 HAL,
代码路径:
frameworks/av/services/audioflinger/AudioFlinger.cpp
sp<DeviceHalInterface> dev = mDevicesFactoryHal->openDevice(name.c_str());
- 数据写入调用链AudioFlinger::PlaybackThread::threadLoop_write() → HAL::AudioStreamOut::write()。
4.HAL版本与兼容性
- 传统 HAL(Legacy HAL)
- 基于 hw_module_t 和函数指针,Android 7.0 及之前版本使用。
- 接口定义在 audio.h 和 audio_policy.h。
- HIDL HAL(Android 8.0+)
- 使用 HIDL(Hal Interface Definition Language)定义接口,提升稳定性和兼容性。
- 接口文件示例:
hardware/interfaces/audio/core/4.0/IDevicesFactory.hal
- AIDL HAL(Android 12+)
- 进一步升级为 AIDL(Android Interface Definition Language),支持更灵活的扩展。
5.调试与工具
5.1查看HAL日志
adb logcat | grep audio_hw
5.2参数查看与修改
adb shell tinymix -D 0 # 查看 Mixer 控件
adb shell tinypcminfo # 查看 PCM 设备信息
5.3直接测试硬件
adb shell tinyplay test.wav # 播放音频文件
adb shell tinycap record.wav # 录制音频
6.常见问题与解决
6.1无声音或杂音
- 检查 HAL 配置:确认 PCM 格式(采样率、位深)与硬件匹配。
- 调试 DMA 传输:通过 tinymix 确认数据路径是否正常。
6.2高延迟
- 启用低延迟模式:配置 AUDIO_OUTPUT_FLAG_FAST 标志,使用 AAudio API
- 优化缓冲区大小:确保 HAL 缓冲区与 AudioFlinger 配置一致。
6.3设备切换失败
- 验证路由策略:检查 set_parameters() 是否正确处理设备 ID。
- HAL 日志分析:确认设备打开/关闭流程无错误。
7.总结
- 功能定位:Audio HAL 是 Android 音频系统的硬件桥梁,标准化硬件操作,隔离厂商差异。
- 处理流程:从初始化、配置、数据传输到资源释放,贯穿音频生命周期。
- 关键代码:以 audio_hw_device 和 audio_stream_out 为核心的结构体与接口实现。
- 调试要点:结合日志、系统工具(如 tinymix)和硬件验证,定位 HAL 层问题。
- 理解 Audio HAL 的实现机制,有助于优化音频性能(如低延迟)、解决兼容性问题,或为特定硬件定制音频功能。