核心内容摘要
502887·mooc免费版:解锁知识的无限可能,开启学习新纪元!
目录
简述2 类结构说明
初始化流程
设备连接管理
输出路由策略1 获取输出 (getOutputForAttr)2 Engine 选设备逻辑 (getDevicesForStrategyInt)
输入路由策略1 getInputForAttr2 getDeviceForInputSource
动态策略与 Mix
8.
总结深入剖析 Android AudioPolicyManager (后面简称APM) 及其策略引擎 (Engine) 的内部运作机制、核心数据结构与关键流程。
本文基于 Android 源码重点关注设备管理、路由策略选择及其与 Engine 的交互。
简述AudioPolicyManager (APM) 是 Android 音频系统的策略中心设备管理维护系统所有可用输入输出设备的状态。
策略路由决定特定音频流Stream或属性Attributes应路由到哪个设备。
资源控制管理音频输入输出并发、音量计算。
Engine 是 APM 的策略决策模块Strategy Decision Module定义产品策略 (Product Strategy)将 Audio Attributes 映射到 Strategy。
设备选择算法根据当前 Use Case如通话、媒体、铃声和强制配置Force Use为每个 Strategy 计算最佳输出设备。
这种分离设计使得 APM 框架可以保持通用而具体的路由策略如插入蓝牙耳机等等可以通过替换 Engine 实现或配置。
2 类结构说明APM 管理着由于音频策略配置文件audio_policy_configuration.xml解析出的对象模型。
图1 APM与Engine简单图如图1APM与Engine是一种策略模式更详细的关系如图2所示。
图2 APM与EngineHwModule: 对应 HAL 模块如 primary、 a2dp、usb。
包含其支持的 IOProfile。
IOProfile: 描述了 HAL 能提供的输入输出能力采样率、格式、通道、支持的设备。
它是静态配置的。
SwAudioOutputDescriptor: 描述了一个实际打开的输出流Stream。
它关联到一个具体的 IOProfile 和当前路由的 DeviceDescriptor。
DeviceDescriptor: 运行时设备对象包含地址、类型、能力等。
初始化流程初始化阶段APM 会加载 XML 配置文件构建 HwModule 和 IOProfile 及其支持的 DeviceDescriptor 集合。
1Factory 创建: AudioPolicyService 调用 createAudioPolicyManager。
2 Config 解析: APM 构造函数中解析 audio_policy_configuration.xml填充 mHwModules。
3Engine 初始化: Engine 加载自己的策略配置如有建立 Attributes 到 Strategy 的映射表。
4打开 Output: APM 遍历 HwModule预先打开那些 Attached非动态的 Output Profile如 Speaker/Earpiece 对应的 Output。
设备连接管理当设备插入如有线耳机、蓝牙耳机时流程如图3所示图3checkOutputsForDevice 逻辑如下当新设备连接时APM 会检查所有活动输出询问 Engine“这个 Output 现在应该去哪个设备”如果 Engine 返回的新设备就是刚连接的设备或者包含它APM 就会执行路由切换Tear down patch Create new patch。
输出路由策略这是 APM 最核心的部分App 请求播放 - 决定使用哪个 Output - 路由到哪个 Device。
1 获取输出 (getOutputForAttr)当 App 创建 AudioTrack 时 AudioTrack调用AudioFlinger::createTrack 然后会调用getOutputForAttr函数status_t AudioFlinger::createTrack(const media::CreateTrackRequest _input, media::CreateTrackResponse _output) { …… // Aptiv Audio lStatus AudioSystem::getOutputForAttr(localAttr, output.outputId, sessionId, streamType,adjAttributionSource, input.config, input.flags, output.selectedDeviceId, portId, secondaryOutputs); …… }后续流程如图4所示图4 getOutputForAttr流程2 Engine 选设备逻辑 (getDevicesForStrategyInt)在 Engine.cpp 中getDevicesForStrategyInt 是决策核心。
以下是 STRATEGY_MEDIA 为例简单说明下强制配置检查: getForceUse(FOR_MEDIA)。
如果是 FORCE_SPEAKER直接选 Speaker。
外部设备优先: 检查 A2DP, Wired Headset, USB Device。
getLastRemovableMediaDevices() 会返回最后连接的外部设备。
默认设备: 如果没有外部设备退回默认Speaker 或 Earpiece。
特殊规则:STRATEGY_PHONE (通话)优先蓝牙 SCO然后 Earpiece。
STRATEGY_SONIFICATION (铃声)同时从 Speaker 和 Headset 出声Dual Routing。
输入路由策略输入路由即决定录音来源选择哪个麦克风或输入设备。
1 getInputForAttr图5 getInputForAttr流程2 getDeviceForInputSourceEngine::getDeviceForInputSource 处理输入源映射VOICE_COMMUNICATION: 如果在通话中可能强制使用与输出设备匹配的输入如蓝牙耳机麦克风。
DEFAULT/MIC: 优先蓝牙 A2DP/SCO如果支持其次有线耳机麦克风最后是内置 Mic。
动态策略与 Mix除了传统的基于 Stream Type 的策略Android 还支持 Dynamic Policy (Audio Mix)常用于车机系统Car Audio将特定 uid 的导航声音路由到特定 BUS 设备。
投屏/录屏捕获特定内容的音频。
相关类AudioPolicyMix。
Engine 在计算设备时会优先检查是否有 AudioPolicyMix 匹配当前 Attributes如果有则强制路由到对应的 Mix 输出绕过默认策略。
8.
总结Android 音频策略框架是一个分层清晰的系统1 静态配置层 (HwModule/IOProfile)定义硬件能力底座。
2 动态状态层 (DeviceDescriptor/SwAudioOutputDescriptor)维护运行时状态。
3 策略决策层 (Engine)getDevicesForStrategyInt 是“大脑”根据优先级规则输出目标设备。
4 执行层 (APM)根据 Engine 的决策操作 AudioPolicyClient 完成物理连接。
理解 Engine 的 getDevicesForStrategyInt 和 APM 的 setDeviceConnectionState 是掌握 Android 音频路由切换的关键。
更多的内容敬请关注待分解。