安卓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() -> 必要时创建/释放补丁

相关推荐
℡余晖^几秒前
每日面试题20:spring和spring boot的区别
java·spring boot·spring
poemyang5 分钟前
“同声传译”还是“全文翻译”?为何HotSpot虚拟机仍要保留解释器?
java·java虚拟机·aot·编译原理·解释执行
苦学编程的谢1 小时前
Spring AOP_2
java·后端·spring·java-ee
没有bug.的程序员1 小时前
《Spring Boot应用工程化提升:多模块、脚手架与DevTools》
java·运维·spring boot
Java烘焙师1 小时前
架构师必备:实时对账与离线对账
hive·mysql·架构·对账
DemonAvenger1 小时前
构建实时应用:WebSocket+Go实战
网络协议·架构·go
Derek_Smart1 小时前
工业级TCP客户端高可靠连接架构设计与Netty优化实践
java·性能优化·netty
长安城没有风1 小时前
从 0 到 1 认识 Spring MVC:核心思想与基本用法(上)
java·spring boot·spring·java-ee·mvc
许野平2 小时前
Rust 同步方式访问 REST API 的完整指南
java·网络·rust·restful
设计师小聂!2 小时前
力扣热题100--------240.搜索二维矩阵
java·算法·leetcode·矩阵