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

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

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

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

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