车载音频路由分底层硬件定义 audio_policy_configuration.xml + 车载业务路由 car_audio_configuration.xml,两者配合实现「不同音源路由到不同 address」。
一、底层硬件:audio_policy_configuration.xml
作用:定义所有总线设备地址(bus0_media_out /bus1_navigation_out 等)、硬件端口、混音路由,所有 car 配置里用到的 address 必须在这里注册。 路径:vendor/etc/audio_policy_configuration.xml
XML
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
<globalConfiguration speaker_drc_enabled="true"/>
<modules>
<!-- 车载主音频HAL模块 -->
<module name="primary" halVersion="3.0">
<!-- 声明所有输出总线address(对应功放独立通道) -->
<attachedDevices>
<item>bus0_media_out</item> <!-- 音乐/媒体 -->
<item>bus1_navigation_out</item><!-- 导航播报 -->
<item>bus2_voice_cmd_out</item> <!-- 语音助手 -->
<item>bus4_call_out</item> <!-- 蓝牙通话 -->
<item>bus3_ring_out</item> <!-- 来电铃声 -->
<item>bus5_alert_out</item> <!-- 告警/雷达提示音 -->
<item>primary_mic</item> <!-- 车载麦克风输入 -->
</attachedDevices>
<defaultOutputDevice>bus0_media_out</defaultOutputDevice>
<!-- 混音源端口:APP音频流输出节点 -->
<mixPorts>
<mixPort name="mix_media" role="source" flags="AUDIO_OUTPUT_FLAG_DEEP_BUFFER">
<profile format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
</mixPort>
<mixPort name="mix_nav" role="source" flags="AUDIO_OUTPUT_FLAG_FAST">
<profile format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
</mixPort>
<mixPort name="mix_call" role="source" flags="AUDIO_OUTPUT_FLAG_FAST">
<profile format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
</mixPort>
</mixPorts>
<!-- 硬件输出端口:绑定上面的bus address -->
<devicePorts>
<devicePort tagName="bus0_media_out" role="sink" type="AUDIO_DEVICE_OUT_BUS" address="bus0_media_out">
<profile format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_5POINT1"/>
</devicePort>
<devicePort tagName="bus1_navigation_out" role="sink" type="AUDIO_DEVICE_OUT_BUS" address="bus1_navigation_out">
<profile format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
</devicePort>
<devicePort tagName="bus4_call_out" role="sink" type="AUDIO_DEVICE_OUT_BUS" address="bus4_call_out"/>
<devicePort tagName="primary_mic" role="source" type="AUDIO_DEVICE_IN_BUILTIN_MIC" address="primary_mic"/>
</devicePorts>
<!-- 底层硬件路由:mix流 → bus硬件地址 -->
<routes>
<route type="mix" sink="bus0_media_out" sources="mix_media"/>
<route type="mix" sink="bus1_navigation_out" sources="mix_nav"/>
<route type="mix" sink="bus4_call_out" sources="mix_call"/>
</routes>
</module>
</modules>
<xi:include href="audio_policy_volumes.xml"/>
</audioPolicyConfiguration>
关键点:
address="bus0_media_out" 就是你说的路由地址,每一路音源对应独立 bus;
AUDIO_DEVICE_OUT_BUS 车载专用总线设备类型,直通功放不同 I2S/SPDIF 通道。
二、车载业务路由:car_audio_configuration.xml(核心音源分流)
作用:绑定音频上下文 context (music/navigation/call)到上面定义的 bus address,实现「音乐走 bus0、导航走 bus1、通话走 bus4」,独立音量、抢占逻辑。 路径:vendor/etc/car_audio_configuration.xml
XML
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<audioZoneConfiguration version="3.0">
<zones>
<!-- 前排主音频区 isPrimary="true" -->
<zone name="main_cabin" audioZoneId="0" isPrimary="true">
<zoneConfigs>
<zoneConfig name="default_config" isDefault="true">
<volumeGroups>
<!-- 1. 媒体音量组:音乐、APP多媒体 -->
<group>
<device address="bus0_media_out">
<context context="music"/>
<context context="announcement"/>
</device>
</group>
<!-- 2. 导航独立音量组:地图播报 -->
<group>
<device address="bus1_navigation_out">
<context context="navigation"/>
</device>
<device address="bus2_voice_cmd_out">
<context context="voice_command"/>
</device>
</group>
<!-- 3. 通话独立通道:蓝牙电话最高优先级 -->
<group>
<device address="bus4_call_out">
<context context="call"/>
</device>
</group>
<!-- 4. 提示音/告警:雷达、安全带、故障音 -->
<group>
<device address="bus5_alert_out">
<context context="system_sound"/>
<context context="safety"/>
<context context="vehicle_status"/>
</device>
</group>
<!-- 5. 来电铃声 -->
<group>
<device address="bus3_ring_out">
<context context="call_ring"/>
</device>
</group>
</volumeGroups>
</zoneConfig>
</zoneConfigs>
</zone>
<!-- 后座娱乐分区(多区车型可选) -->
<zone name="rear_seat" audioZoneId="1">
<zoneConfigs>
<zoneConfig name="rear_default" isDefault="true">
<volumeGroups>
<group>
<device address="bus8_rear_media_out">
<context context="music"/>
</device>
</group>
</volumeGroups>
</zoneConfig>
</zoneConfigs>
</zone>
</zones>
</audioZoneConfiguration>
关键对应关系(回答你开头的疑问)
| 音源 Audio 类型 | context 上下文 | 路由 address 地址 | 独立特性 |
|---|---|---|---|
| 蓝牙音乐 / USB/CarPlay | music | bus0_media_out | 媒体音量,可被导航压低 |
| 地图导航播报 | navigation | bus1_navigation_out | 导航单独音量,优先混音 |
| 蓝牙通话 / 车载电话 | call | bus4_call_out | 最高抢占优先级,独立降噪 |
| 语音助手唤醒反馈 | voice_command | bus2_voice_cmd_out | 语音助手专属通道 |
| 倒车雷达 / 提示音 | safety | bus5_alert_out | 固定小音量,不可静音 |
三、配套开关(必须开启才能生效多地址路由)
vendor/etc/overlay/frameworks/base/core/res/res/values/bools.xml
XML
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 开启车载动态多总线路由,关闭则所有音源共用bus0 -->
<bool name="audioUseDynamicRouting">true</bool>
</resources>
四、简单逻辑总结
audio_policy_configuration.xml:注册硬件地址 busX_out,告诉系统有多少条独立音频总线;car_audio_configuration.xml:音源→地址绑定,哪种音频流走哪条总线;- 不同 address 对应功放不同硬件通道,实现独立音量、混音优先级、多喇叭分区输出。
===================================================================
AAOS 里一条 busXXX_out 到底代表什么(分层讲清楚)
一、软件抽象层(XML 里看到的 bus)
bus0_media_out / bus1_nav_out 是 AUDIO_DEVICE_OUT_BUS 类型的独立端口地址 ,属于 Android Audio HAL 的软件逻辑流通道:
- 一条 bus = 一路独立、不与其他音源提前混音的 PCM 数据流
- 每个 bus 独占一条
mixPort,Android 上层不会把不同 context 的声音混在一起下发 - 作用:让功放 / 底层 DSP 拿到分离的媒体、导航、通话裸流,由硬件侧做闪避、分喇叭、独立音量控制
举个例子:
- bus0:纯音乐流(48k 立体声)
- bus1:纯导航播报流(48k 立体声)
- bus4:纯通话语音流(16k 单声道) 三条流并行同时输出到功放,互不干扰,功放硬件再做混音、压低音乐。
二、对应硬件层(物理链路)
软件 bus 一一映射主机到功放的一条物理数字音频传输链路,常见三种硬件载体:
1. I2S/TDM(最普遍)
一条 bus = 一组完整 I2S 硬件通道(MCLK+BCLK+WS+SD)
- bus0 → I2S0 硬件口(全车音乐)
- bus1 → I2S1 硬件口(导航只走前门喇叭) 主机每多一条 bus,就要多一组 I2S 引脚输出 PCM 流给功放 DSP。
2. A²B 汽车音频总线(高端分布式功放)
A²B 是双绞线菊花链,一条物理 A²B 线缆里可以承载多路 TDM 时隙:
- 软件 bus0 = A²B TDM slot0~1(音乐)
- 软件 bus1 = A²B TDM slot2~3(导航) 此时多条逻辑 bus 复用一条 A²B 物理线,靠时隙区分。
3. SPDIF / 光纤同轴
一条 bus = 一路独立光纤 / 同轴数字输出。
三、业务层面:一条 bus = 一组独立音量组(CarAudio 核心)
car_audio_configuration.xml 里,一个 volumeGroup 绑定一个 bus:
- 一个 bus 对应一套独立音量记忆、独立焦点、独立闪避策略
- 音乐调音量只改 bus0;导航调音量只改 bus1;通话优先级最高直接抢占 bus4
四、极简总结(一句话)
AAOS XML 里的一条 bus = 一条独立未混音的数字音频流通道,上层软件用来隔离不同音源(music/nav/call),底层对应主机到功放的一组 I2S/TDM 时隙 / A²B 时隙物理链路,实现分音源独立音量、硬件闪避、分区喇叭输出。
=========================================================
每个独立 bus address,运行时会对应一条独立 PlaybackThread(MixerThread)
1. 核心对应关系
AudioFlinger 规则: 一个 HAL output(一条硬件输出流) ↔ 一个 PlaybackThread 而 AAOS 里每一条 busXXX_out 是独立 AUDIO_DEVICE_OUT_BUS 设备,AudioPolicy 会为每个 bus 打开独立 OutputDescriptor,最终在 AudioFlinger 生成独立 MixerThread。
举你车载多 bus 场景:
- bus0_media_out → Output0 → MixerThread0(音乐混音线程)
- bus1_navigation_out → Output1 → MixerThread1(导航线程)
- bus4_call_out → Output2 → MixerThread2(通话线程) 三条线程并行跑、各自独立调度、独立缓冲、独立输出到 HAL。
2. 为什么必须分开线程?
- 采样率 / 位深 / 声道参数完全独立
- bus0 音乐:48k stereo
- bus4 通话:16k mono 同一个 PlaybackThread 只能一套硬件参数,不同规格流不能共用线程。
- 独立硬件时钟同步 每条 bus 对应独立 I2S/TDM 时隙,硬件中断周期不同,必须单独线程驱动 HAL 写 PCM。
- 互不干扰的混音、闪避、音量控制 音乐线程只管 mix 所有 music 类 Track;导航线程只 mix 导航播报;通话线程独占、高优先级,各自内部独立音量衰减,不用跨线程同步混音逻辑。
- 线程优先级隔离 通话 / 导航线程可配置更高调度优先级,避免被音乐大混音线程抢占 CPU。
3. 容易混淆的两个概念(别搞混)
① PlaybackThread(线程)
一条 bus 对应一个线程,负责:
- 收集本 bus 下所有 AudioTrack(应用声音)
- 软件混音
- 周期往 HAL bus 流写 PCM 数据
② Track(应用流)
同一个 bus / 同一个线程里,可以存在N 个 Track(多路声音叠加) 例:bus0 音乐线程内同时存在:蓝牙音乐 + CarPlay 音频 + 本地 U 盘歌,三个 Track 在同一个 MixerThread 内混音后输出 bus0。
4. 两种车载架构对比验证
低配单 bus 方案(仅 bus0)
只有 1 个 Output → 只有 1 条 MixerThread;所有音源上层先混在一起再下发功放。
主流多 bus 车载方案(music/nav/call 分开 bus)
每个 bus 独立 Output → 每个 bus 一条独立 PlaybackThread,上层不混音,裸流分别下发功放 DSP 做硬件闪避、分喇叭输出。
5. 补充边界特例
- 同一条 bus 下多个 context:共用同一个线程,内部软件混音;
- 同一物理 A²B 线缆多路 TDM bus:逻辑上多条 bus,依然多条独立线程,只是底层复用双绞线;
- Tone / 提示音:短音会临时复用对应 bus 的现有线程,不会单独新建线程。
一句话总结
XML 里每一个唯一 busXXX_out 硬件地址,运行时都会创建一条专属 MixerThread(PlaybackThread);同一 bus 内多个音源是在线程内部混音,不同 bus 之间是完全隔离的独立播放线程。
============================================
PlaybackThread 完整分类(基类 + 4 种派生播放线程,车载场景全覆盖)
类继承关系
XML
ThreadBase
├─ RecordThread(录制,非播放)
└─ PlaybackThread(播放基类,所有输出线程父类)
├─ MixerThread 标准混音线程(车载bus默认用这个)
├─ DirectOutputThread 直通线程
│ └─ OffloadThread 硬解直通线程
└─ DuplicatingThread 复制分流线程
1. MixerThread(你前面关心的 bus 全部是它)
触发 flag
AUDIO_OUTPUT_FLAG_PRIMARY / DEEP_BUFFER / FAST
核心特点
- 内置
AudioMixer,支持多路 Track 软件混音、重采样、独立音量、音效处理; - 一条独立
busXXX_out= 一个 Output = 一条独立 MixerThread; - 同一条 bus 内可以叠加无数 Track(蓝牙音乐 + CarPlay + 本地媒体一起混);
- AAOS 多 bus 架构(music/nav/call 分总线)全部使用该线程。
车载场景
bus0_media、bus1_nav、bus4_call、bus5_alert 每条 bus 各自一条 MixerThread。
2. DirectOutputThread 直通线程
触发 flag
AUDIO_OUTPUT_FLAG_DIRECT
核心特点
- 无软件混音器 ,一个 Output 同一时间只能存在一条 Track;
- 音频格式、采样率、声道必须和 HAL 硬件端口完全匹配,不做 SRC 重采样;
- 省去混音开销,延迟极低;
- 不能叠加多路声音,新 Track 会抢占、挤掉旧 Track。
车载使用场景
- 蓝牙 SCO 通话直通(部分厂商 HAL);
- 专业低延迟语音助手拾音反馈;
- 无损 HiFi 比特完美直通(bit-perfect)。
3. OffloadThread 硬件硬解线程(继承自 DirectOutputThread)
触发 flag
AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD
核心特点
- 下发压缩码流(AAC/MP3/FLAC),不解 PCM,直接丢给 DSP / 功放硬解;
- CPU 占用极低,适合长时间后台音乐;
- 同样不支持多路混音,独占输出端口;
- 暂停 / 切歌控制交给硬件 DSP,AudioFlinger 只做调度。
车载场景
高配车机本地无损、USB 音乐 offload 模式。
4. DuplicatingThread 复制分流线程(继承自 MixerThread)
触发场景
需要一轨音源同时输出到多个设备(复制流)
核心特点
- 输入一路混音流,内部复制多份分别下发多个 Output 设备;
- 底层依然依赖 Mixer 做混音,只是多输出分支;
- 共享同一条线程,不会新建多条 MixerThread。
车载场景
- 全车音乐同时输出前门 + 后座娱乐;
- 蓝牙音乐同时车内喇叭 + 蓝牙耳机双出。
补充:容易混淆的其他音频线程(不属于 PlaybackThread)
- RecordThread 录音专用,麦克风输入、通话上行拾音、语音助手收音,和播放线程完全隔离。
- AudioTrackThread(APP 进程内) 应用侧客户端线程,负责往共享内存写数据;不在 AudioFlinger 服务端,和上面四类 PlaybackThread 不是一层东西。
- FastMixer 子路径 不是独立线程类型,是 MixerThread 内部的低延迟调度分支,优先级更高,用于按键音、导航播报。
车载多 bus 架构线程对应总结
- 每一个
busXXX_out→ 独立 Output → 独立 MixerThread; - 如果某条 bus 配置
DIRECT直通,则该 bus 创建 DirectOutputThread; - 开启 offload 硬解时,对应 Output 替换为 OffloadThread;
- 多区同步输出(主驾 + 后座)会生成 DuplicatingThread 复制流;
- 所有播放线程互相独立调度、独立缓冲区、独立 HAL 写入,互不阻塞。
一句话区分
- MixerThread:多路混音,车载 bus 标准;
- Direct:单路独占、低延迟、无混音;
- Offload:压缩码流硬件解码,省电;
- Duplicating:一份声音复制多设备输出。
==========================================================
三层分工:CarAudioService / 音频焦点 / 功放 DSP,各自核心职责 + DSP 策略来源完整梳理
一、三层核心定位与各自重点(从上到下)
1. 音频焦点(AudioFocus,业务仲裁规则层)
本质:一套「并发交互矩阵」,定义谁能播、谁该停、谁可以共存压低
- 数据来源:
car_audio_configuration.xml内置上下文优先级矩阵(safety > call > nav > music) - 核心重点:
- 处理 App 焦点请求栈,判断独占 / 并发 / 拒绝 三种交互模式
- 来电 call:独占,音乐直接丢 loss,建议暂停;
- 导航 nav:并发 may_duck,允许一起出声;
- 倒车告警 safety:最高优先级,压制所有其他音源。
- 下发事件通知:给音乐 App 回调「你要被压低 / 暂停」;同步通知 CarAudioService 触发闪避指令。
- 纯业务逻辑、无 PCM 数据操作,只做 "权限分配",不碰音量增益、不混音。
- 处理 App 焦点请求栈,判断独占 / 并发 / 拒绝 三种交互模式
- 局限:只是上层君子协议,App 可无视焦点回调继续播放;必须靠下层硬件兜底。
2. CarAudioService(车载音频总调度枢纽,框架控制层)
本质:连接焦点、路由、音量、HAL、DSP 指令的中间大脑
- 核心重点 5 件事:
- 路由分配:解析 xml,把 music/nav/call 绑定到独立 bus 地址,决定每条流走哪一路 I2S/TDM;
- 音量分组管理:每个 bus 对应独立 volumeGroup,调节媒体 / 导航 / 通话独立音量;
- 焦点事件转发 :焦点状态变化后,组装Ducking / 静音控制指令下发 AudioControl HAL;
- 车辆信号联动:车速、倒车、车门、档位等 VHAL 信号联动静音 / 衰减;
- OEM 扩展钩子(Android14+):厂商自定义焦点、闪避、音量规则插件。
- 输出产物:标准化控制指令(哪条 bus 要衰减多少 dB、是否静音、持续多久),下发给 HAL 再透传给功放 DSP。
3. 功放 DSP(硬件执行层,最终声音渲染)
本质:多路 PCM 并行接收、实时硬件运算、最终输出喇叭
- 核心重点:
- 接收多条独立 bus 的裸 PCM 流(bus0 音乐、bus1 导航、bus4 通话互不干扰);
- 多路硬件混音、动态增益闪避 ducking、分喇叭路由(导航只前门、通话头枕);
- EQ、响度补偿、降噪、回声消除、限幅等音效处理;
- 根据上层下发的指令动态修改各路通道增益,播报结束自动恢复音量。
- 关键:真正听到 "音乐变小、导航清晰" 的动作全部在这里硬件完成。
二、DSP 执行的策略从哪里来?分 2 套策略(静态基准 + 动态实时指令)
1. 静态基准策略(DSP 固件固化,底层永久生效)
由功放 / DSP 厂商预设,不随场景实时变化:
- 各路音源基础增益配比:导航默认比音乐高 6dB、告警音固定增益;
- 喇叭分配规则:call 走头枕、nav 前排、music 全车;
- 硬件保护逻辑:削波限幅、高低通分频;
- 基础闪避曲线:衰减斜率、恢复时长(播报结束平滑回升)。 来源:功放 DSP 固件、调音工程文件(.tap/.bin 调音参数),出厂烧录,AP 无法修改底层曲线。
2. 动态实时控制指令(上层 AAOS 下发,场景临时覆盖静态策略)
完整传递链路:App 请求焦点 → 焦点引擎判定交互类型 → CarAudioService 组装 Ducking 指令 → AudioControl HAL → 功放 DSP 控制通道增益
- 源头 1:
car_audio_configuration.xml交互矩阵(定义什么场景该闪避 / 静音) 例:nav gain -12dB、call gain -20dB、safety gain -30dB; - 源头 2:CarAudioService OEM 插件(Android14+,厂商可自定义差异化策略) 比如高速导航只衰减 6dB,城市道路衰减 12dB;倒车时媒体直接静音;
- 源头 3:用户手动音量调节(CarAudioService 同步下发对应 bus 基准增益给 DSP);
- 源头 4:车辆 VHAL 信号(倒车、开门、车速联动衰减指令)。
一句话链路总结 DSP 动态指令来源
xml交互矩阵规则 + OEM自定义业务逻辑 → CarAudioService 生成增益 / 静音指令 → HAL 透传 → DSP 实时修改各路通道音量。
三、完整场景串联(导航播报压低音乐,看懂三层配合)
- 导航 App 请求焦点
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK; - 音频焦点引擎 查询交互矩阵:nav 与 music 是并发 duck 关系,授予焦点,通知音乐 App 短暂压低;
- CarAudioService 收到焦点变更,读取 xml 配置:music 通道衰减 12dB,组装 Ducking 控制消息下发 AudioControl HAL;
- HAL 把指令转发给外置功放 DSP;
- DSP 同时接收 bus0 (音乐)、bus1 (导航) 两路独立 PCM:
- 临时降低 bus0 音乐通道增益 - 12dB;
- bus1 导航正常音量输出;
- 两路硬件混音后推喇叭;
- 导航播报结束,App 释放焦点;焦点栈恢复,CarAudioService 下发恢复增益指令,DSP 把音乐音量拉回原值。
四、关键区分:三层权责边界(避免混淆)
- 音频焦点:只定规则、发通知,不控制硬件音量;
- CarAudioService:规则翻译官,把焦点业务规则翻译成 DSP 能识别的硬件控制指令,管理路由与音量分组;
- DSP:纯粹执行者,自有固定硬件混音 / 闪避曲线,只响应上层下发的实时增益指令,底层声学逻辑由功放固件决定。
五、补充两种降级方案对比,凸显多 bus+DSP 架构优势
- 低配单 bus 车机: 所有音源在 AudioFlinger 软件混音,闪避只能靠 CarAudioService 提前软件衰减音乐,无 DSP 多路独立通道,顿挫、恢复生硬;
- 高端多 bus 架构(你 XML 的方案): AP 只下发指令,多路裸流直送 DSP,硬件平滑闪避、分喇叭、独立音量,体验最优,也是 AAOS 官方推荐架构。
===============================================================
一、音频焦点相关配置在哪定义,为何 car_audio_configuration.xml 看不到
1. 核心配置文件分工(Android Automotive AAOS)
(1)car_audio_configuration.xml 职责
只定义音频总线 (Audio Bus)、音量组 (Volume Group)、设备映射、流类型分配 ,不存储音频焦点抢占 / 流转规则、优先级矩阵,所以你在这个 xml 里搜不到焦点逻辑。 字段仅包含:
- audioBus:bus 编号、设备、支持的 usage(音频用途 music/call/nav 等)
- volumeGroup:绑定多个 bus,统一音量控制
- audioDevice:硬件输出设备映射
(2)音频焦点 + 优先级矩阵的 3 个定义位置
① 硬编码上下文优先级矩阵(safety > call > nav > music)
源码路径:packages/services/Car/car-lib/src/android/car/audio/CarAudioContext.java 内置固定优先级数组,是系统底层静态优先级,无 xml 配置,写死在 Java 代码中。
② 音频焦点抢占 / 打断规则(主流配置文件)
audio_policy_configuration.xml(系统 audio policy 核心)
- 定义 audio_usage、stream、焦点请求模式(临时抢占 / 混合 / 独占)
- 配置不同 usage 之间的 duck(音量压低)、pause(暂停)行为
- 区分跨 bus / 同 bus 焦点处理逻辑
③ 车载专属焦点策略扩展(AAOS)
car_audio_policy_configuration.xml(车载专用音频策略) 补充车载场景规则:
- 安全提示 (safety) 高优先级强制打断所有音频
- 通话 (call) 打断导航 / 音乐,导航仅压低音乐不暂停通话
- 同 bus / 跨 bus 焦点流转逻辑开关
2. 为什么 car_audio_configuration.xml 看不到焦点定义
该文件是车载音频硬件 & 音量分组配置 ,只管硬件通路、音量分组; 音频焦点、打断、优先级属于音频策略 (Audio Policy) 范畴,由 audio_policy 系列 xml + CarAudio 服务硬编码共同管控,两者职责完全隔离。
二、音频焦点是否在不同 bus 之间流转?
结论:会跨 Bus 流转,焦点是全局系统级资源,不受 Bus 隔离
- 焦点归属维度:Usage(音频用途),不是 Bus 焦点请求时 APP 传递
AudioAttributes.USAGE_MEDIA/USAGE_NAVIGATION/USAGE_VOICE_COMMUNICATION,系统只识别 Usage,不绑定 Bus。 - 跨 Bus 流转场景举例
- Bus0:多媒体音乐(music)正在持有焦点
- Bus1:蓝牙电话(call)发起焦点请求 系统读取内置优先级 call > music,直接剥夺 Bus0 音乐焦点,将全局焦点切换给 Bus1 通话,完成跨 Bus 流转。
- Bus 仅作用:硬件输出通路隔离 同一 Usage 可以绑定多个 Bus;不同 Bus 可以承载同 / 不同 Usage,但焦点是全局唯一,高优先级 Usage 无论在哪条 Bus,都能抢占低优先级 Bus 上的音频焦点。
三、同一 bus 内不同 APP 是否共用同一个音频焦点?
分两种场景,核心看 Usage,不是 Bus
场景 1:多个 APP 同 Usage(例:Bus0 里网易云 + QQ 音乐,都是 USAGE_MEDIA)
共用同一类焦点槽位,互斥
- A 音乐持有焦点播放;B 音乐请求焦点时,系统判定为同 Usage,直接夺走焦点,A 被暂停;
- 同 Bus 同 UsageAPP 无法同时持有焦点,同一时刻只有一个能播放。
场景 2:同一 Bus 内不同 Usage(例:Bus0 同时跑音乐 music + 导航 nav)
独立焦点,有优先级区分
- 音乐持有基础焦点;导航高优先级请求临时焦点,触发 duck(音乐压低),不会完全夺走音乐焦点;
- 两个 APP 各自持有对应 Usage 的焦点,同 Bus 共存,由优先级矩阵控制混音行为。
总结
同 Bus 内:同 Usage 共享一个焦点,互斥;不同 Usage 独立焦点,按优先级混音 / 打断。Bus 不隔离焦点,Usage 才是焦点区分核心。
四、同一个音量组 (volumeGroup) 音量是否同步变化?
结论:是,音量组是批量音量控制单元,组内所有 Bus 音量同步联动
整体逻辑串联总结
==============================================================
-
配置逻辑(car_audio_configuration.xml 内 volumeGroup 标签)
XML<volumeGroup name="media_group"> <audioBus busNumber="0"/> <audioBus busNumber="3"/> </volumeGroup>Bus0、Bus3 归属同一个 media_group 音量组。 2. 行为表现
-
调节多媒体音量条,组内所有绑定 Bus 的输出音量同步增减;
-
底层 CarAudioService 统一给组内所有 audioBus 下发相同音量缩放系数;
-
边界区分
-
不同 volumeGroup 完全独立音量(通话组、多媒体组、安全提示组互不干扰);
-
优先级矩阵 (safety>call>nav>music):Java 硬编码,不在 car_audio_configuration.xml;
-
car_audio_configuration.xml:仅 Bus、音量组、硬件映射;焦点策略在 audio_policy_configuration/car_audio_policy_configuration.xml;
-
音频焦点全局流转,可跨 Bus 抢占,优先级由 Usage 决定,Bus 只是硬件通路;
-
同 Bus 同 APP Usage 互斥共用焦点,不同 Usage 独立焦点;
-
volumeGroup 内所有 Bus 基础音量同步调节,组间音量隔离。
- 音量组只控制硬件输出音量,不影响音频焦点、混音逻辑;焦点打断 duck 压低是软件动态衰减,不会修改音量组基础音量值。
一、系统到底是不是只有一个全局音频焦点?
1. 原生 Android 手机(标准 AudioFocus):同一时刻只有 1 个主焦点持有者
底层规则: 系统维护单一全局焦点锁 ,任意时刻只会有一个 App 拿到AUDIOFOCUS_GAIN(长期主焦点)。 分三种请求类型,对应三种失去焦点回调:
AUDIOFOCUS_GAIN(音乐长期播放) 别人抢长期焦点 → 你收到 AUDIOFOCUS_LOSS,必须暂停 / 停止,完全丢失焦点; AUDIOFOCUS_GAIN_TRANSIENT(临时独占,来电、语音输入) 你收到 AUDIOFOCUS_LOSS_TRANSIENT,建议暂停,临时丢失;播报结束焦点归还; AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK(导航播报、提示音) 你收到 AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK → 你没有丢失焦点,只是需要压低音量继续播放。
关键澄清:"音乐持有基础焦点,导航拿临时 duck 焦点" 是什么意思?
2. AAOS 车载系统(CarAudioService 扩展):支持多 Usage 并行持有有效焦点
手机框架是单焦点互斥;车载做了优先级矩阵增强,允许高优先级 Usage 共存、同时持有有效焦点:
二、Duck 闪避:软件层面音量调节,和用户手动调音量组完全隔离
1. 两种音量增益完全分开,互不覆盖
① 用户手动调节音量组(volumeGroup)------ 硬件基础增益
② Duck 闪避衰减 ------ 软件混音临时增益(系统强制 / APP 配合)
两条实现路径:
2. 核心区分:Duck 是临时动态衰减,不改动音量组基准
举例子:
三、同 Bus、跨 Bus 焦点流转补充纠正
四、一句话总结关键点
- 音乐依旧是全局唯一主焦点持有者,没有被剥夺焦点;
- 导航只是临时叠加一层临时请求标记,系统通知音乐做衰减混音;
- 导航播报结束释放临时请求后,音乐直接恢复正常音量,不需要重新申请焦点。 不是系统存在两个独立焦点,而是同一主焦点下允许临时混音闪避。
- 通话 USAGE_VOICE_COMMUNICATION(最高优先级)长期持有焦点;
- 同时导航 USAGE_ASSISTANCE_NAVIGATION 可叠加临时 duck 焦点;
- 媒体音乐 USAGE_MEDIA 被 duck 压低,但仍保留自身焦点状态; 底层逻辑: 车载不再是单纯 "一把锁",而是按AudioAttributes.usage做分层优先级调度,不同 Usage 可以同时处于 "持有焦点" 状态,仅做音量衰减区分,这也是车载能同时通话 + 导航 + 背景音乐的根本原因。
- 配置:
car_audio_configuration.xmlvolumeGroup - 作用:保存基础音量档位(比如媒体音量 30%),持久化存储;
- 实现(AAOS 默认
config_useFixedVolume=true):下发到 HAL 硬件功放,硬件整体放大 / 缩小信号; - 特点:duck 不会修改这个基础值,播报结束音量自动回到原档位。
- APP 主动兼容(原生标准逻辑) 收到
AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK回调,App 内部播放器把音量乘 0.3~0.5 做衰减,属于应用层软件调节; - AAOS 系统强制 Ducking(Android14+ OemCarDuckingService) CarAudioService 检测焦点变化,直接给 AudioFlinger/HAL 下发临时衰减增益,不依赖 APP 配合,底层混音器软件压低对应流,即便 APP 不处理回调也会变小声。
- 媒体音量组手动调到 50%(硬件基础增益固定);
- 导航播报触发 duck,软件叠加 - 12dB 衰减,音乐实际输出等效 20% 音量;
- 导航播报完成,临时软件衰减撤销,立刻回到硬件 50% 基准音量;
- 中途手动调媒体音量条,只会修改硬件基础增益,不影响 duck 逻辑。
- Bus 只是硬件输出通路,焦点调度完全不看 Bus,只看 Usage 优先级;
- 同 Bus 多 APP:
- 同 Usage(多个音乐):互斥,后申请的会夺走主焦点,前者收到 LOSS 完全暂停;
- 不同 Usage(音乐 + 导航):车载支持共存,音乐 duck,各自保留焦点状态;
- 跨 Bus 场景(Bus0 音乐 / Bus1 蓝牙通话): Call 优先级高于 Media,通话直接抢占全局高优先级焦点,音乐被 duck 或暂停,焦点可以跨 Bus 切换。
- 原生 Android:全局只有 1 个长期主焦点,duck 只是临时混音标记,音乐没丢焦点;
- AAOS 车载增强:按 Usage 分层优先级,允许多类音频同时持有有效焦点并行播放;
- Duck 是软件临时衰减增益,和 volumeGroup 硬件基础音量两套独立控制,互不修改;
- 音量组仅控制硬件基准音量,duck 播报结束自动恢复原音量档位。