【车载audio开发】【Qualcomm PAL 详解 6】【PAL 总体架构与模块交互指南】

PAL 总体架构与模块交互指南

1. 宏观架构:PAL 的世界观

欢迎来到 Qualcomm PAL (Platform Audio Layer) 的世界。为了更好地理解,我们继续使用餐厅的比喻:

  • Android HAL (Client) : 顾客。负责点菜(提需求)。
  • Stream (流) : 订单。记录了顾客要什么(听歌、打电话、录音),并负责整个服务流程的进度。
  • Session (会话) : 厨房。负责真正的制作(DSP 音频处理、混音、重采样)。
  • Device (设备) : 餐桌/外卖窗口。最终呈现声音的地方(喇叭、耳机)。
  • ResourceManager (RM) : 大堂经理。统筹全局,安排哪个订单去哪个厨房,送到哪张桌子,处理突发情况(插队、换桌)。

2. 核心交互流程图

  1. pal_stream_open 2. 请求资源 3. 分配 Device 4. 创建 Session 5. pal_stream_start 6. start() 7. 冲突检查 & 并发控制 8. start() 9. 打开硬件通路(Mixer) 10. prepare() & start() 11. 配置 DSP Graph 12. pal_stream_write(数据) 13. write() 14. pcm_write Android Audio HAL
    Stream(订单)
    ResourceManager(经理)
    Device(餐桌)
    Session(厨房)
    Audio Hardware
    DSP
    Kernel / DSP Driver

3. 深度解析:一次完整的音频播放

让我们跟踪一次"播放音乐"的全过程,看看各模块如何协作。

第一阶段:创建与建立连接 (Open)

  1. Client : 调用 pal_stream_open(STREAM_LOW_LATENCY, DEVICE_SPEAKER)
  2. Stream : 创建 StreamPCM 对象。
  3. Stream -> RM :
    • 调用 rm->getDeviceConfig():经理,Speaker 需要什么参数?(RM 查 XML 返回:48kHz, 24bit)。
    • 调用 Session::makeSession(rm):创建一个能处理 PCM 的厨房(通常是 SessionAlsaPcm)。
    • 调用 rm->registerStream():经理,记下来,现在有一单音乐要播放。
  4. 关联 : Stream 内部保存了 SessionDevice 的指针。连接建立完毕。

第二阶段:启动与资源分配 (Start)

  1. Client : 调用 pal_stream_start()
  2. Stream -> RM: 经理,我要开始播了,可以吗?
  3. RM :
    • 检查并发:现在有电话吗?有语音唤醒吗?(如果有,RM 会通知其他 Stream 暂停或由 DSP 混音)。
    • 增加引用计数:Speaker 的使用人数 +1。
  4. Stream -> Device : device->start()
    • Device : 下发 Mixer Controls (如 "SLIMBUS_0_RX Audio Mixer MultiMedia1"),打通物理通路。
  5. Stream -> Session : session->prepare() -> session->start()
    • Session :
      • 从 RM 申请 FrontEnd ID (比如 pcm0p)。
      • 从 Device 知道 BackEnd Name (比如 QUAT_TDM_RX_0)。
      • 关键动作: 配置 DSP,告诉它"把 PCM0 的数据处理完后,送到 TDM_RX_0 接口"。
      • 调用 pcm_start 激活内核节点。

第三阶段:数据传输 (Running)

  1. Client : 循环调用 pal_stream_write(buffer)
  2. Stream: 不做处理,直接透传。
  3. Session : 调用 pcm_write (TinyALSA) 将数据写入共享内存或内核缓冲区。
  4. DSP/Kernel: 读取数据 -> 音效处理 -> 发送给 Codec -> 喇叭发声。

第四阶段:动态设备切换 (Device Switch)

场景:插耳机

  1. RM : 收到 ConnectionStateChange 事件。
  2. RM : 扫描所有活跃 Stream,发现 MusicStream 在用 Speaker
  3. RM -> Stream : 强制切换!
    • 调用 stream->disconnectStreamDevice(Speaker)
    • 调用 stream->connectStreamDevice(Headphone)
  4. Stream :
    • 暂停 Session 数据写入(防止杂音)。
    • Device(Speaker)->stop()
    • Device(Headphone)->start()
    • Session 更新路由配置 (告诉 DSP 换出口)。
    • 恢复 Session 数据写入。

4. 模块间接口汇总

调用方 被调用方 关键接口 目的
Stream RM registerStream 注册自己,纳入管理
Stream RM getDeviceConfig 获取设备能力
Stream Session open, start, write 控制 DSP 管道
Stream Device start, stop 控制物理硬件开关
RM Stream switchDevice 通知流进行设备切换
Session RM allocateFrontEndIds 申请 PCM 设备号
Session RM getVirtualAudioMixer 获取 Mixer 句柄

5. 常见问题 (FAQ)

  • Q: 为什么要分 Stream 和 Session?
    • A: 解耦。Stream 关注业务(播放/录音/通话),Session 关注底层实现(TinyALSA/GSL/AGM)。如果高通换了底层架构(比如从 ALSA 换到 GSL),只需要重写 Session,Stream 层的业务逻辑不用动。
  • Q: ResourceManager 的 XML 到底决定了什么?
    • A: 它决定了"静态路由图"。比如:哪个流类型对应哪种 Session 模式?哪个 Device 对应哪个 Backend 接口?所有的硬件拓扑都在 XML 里。
  • Q: 为什么会有并发问题?
    • A: 硬件资源是有限的。比如 DSP 里的回声消除 (EC) 模块可能只有一个,或者某个 Backend 接口同一时间只能跑一个采样率。RM 的作用就是协调这些冲突。

6. 学习路线建议

  1. 入门 : 先看 Stream模块介绍,理解业务流程。
  2. 进阶 : 结合 ResourceManager 模块介绍 和 XML 文件,理解系统是如何配置起来的。
  3. 深入 : 阅读 Session 模块介绍Device 模块介绍 ,理解数据到底是怎么送到底层的。
  4. 实战 : 尝试在 resourcemanager.xml 中新增一个 Device,并在代码中打通它。
相关推荐
奔跑吧 android4 小时前
【车载audio开发】【Qualcomm PAL 详解 4】【Session 模块 介绍】
audio·aosp·高通·车载音频
千里马学框架1 天前
跟着google官方文档学习车载音频Car audio configuration
学习·configuration·音视频·aaos·安卓framework开发·audio·车机
不会Android的潘潘2 天前
adb指令扩展方案
android·adb·aosp
安卓兼职framework应用工程师1 个月前
Android 10.0 按键智能机按键连续响两次的异常处理
android·audio·audioservice·按键音·按键声音
Just_Paranoid1 个月前
【AOSP】Android Dump 信息快速定位方法
android·adb·framework·service·aosp·dumpsys
民乐团扒谱机1 个月前
【微实验】仿AU音频编辑器开发实践:从零构建音频可视化工具
算法·c#·仿真·audio·fft·频谱
林鸿群1 个月前
Android AOSP 15 源码Ubuntu编译
android·linux·ubuntu·aosp
Calebbbbb2 个月前
AOSP环境配置和编译
安卓·安全架构·aosp
毛豆的毛豆Y2 个月前
AOSP 14 Launcher3 - Taskbar UI 组成
aosp·launcher3·android14