【android bluetooth 协议分析 11】【AVDTP详解 4】【A2dp Sink 状态机通俗讲解】

Source

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 config
          break;

        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 关闭或本地 cleanup
          event_handler2 = &bta_av_disconnect_req; // 请求断开 L2CAP/ACL
          break;

        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 + cleanup
          p_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; // 处理本地 close
          event_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 -> 打开失败 -> 进入 CLOSING
          p_scb->state = BTA_AV_CLOSING_SST;
          event_handler1 = &bta_av_open_failed;
          break;

        case BTA_AV_STR_GETCAP_OK_EVT:
          // GetCapabilities 成功 -> 处理 capability 结果, 可能继续 setconfig
          event_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 完成 -> 继续做 discover
          event_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:
          // 上层要求停止/挂起 -> 处理 stop
          event_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,再打开 rc
          event_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 完成后释放 buffer
          event_handler1 = &bta_av_free_sdb;
          break;

        case BTA_AV_STR_GETCAP_OK_EVT:
          // GetCapabilities 返回 -> 保存 capability
          event_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_failed
          event_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 到,尝试打开 RC
          event_handler1 = &bta_av_open_rc;
          break;

        case BTA_AV_AVDT_DISCONNECT_EVT:
          // AVDTP 层断开 -> 直接回到 INIT 并通知上层 stream closed
          p_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 请求 -> 处理 reconfig
          event_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 closed
          p_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 打开成功 -> 返回 OPEN
          p_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; // 重新尝试 connect
          break;

        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 cfm
          event_handler1 = &bta_av_rcfg_cfm;
          break;

        case BTA_AV_AVDT_CONNECT_EVT:
          // AVDT connect -> 调用 rcfg_open 继续 open
          event_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 就直接发起 disconnect
          event_handler1 = &bta_av_disconnect_req;
          break;

        case BTA_AV_SDP_DISC_OK_EVT:
        case BTA_AV_SDP_DISC_FAIL_EVT:
          // sdp 在关闭期完成 -> 直接回到 INIT 并报 sdp_failed
          p_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 查询、信道建立、配置协商、流开启和关闭。

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