本页面介绍了如何启用音频框架和音频 HAL (AHAL) 来管理同步连接导向型 (SCO) 连接,此过程称为音频托管 SCO (AMSCO)。
在 Android 17 及更高版本中,Android 音频框架使用 SCO 管理功能来管理 SCO 路由,该路由最初由蓝牙 (BT) 框架处理。此迁移会将 SCO 连接状态从由蓝牙框架拥有的状态移至音频流式传输活动的下游结果。
通过在音频框架内集中管理音频路由的所有权,此功能可使 SCO 的音频硬件抽象层 (HAL) 实现与其他蓝牙配置文件(例如高级音频分发配置文件 [A2DP] 和 LE 音频)保持一致。此重构简化了电信堆栈和 BT 堆栈之间的交互,从而实现了更强大且集中的音频路由架构。
架构概览
AMSCO 架构将 SCO 连接管理集中在 Android 音频框架内,该框架根据音频流式传输活动做出路由决策。此架构与之前由蓝牙堆栈管理连接的模型形成对比。此架构中每个组件的角色如下:
只有在满足以下条件时,AHAL 才会启动和暂停 SCO 会话:
- 将有效的数据流修补到 SCO 设备。
- 音频模式已设置,并且存在指向 SCO 设备的通路。
当满足这些特定条件时,音频框架会阻止 A2DP 设备拥有并发补丁。音频框架不再向 AHAL 发送 SCO 状态更改或 A2DP 暂停。
音频框架会处理 SCO 管理,因此 BT 堆栈不再调用连接或断开音频。如果发生抢占式 SCO 断开连接或错误,BT 堆栈会通过 AudioManager#onHfpAudioDisconnected 通知音频框架。
方案
在实现 SCO 管理重构之前,请使用本部分中的信息评估以下兼容性和架构要求。
向后兼容性
为了使框架能够继续支持可能接收操作系统更新但未更新其 AHAL 或 BT AHAL 的设备,请使用系统属性来指示必须启用新的 SCO 管理。如果系统属性被停用或 HAL 版本过时,旧版路径最多可保留 6 年。
设置 HFP 会话
AHAL 必须使用新的免触摸操作配置文件 (HFP) 会话类型来开始或暂停播放,与其他蓝牙会话类型类似。最终,系统会使用不同的 IBluetoothAudioProviders 管理流状态,这些 IBluetoothAudioProviders 由 Factory 类根据可用途径进行枚举和构建。
蓝牙堆栈会尽可能使用硬件分流路径。协商期间对编解码器的偏好顺序如下:LC3 硬件优先于 LC3 软件,其次是 mSBC 硬件,然后是 mSBC 软件,最后是 CVSD 硬件优先于 CVSD 软件。
以下序列图详细说明了 AHAL 与 BT 堆栈之间建立流状态所需的互动。
硬件分流程序
图 1 说明了 AHAL 和 BT 堆栈如何协调以建立 SCO 音频的直接硬件数据路径:
图 1. 硬件分流程序。
软件数据路径程序
图 2 说明了处理需要系统软件处理的音频数据的流程:
图 2. 软件数据路径程序。
编解码器重新协商程序
当音频网关 (AG) 收到新的蓝牙可用编解码器 (AT+BAC) 命令时,AG 会重新启动编解码器协商程序。图 3 说明了编解码器重新协商过程:
图 3. 编解码器重新协商程序。
对 HeadsetStateMachine 的影响
Java 层耳机状态机(由 HeadsetStateMachine 类表示)基本保持不变,但 AUDIO_CONNECTED 状态除外,该状态由原生堆栈事件驱动。在 Java 层中,系统不再启动 connectAudioNative 或 disconnectAudioNative。相反,系统会响应来自原生堆栈的音频连接状态变化。这些更改由 IBluetoothAudioProvider 或 IBluetoothAudioPort 上的 AHAL 命令触发。
实现
为了集成 SCO 管理重构,请更新 BT 堆栈和音频框架之间的通信。
请按照以下步骤实现此功能:
通知音频框架有关活跃 BT 的更改,以帮助在 HFP 设备连接期间正确管理 SCO 启动和拆除,并处理活跃设备更改。使用
AudioManager.handleBluetoothActiveDeviceChanged(HfpInfo)将此信息提供给音频框架。
图 4. 连接 HFP 设备。
音频框架使用
AudioManagerAudioDeviceCallback#onAudioDevicesAdded回调(而非旧版广播)来指示音频设备状态。使用
setCommunicationDevice(AudioDeviceInfodevice)作为主要控制点来实现 AHAL 流控制,以启动 SCO 连接。如果
HfpTransport::StartRequest返回BluetoothAudioCtrlAck::PENDING,AHAL 必须重试请求,因为 HFP 状态机尚未建立。
使用场景
以下部分概述了典型的关键用户历程 (CUJ)。
电信通话流程
SCO 管理重构将 phoneStateChanged 更改为阻塞函数。此修改会导致电信在调用音频框架 API 以启动 SCO 创建之前,等待 BluetoothInCallService.onCallAdded 方法中的 phoneStateChanged 执行完成。

图 5. 通过电信接听或发起通话。
VoIP 通话流程
音频框架通过调用 BluetoothHeadset.startScoUsingVirtualVoiceCall 方法来启动该进程。在蓝牙堆栈向音频框架提供结果后,该框架会指示 AHAL 执行 startStream。下图演示了此流程:

图 6. 通过 VoIP 接听或发起通话。
语音识别
对于免提 (HF) 和 AG 发起的语音识别,BT 堆栈必须请求音频框架使用 AudioManager.setCommunicationDevice 打开 SCO。下图对此进行了说明:

图 7. 语音识别 SCO 启动。
音频连接
在语音识别期间,BT 堆栈通过使用 AudioManager.setCommunicationDevice(AudioDeviceInfo) 请求音频框架来启动 SCO 连接。如果通话处于有效状态,蓝牙堆栈会改为从电信堆栈请求 BluetoothInCallService#requestBluetoothAudio。
此流程如下图所示:

图 8. 音频连接。
验证和测试
为了验证该功能是否已正确集成并符合质量标准,设备制造商必须运行以下测试:
- CTS 验证程序:使用 CTS 验证程序在通话期间对音频路由进行交互式测试。
- 供应商测试套件 (VTS):使用 VTS 验证 AHAL 和 BT AHAL 互动。
要求
此功能需满足以下要求:
- AHAL:实现需要支持重构的 SCO 管理路径的兼容 AHAL。