这篇写什么?
Aetheryal Multi-Room 要把 本机正在播的系统音频 PCM 送到 TV 侧协议栈做多房间分发。整条链路跨 TVUI、常驻 TVBG、AIDL 服务、Dolby MS12 与 HAL 桥接库,最容易踩坑的是:没 ConnectToSink 就永远收不到回调。
一句话:
TVUI 拉起 TVBG → registerCallback → ConnectToSink(开门控)
→ 系统播放进 MS12 → stereo_pcm_output → aetheryal_audio_write
→ platformWritePcmAudio → onPCMAudioDataReady → Aetheryal native
当前已验证:HAL → AIDL Service → TVBG callback 通路可用,且 dump 文件可正确还原播放音频。
代码时序图
整体架构(10 步)
- tvuiapp 启动后拉起 tvbackground(或等价常驻进程)。
- tvbackground 通过 Binder 获取
IAetheryalAudio/default。 - tvbackground 调用
registerCallback(IAetheryalAudioCallback)。 - (必须写进集成说明) 再调用
aetheryalConnectToSinkStereo/aetheryalConnectToSinkMultichannel,使服务端mAudioDataEnabled = true。
否则platformWritePcmAudio会门控,日志常见pcm gated(disconnected),不会调用onPCMAudioDataReady。
调试可用:vendor.media.audiohal.aetheryal.force_enable=1绕过门控。 - 系统播放音频时,经 MS12 管线:
- 生产者侧:从
out_write_new等进入混音 / MS12 输入,经dolby_ms12_system_process等处理; - 消费者侧:MS12 通过回调产出 PCM,经
stereo_pcm_output→ms12_output_master→ … → 最终 ALSA / 硬件。
- 生产者侧:从
- 在
#ifdef ENABLE_AETHERYAL_AUDIO_BRIDGE下,audio_hw_ms12_v2.c::stereo_pcm_output()末尾调用aetheryal_audio_write(...)(与ms12_info中的格式 / 声道一致,常见 48k / 2ch / 16bit)。 - libaetheryalaudiohal 将 PCM 打成
byte[],调用platformWritePcmAudio(...)。 AetheryalAudioAidlService::platformWritePcmAudio在门控允许时调用mCallback->onPCMAudioDataReady(...)。- tvbackground 在回调中收到 PCM → Aetheryal native / 协议栈。
- 若
vendor.media.audiohal.aetheryal.dump=1,桥接库将同一份 PCM 追加到/data/vendor/audiohal/aetheryal_bridge_in.pcm。
关键模块
| 模块 | 职责 |
|---|---|
IAetheryalAudio.aidl |
控制接口 + platformWritePcmAudio(HAL 注入的服务端入口) |
AetheryalAudioAidlService |
维护 register / unregister、连接门控(mAudioDataEnabled / force_enable)、把 PCM 转发到 onPCMAudioDataReady |
audio_hw_ms12_v2.c::stereo_pcm_output() |
音频消费者:MS12 解码后的立体声 PCM 路径;宏内调用 aetheryal_audio_write |
audio_hw.c::out_write_new() |
音频生产者侧写入口 |
libaetheryalaudiohal |
HAL ↔ AIDL 桥接(C 接口 aetheryal_audio_write、Binder 调 platformWritePcmAudio),并负责可控 dump |
文字时序(对照图)
[TVUI App]
│ (start/bind)
▼
[TVBG Service]
│ 1) getService("…IAetheryalAudio/default")
│ 2) registerCallback(IAetheryalAudioCallback)
│ 3) aetheryalConnectToSinkStereo / Multichannel ← 打开数据门控
▼
[AetheryalAudioAidlService]
│ (holds mCallback, mAudioDataEnabled 或调试 force_enable)
│
│ <audio playback ongoing>
│
[AudioFlinger] → [out_write_new → … → MS12 生产者路径]
│
│ dolby_ms12_system_process / threadloop …
▼
[MS12 消费者:ms12_output → stereo_pcm_output]
│
│ 立体声 PCM(sr/ch/bit 以 ms12_info / 实际 buffer 为准)
▼
[stereo_pcm_output()] (#ifdef ENABLE_AETHERYAL_AUDIO_BRIDGE)
▼
[aetheryal_audio_write()] (libaetheryalaudiohal)
│
├─(optional) dump if dump=1
│ → /data/vendor/audiohal/aetheryal_bridge_in.pcm
▼
platformWritePcmAudio(timestamp, sr, ch, bit, data)
▼
[AetheryalAudioAidlService::platformWritePcmAudio]
▼
mCallback->onPCMAudioDataReady(...)
▼
[TVBG callback] → [Aetheryal native / audio pipeline]
调试属性
| 属性 | 作用 |
|---|---|
vendor.media.audiohal.aetheryal.log=1 |
HAL 侧 bridge stats、服务侧统计日志 |
vendor.media.audiohal.aetheryal.dump=1 |
落盘 /data/vendor/audiohal/aetheryal_bridge_in.pcm |
vendor.media.audiohal.aetheryal.force_enable=1 |
调试时绕过 mAudioDataEnabled 门控 |
集成验收(必看)
正常集成: 应看到 pcm stats:(或等价非 gated 路径),不应长期只有 pcm gated(disconnected)。
| 现象 | 常见原因 | 怎么处理 |
|---|---|---|
只有 pcm gated(disconnected) |
没调 ConnectToSink,或连接失败 | 确认 stereo / multichannel 任一连接成功;或临时 force_enable=1 |
| 有 write、无 callback | 未 registerCallback,或 callback 已死 |
检查 TVBG 注册与进程存活 |
| dump 文件无声 / 不对 | 格式与播放不一致,或未开 dump | 开 dump=1,用 48k/2ch/16bit 等实际参数还原 |
| 宏未编译进 HAL | 未开 ENABLE_AETHERYAL_AUDIO_BRIDGE |
确认 stereo_pcm_output 末尾能进 aetheryal_audio_write |
一句话记住
先 ConnectToSink 开门控,再指望 onPCMAudioDataReady;PCM 从 MS12 的 stereo_pcm_output 抄一份出来,经 HAL 桥进 AIDL,最后进 TVBG。
评论
还没有评论,来做第一个吧
赞同、吐槽、提问都行,评论区开放