【android bluetooth 协议分析 11】【AVDTP详解 4】【A2dp Sink 状态机通俗讲解】
A2dp Sink 状态机通俗讲解
在 Android 蓝牙协议栈中,A2DP Sink(接收端)负责接收音频流并播放,比如车载娱乐系统、蓝牙音箱等。其核心逻辑由 状态机(State Machine) 管理,保证从设备发现、连接建立到音频播放的每一步都能正确处理异常和事件。
在 AOSP 中,这个状态机的实现函数是 bta_av_better_stream_state_machine,它以 每个音频流控制块(SCB, tBTA_AV_SCB) 为单位,根据当前状态和事件决定下一步动作和状态切换。
一、A2DP Sink 的主要状态
根据源码,状态机有如下关键状态:
| 状态 | 描述 |
|---|---|
BTA_AV_INIT_SST | 初始状态,等待远端设备发起连接或本地发起连接请求。 |
BTA_AV_INCOMING_SST | 接收到远端连接请求,正在处理连接协商(配置、认证等)。 |
BTA_AV_OPENING_SST | 本地主动发起连接,正在进行 SDP 查询和信道配置。 |
BTA_AV_OPEN_SST | 连接已经建立,媒体信道准备就绪,等待或进行音频播放。 |
BTA_AV_RCFG_SST | 流重配置中(例如音质或编码参数调整)。 |
BTA_AV_CLOSING_SST | 连接正在关闭,释放资源。 |
每个状态对应 A2DP Sink 的协议阶段,比如 SDP 查询、信道建立、音频流开始等。
二、事件驱动状态切换
状态机是 事件驱动 的,每个状态会对不同事件做出不同反应。以下举几个典型例子:
1. 初始状态(BTA_AV_INIT_SST)
-
事件:
BTA_AV_API_OPEN_EVT
本地发起连接 → 切换到BTA_AV_OPENING_SST→ 执行bta_av_do_disc_a2dp()进行 SDP 查询。 -
事件:
BTA_AV_STR_CONFIG_IND_EVT
远端发起连接 → 切换到BTA_AV_INCOMING_SST→ 执行bta_av_config_ind()响应配置。 -
事件:
BTA_AV_API_OFFLOAD_START_EVT
开启音频硬件加速 → 执行bta_av_offload_req()。
2. 远端连接请求处理中(BTA_AV_INCOMING_SST)
-
事件:
BTA_AV_STR_OPEN_OK_EVT
信道建立完成 → 切换到BTA_AV_OPEN_SST→ 执行bta_av_str_opened(),音频准备就绪。 -
事件:
BTA_AV_API_CLOSE_EVT或BTA_AV_AVDT_DISCONNECT_EVT
本地或远端请求关闭 → 切换到BTA_AV_CLOSING_SST→ 执行关闭和资源清理。
3. 主动连接处理中(BTA_AV_OPENING_SST)
-
事件:
BTA_AV_SDP_DISC_OK_EVT
SDP 查询成功 → 执行bta_av_connect_req()建立信道。 -
事件:
BTA_AV_STR_OPEN_FAIL_EVT
信道打开失败 → 切换到BTA_AV_CLOSING_SST→ 执行bta_av_open_failed()。
4. 连接已打开(BTA_AV_OPEN_SST)
-
事件:
BTA_AV_AP_START_EVT
开始播放音频 → 执行bta_av_do_start()。 -
事件:
BTA_AV_SRC_DATA_READY_EVT
有音频数据 → 执行bta_av_data_path(),把音频传给解码器/播放设备。 -
事件:
BTA_AV_API_RECONFIG_EVT
流重配置 → 切换到BTA_AV_RCFG_SST→ 执行bta_av_reconfig()。 -
事件:
BTA_AV_API_CLOSE_EVT或BTA_AV_AVDT_DISCONNECT_EVT
停止播放或断开连接 → 切换到BTA_AV_CLOSING_SST→ 执行bta_av_do_close()或bta_av_str_closed()。
三、状态机运行原理
-
保存当前状态
previous_state = p_scb->state,方便打印日志和判断是否发生状态切换。 -
根据状态和事件选择处理函数
event_handler1和event_handler2指向对应处理函数,可以同时执行两个动作(例如先关闭信道,再释放资源)。 -
状态切换
如果事件需要改变状态,则p_scb->state = 新状态。 -
执行事件处理函数
最后调用event_handler1(p_scb, p_data)和event_handler2(p_scb, p_data)执行具体动作。 -
日志打印
使用 LOG_INFO 或 LOG_DEBUG 打印状态和事件,便于调试。
四、状态切换顺序示意
场景 1:主动连接手机(本地发起)
[INIT] --API_OPEN--> [OPENING]--SDP_DISC_OK--> CONNECT_REQ --> [OPEN]--STR_OPEN_FAIL--> [CLOSING] --STR_CLOSE--> [INIT]
流程说明:
-
本地发起连接 → 状态切换到
OPENING。 -
SDP 查询成功 → 发起 AVDTP 信道连接。
-
信道打开成功 → 状态切换到
OPEN,准备接收音频。 -
信道打开失败 → 状态切换到
CLOSING→ 清理资源 → 回到INIT。
场景 2:被动连接手机(远端发起)
[INIT] --STR_CONFIG_IND--> [INCOMING]--STR_OPEN_OK--> [OPEN]--API_CLOSE/AVDT_DISCONNECT--> [CLOSING] --STR_CLOSE--> [INIT]
流程说明:
-
手机发起连接 → 车机接收到配置请求 → 状态切换到
INCOMING。 -
信道打开成功 → 状态切换到
OPEN,音频流可用。 -
远端或本地发起断开 → 状态切换到
CLOSING→ 清理资源 → 回到INIT。
场景 3:音频播放控制
[OPEN] --AP_START--> start audio--SRC_DATA_READY--> data path active--AP_STOP--> stop audio--API_RECONFIG--> [RCFG] --STR_RECONFIG_CFM--> [OPEN]--API_CLOSE/AVDT_DISCONNECT--> [CLOSING] --STR_CLOSE--> [INIT]
流程说明:
-
音频开始播放 → 调用
bta_av_do_start()。 -
有音频数据 → 走数据通路发送到解码器。
-
停止播放 → 调用
bta_av_str_stopped()。 -
流重配置 → 状态切换到
RCFG→ 配置完成回到OPEN。 -
关闭或断开 → 状态切换到
CLOSING→ 清理 → 回到INIT。
场景 4:关闭或断开连接
[OPEN]/[INCOMING]/[OPENING] --API_CLOSE/AVDT_DISCONNECT--> [CLOSING]
[CLOSING] --STR_CLOSE--> [INIT]
流程说明:
-
不论当前处于
OPEN、INCOMING还是OPENING,一旦收到关闭或断开事件 → 切换到CLOSING。 -
执行关闭操作和资源清理 → 信道关闭完成 → 回到
INIT。
💡 说明:
-
每个场景只关注本流程相关状态和事件,不与其他流程混合。
-
通过这种分场景方法,可以快速理解 A2DP Sink 在主动/被动连接、播放控制、断开等不同情况下的状态切换。

五、生活化类比
可以把 A2DP Sink 状态机理解为接收音频的“管道工”:
-
INIT:管道工休息中,等水(音频)来。
-
INCOMING / OPENING:管道工开始准备管道(信道),检查接口(SDP/配置)。
-
OPEN:管道已连通,音频流可以顺畅流动。
-
RCFG:调整管道参数(音质/编码)。
-
CLOSING:管道收回,清理杂物(释放资源)。
每个事件都是外界或内部触发的“指令”,状态机保证管道工不会做错事,比如在关闭时不会播放音频,也不会在未建立信道时发送数据。
六、bta_av_better_stream_state_machine 分析
- system/bta/av/bta_av_ssm.cc
// 说明:注释解释了每个状态的语义、该状态下事件的处理逻辑、对应的 AVDTP 信令阶段、以及常见的 race/时序注意点。
// 很多事件处理函数(如 bta_av_do_disc_a2dp/bta_av_config_ind 等)封装了更详细的协议操作。static void bta_av_better_stream_state_machine(tBTA_AV_SCB* p_scb,uint16_t event,tBTA_AV_DATA* p_data) {// 记录上一次状态以便日志输出和调试uint8_t previous_state = p_scb->state;// 两个回调指针:有些事件需要一个主处理动作和一个辅助动作(例如 start timer / cleanup 等)tBTA_AV_ACT event_handler1 = nullptr;tBTA_AV_ACT event_handler2 = nullptr;// 根据当前状态分发事件逻辑(典型有限状态机结构)switch (p_scb->state) {/*************************************************************************** BTA_AV_INIT_SST* ----------------* 含义:初始/空闲状态。尚未建立 AVDTP signaling 或 media channel。* 对应协议:等待连接(等待对端发起 AVDTP 或本地通过 API 发起 SDP/连接)。* 典型进入条件:模块刚启动或上一次连接彻底释放后回到此状态。**************************************************************************/case BTA_AV_INIT_SST:switch (event) {case BTA_AV_API_OPEN_EVT:// 上层请求打开与 remote 的 A2DP 会话(主动发起连接)// 设置状态为 OPENING(主动连接流程开始),并在 event_handler1 中触发 SDP/发现流程p_scb->state = BTA_AV_OPENING_SST;// bta_av_do_disc_a2dp 会去做 SDP 查询(找 A2DP 服务),随后触发 AVDTP 建链event_handler1 = &bta_av_do_disc_a2dp;break;case BTA_AV_API_CLOSE_EVT:// 收到 close 请求,但处于 INIT(未连接)时只是做清理/回调event_handler1 = &bta_av_cleanup;break;case BTA_AV_SDP_DISC_OK_EVT:case BTA_AV_SDP_DISC_FAIL_EVT:// SDP 完成事件(成功或失败),处于 INIT 时直接释放临时 sdp 数据event_handler1 = &bta_av_free_sdb; // 清理 sdp 数据结构break;case BTA_AV_STR_CONFIG_IND_EVT:// 收到对端的 SetConfiguration(远端要配置媒体通道)// 这表示远端主动发起链路,切换到 INCOMING 状态并处理配置请求p_scb->state = BTA_AV_INCOMING_SST;event_handler1 = &bta_av_config_ind; // 处理 AVDTP set configbreak;case BTA_AV_ACP_CONNECT_EVT:// 被动 accept 到一个连接(L2CAP/AVDTP 已建立但尚未配置)// 直接转到 INCOMING 状态,等待后续配置/open 消息p_scb->state = BTA_AV_INCOMING_SST;break;case BTA_AV_API_OFFLOAD_START_EVT:// 请求开始 offload(硬件解码/传输 offload)event_handler1 = &bta_av_offload_req;break;case BTA_AV_API_OFFLOAD_START_RSP_EVT:// offload 请求的响应event_handler1 = &bta_av_offload_rsp;break;}break;/*************************************************************************** BTA_AV_INCOMING_SST* --------------------* 含义:这是 "被动接入" 的处理中间态:对端(source)已建立 signaling 或发送了配置请求。* 对应协议:AVDTP 的 SetConfiguration/Discover/GetCapabilities/Open 等被动接收路径。* 典型进入条件:收到 STR_CONFIG_IND、ACP_CONNECT、对端发起 Discover/GetCap/Open。**************************************************************************/case BTA_AV_INCOMING_SST:switch (event) {case BTA_AV_API_OPEN_EVT:// 上层调用 open(在 already incoming 模式下),处理为 open at incoming// 通常会触发 accept/open 的继续流程(例如发送 GetCapabilities 或等待 Open)event_handler1 = &bta_av_open_at_inc;break;case BTA_AV_API_CLOSE_EVT:// 上层要求关闭:切换到 CLOSING 状态并先调用 cco_close(关闭 connection control)// 再调用 disconnect_req(发起断开请求)。这里使用两个 handler 保证顺序。p_scb->state = BTA_AV_CLOSING_SST;event_handler1 = &bta_av_cco_close; // 触发 AVDTP 关闭或本地 cleanupevent_handler2 = &bta_av_disconnect_req; // 请求断开 L2CAP/ACLbreak;case BTA_AV_API_PROTECT_REQ_EVT:// 上层要求安全(保护)操作,例如 ACL 加密/授权等event_handler1 = &bta_av_security_req;break;case BTA_AV_API_PROTECT_RSP_EVT:// 上层对于 security 的应答event_handler1 = &bta_av_security_rsp;break;case BTA_AV_CI_SETCONFIG_OK_EVT:// 内部模块(CI)告知 setconfig 本地验证成功// 先处理 setconfig rsp,再启动 RC(remote control)相关超时定时器event_handler1 = &bta_av_setconfig_rsp;event_handler2 = &bta_av_st_rc_timer;break;case BTA_AV_CI_SETCONFIG_FAIL_EVT:// setconfig 失败:退回 INIT 并做 reject + cleanupp_scb->state = BTA_AV_INIT_SST;event_handler1 = &bta_av_setconfig_rej;event_handler2 = &bta_av_cleanup;break;case BTA_AV_SDP_DISC_OK_EVT:case BTA_AV_SDP_DISC_FAIL_EVT:// 发现服务后释放 sdp buffer(和 INIT 状态类似)event_handler1 = &bta_av_free_sdb;break;case BTA_AV_STR_DISC_OK_EVT:// 收到 AVDTP discover 的结果(处于被动方时用于记录/响应)event_handler1 = &bta_av_disc_res_as_acp;break;case BTA_AV_STR_GETCAP_OK_EVT:// GetCapabilities 成功,保存 codec 能力event_handler1 = &bta_av_save_caps;break;case BTA_AV_STR_OPEN_OK_EVT:// 对端发送 AVDTP Open 成功(Media channel 已建立)// 进入 OPEN 状态,调用 bta_av_str_opened 做后续处理(例如通知上层)p_scb->state = BTA_AV_OPEN_SST;event_handler1 = &bta_av_str_opened;break;case BTA_AV_STR_CLOSE_EVT:// 收到对端 close:回到 INIT 并进入关闭/cleanup 流程p_scb->state = BTA_AV_INIT_SST;event_handler1 = &bta_av_cco_close;event_handler2 = &bta_av_cleanup;break;case BTA_AV_STR_CONFIG_IND_EVT:// 再次收到 config_ind(可能是重复或迟到的消息),交给 config_ind 处理event_handler1 = &bta_av_config_ind;break;case BTA_AV_STR_SECURITY_IND_EVT:// AVDTP 层的安全指示event_handler1 = &bta_av_security_ind;break;case BTA_AV_STR_SECURITY_CFM_EVT:// AVDTP 安全确认event_handler1 = &bta_av_security_cfm;break;case BTA_AV_AVDT_DISCONNECT_EVT:// AVDTP 层报告断开(例如 L2CAP 或 ACL 断开)p_scb->state = BTA_AV_CLOSING_SST;event_handler1 = &bta_av_cco_close; // 处理本地 closeevent_handler2 = &bta_av_disconnect_req; // 发起断开清理break;case BTA_AV_AVDT_DELAY_RPT_EVT:// 收到延时上报:用于 A2DP delay reporting (用于同步/latency compensation)event_handler1 = &bta_av_delay_co;break;case BTA_AV_API_OFFLOAD_START_EVT:case BTA_AV_API_OFFLOAD_START_RSP_EVT:// offload 请求/响应在任何状态都可以处理event_handler1 = (event == BTA_AV_API_OFFLOAD_START_EVT) ?&bta_av_offload_req : &bta_av_offload_rsp;break;}break;/*************************************************************************** BTA_AV_OPENING_SST* -------------------* 含义:主动发起连接流程中(正在通过 SDP -> AVDTP Discover -> SetConfig -> Open)。* 对应协议:主动方的 Discover/GetCap/SetConfig/Open 的执行路径。* 注意:此阶段会有较多的失败分支、超时以及 role switch 的处理。**************************************************************************/case BTA_AV_OPENING_SST:switch (event) {case BTA_AV_API_CLOSE_EVT:// 在正在打开时上层要求 close:转到 CLOSING 并执行 do_close(撤销发起)p_scb->state = BTA_AV_CLOSING_SST;event_handler1 = &bta_av_do_close;break;case BTA_AV_API_PROTECT_REQ_EVT:event_handler1 = &bta_av_security_req;break;case BTA_AV_API_PROTECT_RSP_EVT:event_handler1 = &bta_av_security_rsp;break;case BTA_AV_SDP_DISC_OK_EVT:// SDP 发现 OK:通常衔接为 connect_req(如果不是 PTS 特殊流程)if (osi_property_get_bool("xxx.bluetooth.pts", false)) {// PTS 测试模式:可能绕过正常流程做特殊处理LOG_INFO(" PTS process.");} else {LOG_INFO(" normal process.");event_handler1 = &bta_av_connect_req; // 发起 AVDTP 连接请求}break;case BTA_AV_SDP_DISC_FAIL_EVT:// 即便 SDP 失败,仍可尝试 connect (兼容性路径)event_handler1 = &bta_av_connect_req;break;case BTA_AV_STR_DISC_OK_EVT:// AVDTP discover 返回(用于记录对端 stream endpoint 列表)event_handler1 = &bta_av_disc_results;break;case BTA_AV_STR_DISC_FAIL_EVT:// discover fail -> 打开失败 -> 进入 CLOSINGp_scb->state = BTA_AV_CLOSING_SST;event_handler1 = &bta_av_open_failed;break;case BTA_AV_STR_GETCAP_OK_EVT:// GetCapabilities 成功 -> 处理 capability 结果, 可能继续 setconfigevent_handler1 = &bta_av_getcap_results;break;case BTA_AV_STR_GETCAP_FAIL_EVT:// 获取 capabilities 失败 -> open 失败处理p_scb->state = BTA_AV_CLOSING_SST;event_handler1 = &bta_av_open_failed;break;case BTA_AV_STR_OPEN_OK_EVT:// AVDTP Open 成功,media channel 建立 -> 进入 OPEN 状态p_scb->state = BTA_AV_OPEN_SST;// 先启动 remote-control timer, 然后执行 str_opened(通知上层/设置参数)event_handler1 = &bta_av_st_rc_timer;event_handler2 = &bta_av_str_opened;break;case BTA_AV_STR_OPEN_FAIL_EVT:// Open 失败 -> 进入 CLOSING,执行 open_failed 逻辑p_scb->state = BTA_AV_CLOSING_SST;event_handler1 = &bta_av_open_failed;break;case BTA_AV_STR_CONFIG_IND_EVT:// 在主动打开期间,远端发来 config_ind(可能 race) -> 切换到 INCOMING 来处理p_scb->state = BTA_AV_INCOMING_SST;event_handler1 = &bta_av_config_ind;break;case BTA_AV_STR_SECURITY_IND_EVT:event_handler1 = &bta_av_security_ind;break;case BTA_AV_STR_SECURITY_CFM_EVT:event_handler1 = &bta_av_security_cfm;break;case BTA_AV_AVRC_TIMER_EVT:// AVRCP 定时器事件,可能用于在打开流程中等待 role switch 或 RC 建立event_handler1 = &bta_av_switch_role;break;case BTA_AV_AVDT_CONNECT_EVT:// AVDT lower-layer 报告 connect 完成 -> 继续做 discoverevent_handler1 = &bta_av_discover_req;break;case BTA_AV_AVDT_DISCONNECT_EVT:// 连接在打开阶段被断开 -> 返回 INIT 并报告连接失败p_scb->state = BTA_AV_INIT_SST;event_handler1 = &bta_av_conn_failed;break;case BTA_AV_ROLE_CHANGE_EVT:// 蓝牙 role(master/slave)改变,需要处理 role 修改的结果event_handler1 = &bta_av_role_res;break;case BTA_AV_AVDT_DELAY_RPT_EVT:// delay report 在任何阶段都可以到达,用于同步event_handler1 = &bta_av_delay_co;break;case BTA_AV_API_OFFLOAD_START_EVT:case BTA_AV_API_OFFLOAD_START_RSP_EVT:event_handler1 = (event == BTA_AV_API_OFFLOAD_START_EVT) ?&bta_av_offload_req : &bta_av_offload_rsp;break;}break;/*************************************************************************** BTA_AV_OPEN_SST* ----------------* 含义:流已打开(AVDTP Open success),可以进行 Start/Stop/重配置或关闭。* 对应协议:AVDTP Open 成功 => A2DP 可开始 Start/传输媒体。**************************************************************************/case BTA_AV_OPEN_SST:switch (event) {case BTA_AV_API_CLOSE_EVT:// 上层要求关闭 -> 进入 CLOSING,执行 do_close 清理 media/信令p_scb->state = BTA_AV_CLOSING_SST;event_handler1 = &bta_av_do_close;break;case BTA_AV_AP_START_EVT:// 上层要求开始播放 -> 执行 do_start(发送 Start 到对端/准备数据路径)event_handler1 = &bta_av_do_start;break;case BTA_AV_AP_STOP_EVT:// 上层要求停止/挂起 -> 处理 stopevent_handler1 = &bta_av_str_stopped;break;case BTA_AV_API_RECONFIG_EVT:// 上层请求重配置(改变 codec 参数等),进入 RCFG 状态p_scb->state = BTA_AV_RCFG_SST;event_handler1 = &bta_av_reconfig;break;case BTA_AV_API_PROTECT_REQ_EVT:case BTA_AV_API_PROTECT_RSP_EVT:event_handler1 = (event == BTA_AV_API_PROTECT_REQ_EVT) ?&bta_av_security_req : &bta_av_security_rsp;break;case BTA_AV_API_RC_OPEN_EVT:// 请求打开 AVRCP remote control channel:先设置 use_rc,再打开 rcevent_handler1 = &bta_av_set_use_rc;event_handler2 = &bta_av_open_rc;break;case BTA_AV_SRC_DATA_READY_EVT:// 源数据可送来 -> 走数据路径(例如写入 L2CAP / push 到 audio HAL)event_handler1 = &bta_av_data_path;break;case BTA_AV_SDP_DISC_OK_EVT:case BTA_AV_SDP_DISC_FAIL_EVT:// 发现 svc 完成后释放 bufferevent_handler1 = &bta_av_free_sdb;break;case BTA_AV_STR_GETCAP_OK_EVT:// GetCapabilities 返回 -> 保存 capabilityevent_handler1 = &bta_av_save_caps;break;case BTA_AV_STR_START_OK_EVT:// 收到对端 Start confirm -> 处理 start_ok(可能启动解码/播放)event_handler1 = &bta_av_start_ok;break;case BTA_AV_STR_START_FAIL_EVT:// Start 失败 -> 处理 start_failedevent_handler1 = &bta_av_start_failed;break;case BTA_AV_STR_CLOSE_EVT:// 对端主动 close -> 回到 INIT 并执行 str_closed(通知上层)p_scb->state = BTA_AV_INIT_SST;event_handler1 = &bta_av_str_closed;break;case BTA_AV_STR_CONFIG_IND_EVT:// 若在 OPEN 时收到对端的 config_ind,通常应拒绝(已经 open)event_handler1 = &bta_av_setconfig_rej;break;case BTA_AV_STR_SECURITY_IND_EVT:case BTA_AV_STR_SECURITY_CFM_EVT:event_handler1 = (event == BTA_AV_STR_SECURITY_IND_EVT) ?&bta_av_security_ind : &bta_av_security_cfm;break;case BTA_AV_STR_WRITE_CFM_EVT:// L2CAP 写确认:先清 congestion,再继续数据路径(双 handler)event_handler1 = &bta_av_clr_cong;event_handler2 = &bta_av_data_path;break;case BTA_AV_STR_SUSPEND_CFM_EVT:// Suspend 确认(对端已停止流),回调处理event_handler1 = &bta_av_suspend_cfm;break;case BTA_AV_AVRC_TIMER_EVT:// AVRCP timer 到,尝试打开 RCevent_handler1 = &bta_av_open_rc;break;case BTA_AV_AVDT_DISCONNECT_EVT:// AVDTP 层断开 -> 直接回到 INIT 并通知上层 stream closedp_scb->state = BTA_AV_INIT_SST;event_handler1 = &bta_av_str_closed;break;case BTA_AV_ROLE_CHANGE_EVT:event_handler1 = &bta_av_role_res;break;case BTA_AV_AVDT_DELAY_RPT_EVT:event_handler1 = &bta_av_delay_co;break;case BTA_AV_API_OFFLOAD_START_EVT:case BTA_AV_API_OFFLOAD_START_RSP_EVT:event_handler1 = (event == BTA_AV_API_OFFLOAD_START_EVT) ?&bta_av_offload_req : &bta_av_offload_rsp;break;}break;/*************************************************************************** BTA_AV_RCFG_SST* ----------------* 含义:重配置状态(reconfiguration)——通常用于 codec 参数变更。* 协议对应:AVDTP Reconfigure / Suspend / Open 的组合处理路径。**************************************************************************/case BTA_AV_RCFG_SST:switch (event) {case BTA_AV_API_CLOSE_EVT:// 重配置期间被要求 close -> 进入 CLOSING 并请求断开p_scb->state = BTA_AV_CLOSING_SST;event_handler1 = &bta_av_disconnect_req;break;case BTA_AV_API_RECONFIG_EVT:// 再次收到 reconfig 请求 -> 处理 reconfigevent_handler1 = &bta_av_reconfig;break;case BTA_AV_SDP_DISC_OK_EVT:case BTA_AV_SDP_DISC_FAIL_EVT:event_handler1 = &bta_av_free_sdb;break;case BTA_AV_STR_DISC_OK_EVT:event_handler1 = &bta_av_disc_results;break;case BTA_AV_STR_DISC_FAIL_EVT:// discover 失败,认为 stream closedp_scb->state = BTA_AV_INIT_SST;event_handler1 = &bta_av_str_closed;break;case BTA_AV_STR_GETCAP_OK_EVT:event_handler1 = &bta_av_getcap_results;break;case BTA_AV_STR_GETCAP_FAIL_EVT:p_scb->state = BTA_AV_INIT_SST;event_handler1 = &bta_av_str_closed;break;case BTA_AV_STR_OPEN_OK_EVT:// reconfig 打开成功 -> 返回 OPENp_scb->state = BTA_AV_OPEN_SST;event_handler1 = &bta_av_rcfg_str_ok;break;case BTA_AV_STR_OPEN_FAIL_EVT:event_handler1 = &bta_av_rcfg_failed;break;case BTA_AV_STR_CLOSE_EVT:event_handler1 = &bta_av_rcfg_connect; // 重新尝试 connectbreak;case BTA_AV_STR_CONFIG_IND_EVT:// 收到 config_ind -> 拒绝,因为在重配置中需要按流程处理event_handler1 = &bta_av_setconfig_rej;break;case BTA_AV_STR_SUSPEND_CFM_EVT:// suspend 确认 -> 先处理 suspend_cfm,再继续 suspend 流程event_handler1 = &bta_av_suspend_cfm;event_handler2 = &bta_av_suspend_cont;break;case BTA_AV_STR_RECONFIG_CFM_EVT:// reconfig 确认 -> 处理 rcfg cfmevent_handler1 = &bta_av_rcfg_cfm;break;case BTA_AV_AVDT_CONNECT_EVT:// AVDT connect -> 调用 rcfg_open 继续 openevent_handler1 = &bta_av_rcfg_open;break;case BTA_AV_AVDT_DISCONNECT_EVT:// AVDT disconnect -> 处理 rcfg_disconnected 等event_handler1 = &bta_av_rcfg_discntd;break;case BTA_AV_AVDT_DELAY_RPT_EVT:event_handler1 = &bta_av_delay_co;break;case BTA_AV_API_OFFLOAD_START_EVT:case BTA_AV_API_OFFLOAD_START_RSP_EVT:event_handler1 = (event == BTA_AV_API_OFFLOAD_START_EVT) ?&bta_av_offload_req : &bta_av_offload_rsp;break;}break;/*************************************************************************** BTA_AV_CLOSING_SST* -------------------* 含义:连接/流正在关闭阶段(等待断开完成与资源清理)。* 典型进入条件:API close, open fail, avdtp disconnect 等。**************************************************************************/case BTA_AV_CLOSING_SST:switch (event) {case BTA_AV_API_CLOSE_EVT:// 在 closing 时如果再收到 close 就直接发起 disconnectevent_handler1 = &bta_av_disconnect_req;break;case BTA_AV_SDP_DISC_OK_EVT:case BTA_AV_SDP_DISC_FAIL_EVT:// sdp 在关闭期完成 -> 直接回到 INIT 并报 sdp_failedp_scb->state = BTA_AV_INIT_SST;event_handler1 = &bta_av_sdp_failed;break;case BTA_AV_STR_OPEN_OK_EVT:// 在 closing 期收到了 open_ok(race 情况) -> 仍然执行 do_close 来收尾event_handler1 = &bta_av_do_close;break;case BTA_AV_STR_OPEN_FAIL_EVT:// open fail -> 发起断开event_handler1 = &bta_av_disconnect_req;break;case BTA_AV_STR_CLOSE_EVT:// stream close -> 发起断开event_handler1 = &bta_av_disconnect_req;break;case BTA_AV_STR_CONFIG_IND_EVT:// 收到 config 请求 -> 明确拒绝(setconfig_rej)event_handler1 = &bta_av_setconfig_rej;break;case BTA_AV_STR_SECURITY_IND_EVT:// 收到 security 请求 -> 拒绝安全请求event_handler1 = &bta_av_security_rej;break;case BTA_AV_AVDT_DISCONNECT_EVT:// AVDTP 报告断开 -> 回到 INIT,执行 str_closed 回调p_scb->state = BTA_AV_INIT_SST;event_handler1 = &bta_av_str_closed;break;case BTA_AV_API_OFFLOAD_START_EVT:case BTA_AV_API_OFFLOAD_START_RSP_EVT:event_handler1 = (event == BTA_AV_API_OFFLOAD_START_EVT) ?&bta_av_offload_req : &bta_av_offload_rsp;break;}break;}// 状态变更日志:打印前后状态、事件编号、peer 地址等,便于调试时追踪状态迁移路径if (previous_state != p_scb->state) {LOG_INFO("peer %s p_scb=%#x(%p) AV event=0x%x(%s) state=%d(%s) -> %d(%s)",p_scb->PeerAddress().ToString().c_str(), p_scb->hndl, p_scb, event,bta_av_evt_code(event), previous_state,bta_av_sst_code(previous_state), p_scb->state,bta_av_sst_code(p_scb->state));} else {LOG_DEBUG("peer %s p_scb=%#x(%p) AV event=0x%x(%s) state=%d(%s)",p_scb->PeerAddress().ToString().c_str(), p_scb->hndl, p_scb,event, bta_av_evt_code(event), p_scb->state,bta_av_sst_code(p_scb->state));}// 执行 handler(先主后辅)if (event_handler1 != nullptr) {event_handler1(p_scb, p_data);}if (event_handler2 != nullptr) {event_handler2(p_scb, p_data);}
}
七、总结
-
A2DP Sink 状态机是事件驱动的,核心函数是
bta_av_better_stream_state_machine。 -
状态划分清晰:INIT、INCOMING、OPENING、OPEN、RCFG、CLOSING。
-
每个状态对不同事件有不同响应,通过
event_handler1/2执行操作。 -
状态切换顺序反映了协议栈的实际操作流程,包括 SDP 查询、信道建立、配置协商、流开启和关闭。
-
通过日志打印和事件处理函数的组合,可以高效、安全地处理音频连接。
