安卓audio 架构解析

audio_port_handle_t

• 定义:audio_port_handle_t标识音频设备(如扬声器、耳机)或虚拟端口(如远程 submix)。它在设备连接或策略路由时由AudioPolicyManager分配,例如通过setDeviceConnectionState()动态注册设备。

周期

audio_port_handle_t的生命周期,其周期可分为以下几个阶段:

  1. 生成阶段

    • 动态分配:当物理设备(如耳机、蓝牙设备)连接或虚拟设备(如远程submix)初始化时,AudioPolicyManager通过setDeviceConnectionState()动态分配唯一的audio_port_handle_t,并注册到系统可用设备列表(如mAvailableOutputDevices或mAvailableInputDevices)中。例如,USB声卡插入时会生成独立的标识符。

    • 静态预定义:部分内置设备(如扬声器)的audio_port_handle_t在系统启动时通过解析audio_policy_configuration.xml预生成,无需动态注册。

  2. 绑定与路由阶段

    • 策略路由选择:应用创建AudioTrack或AudioRecord时,AudioPolicyManager根据音频属性(如usage、contentType)从可用设备中选择目标设备,并返回其audio_port_handle_t。例如,媒体播放会选择扬声器,而通话则选择听筒。

    • 动态更新:设备状态变化(如拔出耳机)会触发路由更新,系统销毁原有绑定并重新分配audio_port_handle_t到新设备(如切换到扬声器)。此过程通过SessionRouteMap维护会话与设备的关联。

  3. 复用与共享

    • 多会话共享:同一设备的audio_port_handle_t可被多个音频会话复用。例如,多个AudioTrack输出到蓝牙设备时共享同一标识符,但各自维护独立会话ID。

    • 策略优先级调整:通过setPreferredDeviceForStrategy()等API,应用可指定策略的优先设备,系统动态更新audio_port_handle_t的绑定关系。

  4. 销毁阶段

    • 设备断开时释放:设备断开(如蓝牙关闭)或虚拟设备销毁时,AudioPolicyManager释放对应的audio_port_handle_t并清理路由。例如,USB声卡拔出后其标识符从可用设备列表中移除。

    • 资源回收:若设备长时间未重新连接,系统可能回收其audio_port_handle_t以避免标识符耗尽。

关键特点

• 唯一性与动态性:每个标识符在生命周期内全局唯一,但设备重连可能重新分配不同值。

• 策略依赖性:生命周期受AudioPolicyManager路由规则控制,与硬件状态和用户配置强相关。

AudioPatch

1.核心变量
  1. audio_patch 结构体:

    • num_sources - 源端数量

    • sources[] - 源端配置数组(可以是设备或混音端口)

    • num_sinks - 接收端数量

    • sinks[] - 接收端配置数组(可以是设备或混音端口)

  2. AudioPatch 类成员:

    • mPatch - 存储当前的音频补丁配置

    • mUid - 创建该补丁的用户ID

    • mHandle - 补丁的唯一标识符

    • mAfHandle - AudioFlinger 分配的补丁句柄

  3. 线程相关变量:

    • mAudioPatches - 存储所有音频补丁的集合

    • mPatchSinks - 输出设备描述

    • mPatchSources - 输入设备描述

2.核心函数
  1. 创建补丁:

    • createAudioPatch() - 创建新的音频路由补丁

    • sendCreateAudioPatchConfigEvent() - 发送创建补丁的配置事件

    • installPatch() - 实际安装补丁到系统中

  2. 释放补丁:

    • releaseAudioPatch() - 释放已存在的音频补丁

    • sendReleaseAudioPatchConfigEvent() - 发送释放补丁的配置事件

  3. 管理函数:

    • updateAudioProfiles() - 更新与补丁相关的音频配置

    • checkForNewParameter_l() - 检查补丁参数变化

    • getParameters() - 获取补丁参数

  4. 工具函数:

    • patchSinksToString() - 将补丁接收端转换为字符串

    • patchSourcesToString() - 将补丁源端转换为字符串

3.调用场景
  1. 设备连接/断开时:

    • 当音频设备连接或断开时,系统会创建或释放相应的音频补丁

    • 调用createAudioPatch()或releaseAudioPatch()

  2. 路由策略变化时:

    • 当音频策略要求改变路由时(如通话时切换到耳机)

    • 通过setParameters()触发补丁更新

  3. 动态策略应用时:

    • 应用请求特定路由(如远程submix)时

    • 使用sendCreateAudioPatchConfigEvent()通知音频系统

  4. 效果链管理时:

    • 当音频效果需要特定设备路由时

    • 通过补丁系统确保效果处理在正确的设备上

  5. 多设备输出时:

    • 需要同时输出到多个设备(如蓝牙和有线耳机)

    • 创建多接收端的补丁配置

4.关键流程
  1. 补丁创建流程:

    应用请求 -> AudioPolicyManager -> AudioFlinger -> ThreadBase::createAudioPatch()

    -> installPatch() -> HAL层实现

  2. 补丁释放流程:

    设备断开/策略变化 -> AudioPolicyManager -> AudioFlinger -> releaseAudioPatch()

    -> HAL层清理

  3. 参数更新流程:

    参数变化 -> checkForNewParameter_l() -> 必要时创建/释放补丁

相关推荐
极客先躯2 小时前
高级java每日一道面试题-2025年11月24日-容器与虚拟化题[Dockerj]-runc 的作用是什么?
java·oci 的命令行工具·最小可用·无守护进程·完全标准·创建容器的核心流程·runc 核心职责思维导图
用户60648767188962 小时前
AI 抢不走的技能:用 Claude API 构建自动化工作流实战
java
jinanwuhuaguo2 小时前
(第二十七篇)OpenClaw四月的演化风暴:OpenClaw 2026年4月全版本更新的文明级解读
大数据·人工智能·架构·kotlin·openclaw
James_WangA2 小时前
我给 AOI 设备装了一个 Agent,然后发现工具注册才是最难写的
架构·github
我命由我123452 小时前
Kotlin 开发 - lateinit 关键字
android·java·开发语言·kotlin·android studio·android-studio·android runtime
aXin_ya2 小时前
微服务第八天 Sentinel 四种分布式事务模式
java·数据库·微服务
James_WangA2 小时前
产线上跑 Agent:LLM 挂了不是 500 错误,是停线
架构·github
Halo_tjn2 小时前
Java Set集合相关知识点
java·开发语言·算法
Linsk2 小时前
Java和JavaScript的关系真是雷峰和雷峰塔的关系吗?
java·javascript·oracle
许彰午2 小时前
我手写了一个 Java 内存数据库(二):B+ 树的插入与分裂
java·开发语言·面试