当前位置: 首页 > news >正文

【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_EVTBTA_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_EVTBTA_AV_AVDT_DISCONNECT_EVT
    停止播放或断开连接 → 切换到 BTA_AV_CLOSING_SST → 执行 bta_av_do_close()bta_av_str_closed()


三、状态机运行原理

  1. 保存当前状态
    previous_state = p_scb->state,方便打印日志和判断是否发生状态切换。

  2. 根据状态和事件选择处理函数
    event_handler1event_handler2 指向对应处理函数,可以同时执行两个动作(例如先关闭信道,再释放资源)。

  3. 状态切换
    如果事件需要改变状态,则 p_scb->state = 新状态

  4. 执行事件处理函数
    最后调用 event_handler1(p_scb, p_data)event_handler2(p_scb, p_data) 执行具体动作。

  5. 日志打印
    使用 LOG_INFO 或 LOG_DEBUG 打印状态和事件,便于调试。

四、状态切换顺序示意

场景 1:主动连接手机(本地发起)

[INIT] --API_OPEN--> [OPENING]--SDP_DISC_OK--> CONNECT_REQ --> [OPEN]--STR_OPEN_FAIL--> [CLOSING] --STR_CLOSE--> [INIT]

流程说明

  1. 本地发起连接 → 状态切换到 OPENING

  2. SDP 查询成功 → 发起 AVDTP 信道连接。

  3. 信道打开成功 → 状态切换到 OPEN,准备接收音频。

  4. 信道打开失败 → 状态切换到 CLOSING → 清理资源 → 回到 INIT

场景 2:被动连接手机(远端发起)

[INIT] --STR_CONFIG_IND--> [INCOMING]--STR_OPEN_OK--> [OPEN]--API_CLOSE/AVDT_DISCONNECT--> [CLOSING] --STR_CLOSE--> [INIT]

流程说明

  1. 手机发起连接 → 车机接收到配置请求 → 状态切换到 INCOMING

  2. 信道打开成功 → 状态切换到 OPEN,音频流可用。

  3. 远端或本地发起断开 → 状态切换到 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]

流程说明

  1. 音频开始播放 → 调用 bta_av_do_start()

  2. 有音频数据 → 走数据通路发送到解码器。

  3. 停止播放 → 调用 bta_av_str_stopped()

  4. 流重配置 → 状态切换到 RCFG → 配置完成回到 OPEN

  5. 关闭或断开 → 状态切换到 CLOSING → 清理 → 回到 INIT

场景 4:关闭或断开连接

[OPEN]/[INCOMING]/[OPENING] --API_CLOSE/AVDT_DISCONNECT--> [CLOSING]
[CLOSING] --STR_CLOSE--> [INIT]

流程说明

  1. 不论当前处于 OPENINCOMING 还是 OPENING,一旦收到关闭或断开事件 → 切换到 CLOSING

  2. 执行关闭操作和资源清理 → 信道关闭完成 → 回到 INIT


💡 说明

  • 每个场景只关注本流程相关状态和事件,不与其他流程混合。

  • 通过这种分场景方法,可以快速理解 A2DP Sink 在主动/被动连接、播放控制、断开等不同情况下的状态切换。

在这里插入图片描述

五、生活化类比

可以把 A2DP Sink 状态机理解为接收音频的“管道工”

  1. INIT:管道工休息中,等水(音频)来。

  2. INCOMING / OPENING:管道工开始准备管道(信道),检查接口(SDP/配置)。

  3. OPEN:管道已连通,音频流可以顺畅流动。

  4. RCFG:调整管道参数(音质/编码)。

  5. 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 查询、信道建立、配置协商、流开启和关闭。

  • 通过日志打印和事件处理函数的组合,可以高效、安全地处理音频连接。

http://www.dtcms.com/a/535989.html

相关文章:

  • Python、Java与Go:AI大模型时代的语言抉择
  • 【Go】P14 Go语言核心利器:全面解析结构体 (Struct)
  • 华为OD机试双机位A卷 - 最佳植树距离 (C++ Python JAVA JS GO)
  • Go学习资料整理
  • 旅游网站规划建设郑州网站建设网络公司
  • k8s滚动升级
  • 舆情网站入口wordpress文章添加seo标题代码
  • Android分区刷机原理深度解析:从Bootloader到Framework的完整启动流程
  • 高防 IP 如何保护企业网站?
  • 原创 网站 源码Discuz网站制作教程
  • windows 2003建设网站网站制作案例市场
  • mysql的安装和卸载过程
  • 软件设计师知识点总结:算法设计与分析
  • 互联网设计公司网站wordpress 404页面模板
  • python+ai智能根据doc教案文档生成ppt
  • PPT WPS ERROR +mn-ea
  • 技术解析 | QtScrcpy:一款基于Qt的跨平台Android投屏工具的实现原理与代码架构
  • F037 vue+neo4j 编程语言知识图谱可视化分析系统vue+flask+neo4j
  • qt设置运行框左上角图标
  • 大量PPT文件怎么快速转换成JPG格式的长图
  • 网站数据怎么做接口供小程序调用企业手机网站建设策划方案
  • LabVIEW机械零件尺寸检测
  • 网站建设公司整站源码专做网站公司
  • ProfiNet转EtherNet/IP工业智能网关实现欧姆龙PLC与倍福I/O模块通讯的实操案例
  • AR工业巡检:虚实融合的智能巡检技术详解
  • 【LUA教程】LUA脚本语言中文教程.PDF
  • 初识影刀--一款 AI 驱动的 RPA 自动化软件
  • SAP SD客户对账开票功能分享
  • 洛谷 P1177:【模板】排序 ← 基数排序实现
  • 株洲网站设计外包首选中国可信网站查询