【车载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,并在代码中打通它。
相关推荐
消失的旧时光-19438 天前
Android 系统层扫盲 09:AMS、ATMS、WMS、PMS 到底分别管什么?
android·wms·pms·ams·aosp·atms
千里马-horse9 天前
附录 C:AOSP 不在公共框架 API 中采用 Kotlin 的原因
aosp
千里马-horse11 天前
65 定制 Android ROM
aosp
千里马-horse11 天前
第 66 章:在 Android 上运行 Windows 游戏
android·aosp
消失的旧时光-194313 天前
Android 系统层扫盲 05:Android 开机后发生了什么?从 Bootloader 到 Launcher
android·zygote·fork·aosp·cow
千里马-horse13 天前
第 61 章:设备策略与 Android 企业版
android·aosp
千里马-horse14 天前
第 60 章 模拟器架构
架构·aosp
熊猫钓鱼>_>14 天前
用 OHAudioSuite 空间渲染节点搭一座「3D 有声博物馆」——从三种模式到 FreeBuds 头追的实战记录
c++·3d·ai·harmonyos·arkts·audio·ohaudiosuite
千里马-horse16 天前
第 55 章:OTA 更新
aosp
消失的旧时光-194317 天前
Android 系统层扫盲 03:第一次看 AOSP 源码目录,frameworks、system、packages、hardware 都是干什么的?
aosp