音频切换

随着用户越来越多地使用多个音频源设备执行日常任务,人们越来越需要一种更简单的解决方案来管理跨设备的耳机使用情况。音频切换可以根据用户活动(例如开始播放电影)和优先事件(例如来电)无缝切换设备之间的耳机连接。

用户体验原则

  1. 连接应能够快速切换,并且应基于用户操作。
  2. 连接切换对用户来说应该是透明的,以便用户在不需要切换时进行控制/还原。
  3. 切换应尊重用户隐私。

角色

音频切换搜寻器:搜寻器是一种音频源设备(例如手机或平板电脑),寻找可连接的附近耳机(如适用)。

音频切换提供程序:提供程序通常是耳机,用于通告其存在状态和连接状态,以便探索者做出切换决策。

要求概览

如需实现智能切换,提供商必须遵循以下要求:

名称 说明 要求 是否必需?
页面扫描 在存在现有连接时接受来自另一个探索者的新连接请求。
对于单点提供程序:
  • 在 Provider 断开连接时,原始源设备将自动暂停其音频播放。
对于多点提供商:
  • 如果仍有可用连接,它会接受连接请求。
  • 如果连接带宽已满,请断开最近最少使用的连接(例如长时间没有音频事件),然后接受新的传入请求。
必须使用低延迟页面扫描模式(扫描间隔不应超过 640 毫秒)才能提高性能。
为了在电池续航时间和切换性能之间取得平衡,提供商可以在大多数情况下都使用默认页面扫描模式(低功耗模式,扫描间隔不应超过 1280 毫秒)。但在以下情况下,必须使用低延迟模式:
  • 开机前 30 秒
  • 无连接或分页的前 30 秒
  • 设备处于闲置状态的前 30 秒
强制
连接历史记录 切换回之前的连接并恢复播放(如果适用)。
系统将通过 Message Stream API 的通信触发切换回系统。
在适用的情况下,应将暂停音频事件包含在录音中,以便继续播放。
维护连接历史记录并实现 Message Stream API。 强制
连接状态 供搜索者判断是否连接网络。连接状态包括:
  • 连接状态
  • 有效连接的音频类型
  • 有效连接的帐号信息
  • 已连接的设备
在 BLE 通告和消息流中包含连接状态。 强制
运行时功能发生变化 可通过升级提供程序上的固件启用音频切换,因此需要在运行时在查找器和提供程序之间同步这些功能。 实现 Message Stream API 以使用运行时功能。 强制
可配置的切换规则 让 Seeker 可以通过用户偏好设置在现有的正在进行的音频流式传输和新的音频流式传输请求之间配置优先级。
例如,音频切换 Seeker 可以提供界面设置,以便用户启用/停用媒体流式传输与通话之间的自动切换。
音频切换用户会通过消息流设置并获取切换规则。
仅限多点提供程序。
实现 Message Stream API 可配置已连接设备之间的切换规则。
可选
活跃设备切换 让音频切换搜寻器在已连接的设备之间模拟音频切换。
在音频切换搜寻器端,可能会提供一个界面,供用户在已连接的设备之间轻松切换。
仅限多点提供程序。
为音频切换搜寻器实现 Message Stream API,以确定已连接设备之间的活跃音频源。
强制
多点切换通知 让音频切换查找器显示切换通知。 仅限多点提供程序。
实现 Message Stream API,以便在发生多点切换时通知已连接的音频切换搜寻者。
强制

广告载荷

提供商应在通告中包含其当前连接状态,该状态基于通告:何时不可发现中所述的快速配对帐号数据构建而成。

请注意,表 4.2 的版本为 0x1。

连接状态字段

八位字节 数据类型 说明 是否必需?
0 uint8 字段长度和类型
0bLLLLTTTT
  • L = 连接状态的长度(以字节为单位)
  • T = 类型
0bLLLL0101
  • 长度:不固定
  • type = 0b0101
强制
1 uint8 连接状态
0bHAFRSSSS
  • H = 头部检测时
  • A = 连接可用性
  • F = 对焦模式
  • R = 自动重新连接
  • S = 连接状态
0bHAFRSSSS
强制
2 uint8 自定义数据
目前,仅包含用于描述当前音频流式传输使用情况的内容类型。探索者会将其发送给提供者。
该值由当前活跃流式传输的查找器通过消息流发送到提供程序。如果当前活跃的流式传输并非来自 Seeker,则为 0。 强制
3 - var 已连接的设备位图
显示哪些设备当前连接到提供程序的位图。所有绑定的设备均按顺序排列,一个位对应一个绑定的设备。时长取决于提供商绑定的设备数量。
如果设备当前已连接到提供程序,则映射位设置为 1,否则设置为 0。
如需了解详情,请参阅已连接设备位图
可选

表 4.1:“连接状态”字段原始数据

连接标志
  • 0bH = 头部检测时

    • 1,现在头上
    • 0,否则不戴在头上或没有超高清传感器
  • 0bA = 连接可用性

    • 1,有可用连接
    • 0,否则为 0
  • 0bF = 对焦模式

    • 1,现在在聚焦模式下,不允许切换连接用于媒体用途,即不允许从 A2DP 切换到 A2DP
    • 0,否则为 0
  • 0bR = 自动重新连接

    • 1,如果提供程序自动重新连接当前连接,这意味着用户未连接它(对于多点连接,如果其中一个现有连接自动重新连接,则应将其设置为 1)
    • 0,否则为 0
连接状态
  • 0x0:无连接
  • 0x1:分页
  • 0x2:已连接,但不传输数据
  • 0x3:非音频数据传输(仅在可切换时,如果不可切换,使用 0xF)
  • 0x4:A2DP 流式传输,AVRCP 不适用
  • 0x5:A2DP 流式传输和 AVRCP 播放
  • 0x6:HFP(电话/Voip 通话)流式传输,包括带内和非带内铃声
  • 0x7:LE 音频 - 无控制的媒体流式传输
  • 0x8:LE 音频 - 带控制的媒体流式传输
  • 0x9:LE 音频 - 通话流式传输
  • 0xA:LE 音频 - 广播
  • 0xF:暂时停用连接开关(例如固件更新)
已连接设备位图

为避免不必要的连接切换,跳转者可能需要知道耳机当前连接到的设备。例如,将耳机连接到手机后,用户不希望当一位家庭成员在平板电脑上启动 YouTube 时连接切换被中断。

请注意,此位图是匿名的,探索者无法知道哪些其他设备已与提供程序绑定。例如,以 5 个绑定设备为例:

  • 0:笔记本电脑 (0bx0000000)
  • 1:phoneA (0b0x000000)
  • 2:phoneB (0b00x00000)
  • 3:平板电脑 (0b000x0000)
  • 4:电视 (0b0000x000)

如果当前连接的设备是笔记本电脑和平板电脑,则位图的值将为 0b10010000。如果不可避免(例如,当用户将耳机恢复出厂设置或绑定的设备数量达到上限时),可以更改顺序。

可解决的随机广告

为避免跟踪并尊重用户隐私,提供商应使用 AES-CTR 通过帐号密钥轮替和加密字段:

 encrypted_connection_status_field = connection_status_raw_data ^ AES(Key, IV)

哪里

  1. 密钥派生自使用中的帐号密钥,下一部分将对此进行定义。

    • 密钥由 HKDF 函数 (IETF RFC 5869) 使用 SHA-256 哈希函数生成。

        Key = HKDF(account_key, NULL, UTF8("SASS-RRD-KEY"),16)
      
    • 提供方应使用此处的原始帐号密钥,即密钥的第一个字节为 0x04,未包含在使用模式中。

  2. IV(初始矢量)是帐号密钥数据的 2 字节盐,填充为零,即 IV 是 concat(salt,14 字节 ZERO)。

  3. 表 4.1 中定义了连接状态原始数据,如果连接状态发生变化,则应在同一通告时间范围内重新生成盐和 RPA。

这样,加密的连接状态字段会在帐号密钥数据的轮替的同时进行。

BLE 通告的结构如下:

八位字节 数据类型 说明 是否必需?
0 uint8 版本和标志 0x10 强制
1 - t 帐号关键数据 各不相同 强制
t+1 - s 电池数据 各不相同 可选
s+1 - var 随机可解析数据 各不相同 如果帐号密钥列表不为空,则必须提供,
否则会被排除。

表 4.2:包含随机可解析数据的 BLE 广播

随机可解析数据包含:

八位字节 数据类型 说明 是否必需?
0 uint8 字段长度和类型
0bLLLLTTTT
  • L = 加密数据的长度
  • T = 类型
0bLLLL0110
  • 长度:不固定
  • type = 0b0110
强制
1 - var 加密数据 各不相同 强制

表 4.2.1:随机可解析数据

例如,如果随机可解析数据包含加密连接状态字段,则解密后的结果将是 连接状态字段

为防止篡改,当通告中包含随机可解析数据时,应对上述帐号密钥数据稍作修改。通常,在构建帐号密钥过滤条件时,通过将帐号密钥过滤条件与盐相结合,会生成值 V。相反,在同时通告随机可解析数据时,值 V 应构建为:

 V = concat(account_key, salt, random_resolvable_data)

如果同时要通告电池数据和随机可解析数据,则 V 应按以下方式构建:

 V = concat(account_key, salt, battery_data, random_resolvable_data)

使用中的帐号密钥

连接切换基于帐号,因此提供程序应在 BLE 通告中包含当前连接的帐号信息。如果当前连接的设备是音频切换搜寻器,提供程序应能够获取与此搜寻器关联的帐号密钥,并使用此帐号密钥来加密连接状态字段。如果连接的音频来源是非音频切换搜寻器,提供商应使用最近用过的帐号密钥。

在计算帐号密钥过滤条件之前,提供程序应修改帐号密钥的第一个字节,以包含以下任一使用模式:

  1. 0b00000100
    此帐号密钥未在使用。
    这是默认密钥(请参阅帐号密钥)。
  2. 0b00000101
    此帐号密钥是最近使用的帐号密钥。
    连接状态字段使用此帐号密钥加密。没有当前连接状态的帐号密钥信息,这可能意味着未连接任何设备,或者连接的设备不是音频切换搜寻器。
  3. 0b00000110
    此帐号密钥是正在使用的帐号密钥。
    连接状态字段使用此帐号密钥加密,当前连接的设备与此帐号密钥关联。

音频切换载荷的示意图

下图显示了音频切换载荷的示意图。

信息

连接后,查找器和提供程序可以使用消息流同步音频切换功能、触发连接切换、设置和获取切换偏好设置、通知连接状态等。我们创建一个专用于“音频切换”的消息组和消息代码,如下所示。

消息群组名称
音频切换 0x07

以下各部分提供了每个消息代码的其他详细信息。

消息代码名称 仅限多点连接 发件人 回复者 加密 MAC ACK
获取音频切换功能 0x10 二者都有 两者都通过代码 0x11
音频切换的通知功能 0x11 二者都有 二者都有
设置多点状态 0x12 探寻者 提供商
设置切换偏好设置 0x20 探寻者 提供商
获取切换偏好设置 0x21 探寻者 提供程序(通过代码 0x22)
通知切换偏好设置 0x22 提供商 探寻者
切换活跃音频来源(到连接的设备) 0x30 探寻者 提供商
切换回断开连接的设备 0x31 探寻者 提供商
通知多点切换事件 0x32 提供商 探寻者
获取连接状态 0x33 探寻者 提供商(通过代码 0x34)
通知连接状态 0x34 提供商 探寻者
通知音频切换发起的连接 0x40 探寻者 提供商
指明使用中的帐号密钥 0x41 探寻者 提供商
发送自定义数据 0x42 探寻者 提供商
设置拖放连接目标 0x43 探寻者 提供商

表 4.3:音频切换消息

音频切换信息的 MAC 地址

为了提供消息身份验证,所有音频切换消息以及从搜寻者发送至提供方的附加数据都需要提供 消息身份验证代码。收到带有 MAC 的消息时,应予以确认,以便查找者知道提供程序是否已回应该消息。

如果消息身份验证成功,提供商应针对该消息发送 ACK:

八位字节 数据类型 说明
0 uint8 确认 0xFF
1 uint8 ACK 0x01
2 - 3 名 uint16 额外的数据长度 各不相同
4 uint8 音频切换 0x07
5 uint8 音频切换消息代码 各不相同
6 - 附加数据 各不相同

如果失败,提供商应发送该消息的 NAK:

八位字节 数据类型 说明
0 uint8 确认 0xFF
1 uint8 NAK 0x02
2 - 3 名 uint16 额外的数据长度 0x0003
4 uint8 错误原因 各不相同
5 uint8 音频切换 0x07
6 uint8 音频切换消息代码 各不相同

请注意,如果提供商是发送者,则无需使用 MAC 地址。

获取音频切换功能

音频切换提供程序和查找器都可以使用以下消息检查连接的快速配对查找器/提供程序是否支持音频切换:

八位字节 数据类型 说明
0 uint8 音频切换 0x07
1 uint8 获取音频切换功能 0x10
2 - 3 名 uint16 额外的数据长度 0

表 4.3.1.0:获取音频切换功能

音频切换的通知功能

在收到 “获取音频切换”功能消息代码后,音频切换请求器/提供程序将以以下标志之一进行响应:

八位字节 数据类型 说明
0 uint8 音频切换 0x07
1 uint8 音频切换的通知功能 0x11
2 - 3 名 uint16 额外的数据长度 如果由探索者发送,则为 20
4(如果由提供商发送)
4 - 5 名 uint16 音频切换版本代码 非零值表示它支持音频切换。当前版本(带有安全增强功能)代码为 0x0102。
0x0000 或在 1 秒内无响应表示此设备不支持音频切换
6 - 7 个 flags 提供程序的音频切换功能标志
如果由 Seeker 发送,则应忽略这两个字节。
不固定
请参阅音频切换功能标志
8 - 15 岁 消息 Nonce
仅当由探索者发送时才需要
各不相同
16 - 23 岁 消息身份验证码
仅当由探索者发送时才需要验证
各不相同

表 4.3.1.1:音频切换的通知功能

音频切换功能标志
  1. 位 0(八位字节 6,MSB):音频切换状态

    • 1,如果音频切换状态处于开启状态
    • 0,否则为 0
  2. 位 1:多点可配置性

    • 1:如果设备支持多点,并且可以在开启和关闭之间切换
    • 0,否则(不支持多点或始终开启多点功能)
  3. 位 2:多点当前状态

    • 1(如果多点功能已开启)
    • 0,否则为 0
  4. 位 3:头部检测

    • 1,如果设备支持头部检测(即使现在已关闭头部检测)
    • 0,否则为 0
  5. 位 4:头部检测当前状态

    • 1(如果头部检测已开启)
    • 0,否则(不支持头部检测或头部检测已停用)
  6. 所有其他位均预留,默认值为 0。

设置多点状态

对于音频切换搜寻器,我们可能会为用户提供用于开启/关闭多点功能的设置。查找器会使用以下消息将多点状态设置为提供程序:

八位字节 数据类型 说明
0 uint8 音频切换 0x07
1 uint8 设置多点状态 0x12
2 - 3 名 uint16 额外的数据长度 17
4 uint8 多点状态 0:关闭多点连接
1:打开多点连接
5 - 12 岁 消息 Nonce 各不相同
13 - 20 条 邮件身份验证代码 各不相同

表 4.3.1.2:设置多点状态

设置切换偏好设置

音频切换搜寻者可以修改多点的切换偏好设置,并使用以下消息将其设为提供程序:

八位字节 数据类型 说明
0 uint8 音频切换 0x07
1 uint8 设置切换偏好设置 0x20
2 - 3 名 uint16 额外的数据长度 18
4 flags 切换偏好设置 不固定
请参阅多点切换偏好设置标志
5 高级切换设置
该字节已预留,默认值为 0
各不相同
6 - 13 名 消息 Nonce 各不相同
14-21 岁 邮件身份验证代码 各不相同

表 4.3.2.0:设置切换偏好设置

多点切换偏好设置标志
  • 位 0 (MSB):A2DP 与 A2DP(默认值为 0)
  • 位 1:HFP 与 HFP(默认为 0)
  • 位 2:A2DP 与 HFP(默认值为 0)
  • 位 3:HFP 与 A2DP(默认为 1)
  • 位 4 - 7:预留
  • 上方表示的是“新的个人资料请求”与“当前的有效个人资料”
    • 0 表示不切换
    • 1 表示切换

获取切换偏好设置

音频切换探索器可以使用以下消息查询来自 Provider 的多点切换偏好设置:

八位字节 数据类型 说明
0 uint8 音频切换 0x07
1 uint8 获取切换配置 0x21
2 - 3 名 uint16 额外的数据长度 0

表 4.3.2.1:获取切换偏好设置

通知切换偏好设置

八位字节 数据类型 说明
0 uint8 音频切换 0x07
1 uint8 通知切换偏好设置 0x22
2 - 3 名 uint16 额外的数据长度 2
4 flags 切换偏好设置标志 不固定
请参阅多点切换偏好设置标志
5 高级切换设置
该字节已预留,默认值应为 0
各不相同

表 4.3.2.2:通知切换偏好设置

切换活跃音频来源(到已连接的设备)

音频切换搜寻器可以使用以下消息请求多点提供程序在已连接的设备之间切换活跃音频源:

八位字节 数据类型 说明
0 uint8 音频切换 0x07
1 uint8 切换活跃音频来源(到已连接的设备) 0x30
2 - 3 名 uint16 额外的数据长度 17
4 flags 切换活动音频来源事件标记 不固定
请参阅切换活跃音频来源事件
5 - 12 岁 消息 Nonce 各不相同
13 - 20 条 邮件身份验证代码 各不相同

表 4.3.3.0:切换活跃音频来源(切换到连接的设备)

切换进行中的音频来源事件
  • 位 0 (MSB):1 切换到此设备,0 切换到第二个连接的设备
  • 位 1:1:切换后在开关上继续播放,否则为 0。 恢复播放意味着提供程序通过 AVRCP 配置文件向查找器发送 PLAY 通知。如果之前的状态(切换之前)不是 PLAY,则提供程序应忽略此标志。
  • 位 2:1 拒绝切换设备的 SCO,否则为 0
  • 位 3:1 在切换设备上断开蓝牙,否则为 0。
  • 位 4 - 7:保留。

音频切换查找器可能并不总是正确了解其状态,因此,当查找器已经是活跃设备时,提供程序可能会收到“切换到此设备”消息。在这种情况下,为了在 Seeker 上显示正确的界面,Provider 可以发送包含错误原因的 NAK,即“0x4 - 冗余设备操作”。

切换回已断开连接的设备

如果不需要切换连接,用户可以还原切换,并且在某些情况下,最好恢复音频连接以最大限度减少中断。探索者将使用以下消息来触发切换回:

八位字节 数据类型 说明
0 uint8 音频切换 0x07
1 uint8 切换回已断开连接的设备 0x31
2 - 3 名 uint16 额外的数据长度 17
4 uint8 切换回活动 不固定
0x01:切换回
0x02:切换回去并继续播放
5 - 12 岁 消息 Nonce 各不相同
13 - 20 条 邮件身份验证代码 各不相同

表 4.3.3.1:切换回(切换到断开连接的设备)

对于多点提供程序,为了执行连接切换,提供程序可能会断开与一个音频源设备的连接,并在另一个音频源上暂停音频会话。例如,假设多点耳机连接到平板电脑和第三个受支持的音频切换设备。当手机有来电时,用户正在平板电脑上观看视频。手机将触发耳机上的连接开关,该开关需要断开第 3 个设备的连接才能连接到手机,同时暂停平板电脑上的媒体会话以获取手机铃声。如果用户拒接来电,手机可能会要求耳机“切换回去继续播放”。收到此请求后,耳机必须重新连接到第 3 台设备,并在平板电脑上继续播放已暂停的视频。

通知多点切换事件

为了让用户知道正在发生的多点切换事件,音频切换查找器可能会向用户显示通知。提供程序应向已连接的音频切换搜寻器通知切换事件。

八位字节 数据类型 说明
0 uint8 音频切换 0x07
1 uint8 通知多点切换事件
提供商应在每次切换时发送此事件,包括从音频切换查找器切换到非音频切换查找器、从非音频切换查找器切换到音频切换查找器,以及音频切换查找器到音频切换查找器
0x32
2 - 3 名 uint16 额外的数据长度 各不相同
4 uint8 切换原因 不固定
0x00:未指定
0x01:A2DP 流式传输
0x02:HFP
5 uint8 目标设备 不固定
0x01:此设备
0x02:另一个连接的设备
6 - n 号 utf8 如果目标设备是音频切换搜寻器,则使用目标设备名称
,使用接收者发送到的名称;如果不适用,则使用 BT 名称,使用其地址的最后 2 个字节
各不相同

表 4.3.3.2:通知多点切换事件

获取连接状态

探索者可以从提供程序获取当前连接状态:

八位字节 数据类型 说明
0 uint8 音频切换 0x07
1 uint8 获取连接状态 0x33
2 - 3 名 uint16 额外的数据长度 0

表 4.3.3.3:获取连接状态

收到此消息后,提供程序应通过消息代码 0x34 进行响应, 通知连接状态

通知连接状态

如 BLE 通告载荷中所定义,对于多点提供程序,如果连接状态发生变化(更改通告包除外),提供程序还应通知使用同一帐号密钥的已连接探索者相关变更。如果提供器已与音频切换探索器和非音频切换探索器连接,且非音频切换探索器处于活跃状态,则提供程序还应通知已连接的音频切换探索器连接状态(使用探索器的帐号密钥)。

八位字节 数据类型 说明
0 uint8 音频切换 0x07
1 uint8 通知连接状态 0x34
2 - 3 名 uint16 额外的数据长度 各不相同
4 uint8 活跃设备标志 不固定
0x00:此搜寻器处于被动状态,并且主动设备使用相同的帐号密钥
0x01:此搜寻器是有源设备
0x02:此搜寻器是被动的,并且主动设备是非音频切换搜寻器。
5 - n 加密连接状态 各不相同
n+1 - n+8 消息 Nonce 各不相同

表 4.3.3.4:通知连接状态

加密连接状态消息

 encrypted_connection_status = connection_status_raw_data ^ AES(Key, IV)

其中:

通知音频切换发起的连接

音频切换提供程序可能需要了解连接切换是否由音频切换触发以做出不同的回应,例如为音频切换事件停用耳标。查找器发送消息,以通知提供程序此连接是音频切换发起的连接。

八位字节 数据类型 说明
0 uint8 音频切换 0x07
1 uint8 通知音频切换发起的连接 0x40
2 - 3 名 uint16 额外的数据长度 17
4 uint8 音频切换发起的连接指示 不固定
0:此连接不是由音频切换触发的
1:这是音频切换发起的连接
5 - 12 岁 消息 Nonce 各不相同
13 - 20 条 邮件身份验证代码 各不相同

表 4.3.4.0:通知音频切换发起的连接

指明使用中的帐号密钥

如果查找器上的多个帐号密钥(例如多用户)与提供程序相关联,查找器将使用下面的消息来指示正在使用的帐号密钥。

八位字节 数据类型 说明
0 uint8 音频切换 0x07
1 uint8 指明使用中的帐号密钥 0x41
2 - 3 名 uint16 额外的数据长度 22
4 - 9 名 utf8 使用中的字符串 UTF8(“使用中”)
10 - 17 岁 消息 Nonce 各不相同
18-25 岁 邮件身份验证代码 各不相同

表 4.3.4.1:指明使用的帐号密钥

收到此消息后,提供方可以通过验证消息身份验证代码来了解正在使用哪个帐号密钥。

发送自定义数据

处于活跃状态的音频切换搜寻器可以将音频流的信息(例如音频使用情况)封装在自定义数据字节中,并使用以下消息将其发送给提供程序:

八位字节 数据类型 说明
0 uint8 音频切换 0x07
1 uint8 发送自定义数据 0x42
2 - 3 名 uint16 额外的数据长度 17
4 uint8 自定义数据 各不相同
5 - 12 岁 消息 Nonce 各不相同
13 - 20 条 邮件身份验证代码 各不相同

表 4.3.4.2:发送自定义数据

收到自定义数据后,提供程序将更新广告包以包含自定义数据。对于多点提供程序,它还应使用同一帐号密钥将连接状态更改通知给另一个已连接的探索者。

设置拖放连接目标

在多点耳机上,如果要丢弃的首选连接不是最近用过的连接,音频切换查找器可以使用以下消息告知提供程序要丢弃哪个设备:

八位字节 数据类型 说明
0 uint8 音频切换 0x07
1 uint8 设置拖放连接目标 0x43
2 - 3 名 uint16 额外的数据长度 17
4 uint8 要丢弃的目标已连接设备 不固定
1:此设备
5 - 12 岁 消息 Nonce 各不相同
13 - 20 条 邮件身份验证代码 各不相同

表 4.3.4.3:设置拖放连接目标

参考实现

如需查看参考实现,请参阅 Nearby 嵌入式 SDK 库