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

【Bluedroid】btif_av_handle_event 流程源码解析

本文深入解析Android蓝牙A2DP模块中Opened状态的事件处理机制。通过分析btif_av_handle_event的事件分发流程和StateOpened::ProcessEvent的具体实现,揭示蓝牙音频连接在已建立连接但未开始传输音频时的行为逻辑,包括启动流、断开连接、重新配置等关键操作的状态转换过程。

一、概述

1.1 对等端管理

通过BtifAvSource(源)和BtifAvSink(宿)管理器实现BtifAvPeer对象的查找与创建:

  • 查找:已知地址时调用FindPeer;已知 BTA 句柄时调用FindPeerByHandle遍历peers_容器匹配。

  • 创建:遍历kPeerIdMin~kPeerIdMax分配唯一peer_id(共存模式需检查源 / 宿 ID 冲突),绑定 BTA 句柄(未知时查表),创建对象并初始化后存入peers_

1.2 状态机事件处理

对等端通过BtifAvStateMachine管理生命周期,核心逻辑为事件驱动的状态转换:

  • 框架:状态机通过ProcessEvent将事件委托给当前状态(如StateOpened)处理,不同状态重写该方法实现差异化逻辑。

  • 关键状态StateOpened:处理流启动(调用BTA_AvStart)、断开(调用BTA_AvClose)、重配等事件,通过TransitionTo驱动状态转换(如Opened→Started→Closing→Idle)。

1.3 事件路由分发

入口函数btif_av_handle_event根据设备类型(源 / 宿)、地址或 BTA 句柄定位对等端,未找到则丢弃事件;找到后将事件传递给对等端状态机处理,完成从上层到 BTA 层的事件流转。

二、源码解析

btif_av_handle_event

packages/modules/Bluetooth/system/btif/src/btif_av.cc
/*** Process BTIF or BTA AV or BTA AVRCP events. The processing is done on the* JNI thread.** @param peer_sep the corresponding peer's SEP: AVDT_TSEP_SRC if the peer* is A2DP Source, or AVDT_TSEP_SNK if the peer is A2DP Sink.* @param peer_address the peer address if known, otherwise RawAddress::kEmpty* @param bta_handle the BTA handle for the peer if known, otherwise* kBtaHandleUnknown* @param btif_av_event the corresponding event*/
static void btif_av_handle_event(uint8_t peer_sep,const RawAddress& peer_address,tBTA_AV_HNDL bta_handle,const BtifAvEvent& btif_av_event) {log::debug("Handle event peer_address={} bta_handle=0x{:x}",ADDRESS_TO_LOGGABLE_CSTR(peer_address), bta_handle);BtifAvPeer* peer = nullptr;// Find the peerif (btif_av_src_sink_coexist_enabled()) {// 处理双设备场景,直接获取对等端对象peer = btif_av_handle_both_peer(peer_sep, peer_address, bta_handle);} else {if (peer_address != RawAddress::kEmpty) {if (peer_sep == AVDT_TSEP_SNK) { // 对端是宿设备(Sink)peer = btif_av_source.FindOrCreatePeer(peer_address, bta_handle);} else if (peer_sep == AVDT_TSEP_SRC) { // 对端是源设备(Source)peer = btif_av_sink.FindOrCreatePeer(peer_address, bta_handle);}} else if (bta_handle != kBtaHandleUnknown) { // 未知设备地址,但已知 BTA 句柄if (peer_sep == AVDT_TSEP_SNK) {peer = btif_av_source.FindPeerByHandle(bta_handle);} else if (peer_sep == AVDT_TSEP_SRC) {peer = btif_av_sink.FindPeerByHandle(bta_handle);}}}if (peer == nullptr) { //  错误处理(未找到对等端)log::error("jni_thread: Cannot find or create {} peer for peer_address={}  ""bta_handle=0x{:x} : event dropped: {}",peer_stream_endpoint_text(peer_sep),ADDRESS_TO_LOGGABLE_CSTR(peer_address), bta_handle,btif_av_event.ToString());return;}// 事件传递给状态机处理peer->StateMachine().ProcessEvent(btif_av_event.Event(),btif_av_event.Data());
}

基于设备类型(源 / 宿)、地址或 BTA 句柄,定位对应的蓝牙音频对等端对象,并将事件传递给其状态机。

btif_av_source.FindOrCreatePeer

packages/modules/Bluetooth/system/btif/src/btif_av.cc
BtifAvPeer* BtifAvSource::FindOrCreatePeer(const RawAddress& peer_address,tBTA_AV_HNDL bta_handle) {std::unique_lock<std::mutex> lock1(mutex_);log::verbose("peer_address={} bta_handle=0x{:x}",ADDRESS_TO_LOGGABLE_CSTR(peer_address), bta_handle);// 查找已存在的对等端BtifAvPeer* peer = FindPeer(peer_address);if (peer != nullptr) return peer;// 分配唯一的 peer_id// Find next availabie Peer ID to useuint8_t peer_id;for (peer_id = kPeerIdMin; peer_id < kPeerIdMax; peer_id++) {/* because the peer id may be in source cb and we cannot use it */if (btif_av_src_sink_coexist_enabled() && btif_av_both_enable()) {/* 源宿共存模式下,需同时检查源和宿的peer_id是否被占用 */if (FindPeerByPeerId(peer_id) == nullptr &&btif_av_sink.FindPeerByPeerId(peer_id) == nullptr)break;} else {/* 非共存模式,仅检查当前源的peer_id是否被占用 */if (FindPeerByPeerId(peer_id) == nullptr) break;}}// peer_id 分配失败处理if (peer_id == kPeerIdMax) {log::error("Cannot create peer for peer_address={} : cannot allocate unique Peer ""ID",ADDRESS_TO_LOGGABLE_CSTR(peer_address));return nullptr;}// Get the BTA Handle (if known)if (bta_handle == kBtaHandleUnknown) {auto it = peer_id2bta_handle_.find(peer_id);if (it == peer_id2bta_handle_.end() || it->second == kBtaHandleUnknown) {log::error("Cannot create peer for peer_address={} : cannot convert Peer ID={} ""to unique BTA Handle",ADDRESS_TO_LOGGABLE_CSTR(peer_address), peer_id);return nullptr;}bta_handle = it->second;}// 创建并初始化对等端对象log::info("Create peer: peer_address={} bta_handle=0x{:x} peer_id={}",ADDRESS_TO_LOGGABLE_CSTR(peer_address), bta_handle, peer_id);peer = new BtifAvPeer(peer_address, AVDT_TSEP_SNK, bta_handle, peer_id);peers_.insert(std::make_pair(peer_address, peer));peer->Init();return peer;
}

通过地址查找、唯一 ID 分配和 BTA 句柄绑定,确保每个蓝牙设备有对应的 BtifAvPeer 对象,为后续的状态机事件处理(如 btif_av_handle_event 中传递事件)提供基础。

btif_av_sink.FindOrCreatePeer

packages/modules/Bluetooth/system/btif/src/btif_av.cc
std::map<RawAddress, BtifAvPeer*> peers_;BtifAvPeer* BtifAvSink::FindOrCreatePeer(const RawAddress& peer_address,tBTA_AV_HNDL bta_handle) {log::verbose("peer_address={} bta_handle=0x{:x}",ADDRESS_TO_LOGGABLE_CSTR(peer_address), bta_handle);BtifAvPeer* peer = FindPeer(peer_address);if (peer != nullptr) return peer;// Find next availabie Peer ID to useuint8_t peer_id;for (peer_id = kPeerIdMin; peer_id < kPeerIdMax; peer_id++) {/* because the peer id may be in source cb and we cannot use it */if (btif_av_both_enable()) {if (FindPeerByPeerId(peer_id) == nullptr &&btif_av_source.FindPeerByPeerId(peer_id) == nullptr)break;} else {if (FindPeerByPeerId(peer_id) == nullptr) break;}}if (peer_id == kPeerIdMax) {log::error("Cannot create peer for peer_address={} : cannot allocate unique Peer ""ID",ADDRESS_TO_LOGGABLE_CSTR(peer_address));return nullptr;}// Get the BTA Handle (if known)if (bta_handle == kBtaHandleUnknown) {auto it = peer_id2bta_handle_.find(peer_id);if (it == peer_id2bta_handle_.end() || it->second == kBtaHandleUnknown) {log::error("Cannot create peer for peer_address={} : cannot convert Peer ID={} ""to unique BTA Handle",ADDRESS_TO_LOGGABLE_CSTR(peer_address), peer_id);return nullptr;}bta_handle = it->second;}log::info("Create peer: peer_address={} bta_handle=0x{:x} peer_id={}",ADDRESS_TO_LOGGABLE_CSTR(peer_address), bta_handle, peer_id);peer = new BtifAvPeer(peer_address, AVDT_TSEP_SRC, bta_handle, peer_id);peers_.insert(std::make_pair(peer_address, peer));peer->Init();return peer;
}

BtifAvSource::FindOrCreatePeer 类似,通过地址查找、唯一 ID 分配和 BTA 句柄绑定,确保每个蓝牙宿设备有对应的 BtifAvPeer 对象。

BtifAvSource::FindOrCreatePeer 的核心差异

对比项BtifAvSource::FindOrCreatePeerBtifAvSink::FindOrCreatePeer
管理的设备类型处理 A2DP 源设备的对等端(AVDT_TSEP_SNK)处理 A2DP 宿设备的对等端(AVDT_TSEP_SRC)
共存模式判断条件btif_av_src_sink_coexist_enabled() && btif_av_both_enable()btif_av_both_enable()(更简化的条件)
线程安全锁使用 std::unique_lock<std::mutex> lock1(mutex_); 加锁未显式加锁(可能 BtifAvSink 的 mutex_ 管理方式不同)

btif_av_source.FindPeerByHandle

packages/modules/Bluetooth/system/btif/src/btif_av.cc
// 存储了所有已管理的源设备对等端对象(键为设备地址,值为对等端对象指针)
std::map<RawAddress, BtifAvPeer*> peers_;BtifAvPeer* BtifAvSource::FindPeerByHandle(tBTA_AV_HNDL bta_handle) {for (auto it : peers_) {BtifAvPeer* peer = it.second;if (peer->BtaHandle() == bta_handle) {return peer;}}return nullptr;
}

通过 BTA 句柄(bta_handle)查找已存在的蓝牙音频对等端对象(BtifAvPeer)。

btif_av_sink.FindPeerByHandle

packages/modules/Bluetooth/system/btif/src/btif_av.cc
BtifAvPeer* BtifAvSink::FindPeerByHandle(tBTA_AV_HNDL bta_handle) {for (auto it : peers_) {BtifAvPeer* peer = it.second;if (peer->BtaHandle() == bta_handle) {return peer;}}return nullptr;
}

通过遍历sink设备管理的对等端对象,基于 BTA 句柄快速定位目标对象。与Source设备版本的对称性设计,体现了蓝牙模块中源 / 宿角色在对等端管理上的一致性,共同支撑蓝牙音频的多设备事件分发和状态管理逻辑。

ProcessEvent

packages/modules/Bluetooth/system/common/state_machine.h
/*** Process an event.* TODO: The arguments are wrong - used for backward compatibility.* Will be replaced later.** @param event the event type* @param p_data the event data* @return true if the processing was completed, otherwise false*/
bool ProcessEvent(uint32_t event, void* p_data) {if (current_state_ == nullptr) return false;return current_state_->ProcessEvent(event, p_data);
}

将事件传递给当前状态对象的 ProcessEvent 方法处理。这是状态模式(State Pattern)的典型实现:

状态机的行为由当前状态决定,不同状态(如 “StateOpening”“StateOpened”)可重写 ProcessEvent 方法,实现差异化的事件处理逻辑。

BtifAvStateMachine::StateOpened::ProcessEvent

packages/modules/Bluetooth/system/btif/src/btif_av.cc
bool BtifAvStateMachine::StateOpened::ProcessEvent(uint32_t event,void* p_data) {tBTA_AV* p_av = (tBTA_AV*)p_data;log::verbose("Peer {} : event={} flags={} active_peer={}",ADDRESS_TO_LOGGABLE_CSTR(peer_.PeerAddress()),BtifAvEvent::EventName(event), peer_.FlagsToString(),logbool(peer_.IsActivePeer()));// 远程暂停标志的特殊处理:用于恢复音频流传输,避免因暂停标志未清除导致的流中断if ((event == BTA_AV_REMOTE_CMD_EVT) &&peer_.CheckFlags(BtifAvPeer::kFlagRemoteSuspend) &&(p_av->remote_cmd.rc_id == AVRC_ID_PLAY)) {log::verbose("Peer {} : Resetting remote suspend flag on RC PLAY",ADDRESS_TO_LOGGABLE_CSTR(peer_.PeerAddress()));peer_.ClearFlags(BtifAvPeer::kFlagRemoteSuspend);}switch (event) {// 对于停止流、暂停流、ACL 断开等事件,当前状态(Opened)不处理,直接忽略case BTIF_AV_STOP_STREAM_REQ_EVT:case BTIF_AV_SUSPEND_STREAM_REQ_EVT:case BTIF_AV_ACL_DISCONNECTED:break;  // Ignorecase BTIF_AV_START_STREAM_REQ_EVT: { // 启动流请求log::info("Peer {} : event={} flags={}",ADDRESS_TO_LOGGABLE_CSTR(peer_.PeerAddress()),BtifAvEvent::EventName(event), peer_.FlagsToString());if (p_data) {const btif_av_start_stream_req_t* p_start_steam_req =static_cast<const btif_av_start_stream_req_t*>(p_data);log::info("Stream use_latency_mode={}",p_start_steam_req->use_latency_mode ? "true" : "false");peer_.SetUseLatencyMode(p_start_steam_req->use_latency_mode);}BTA_AvStart(peer_.BtaHandle(), peer_.UseLatencyMode()); // 调用BTA接口启动流peer_.SetFlags(BtifAvPeer::kFlagPendingStart); // 标记“等待启动”状态} break;case BTA_AV_START_EVT: { // 流启动完成事件log::info("Peer {} : event={} status={} suspending={} initiator={} flags={}",ADDRESS_TO_LOGGABLE_CSTR(peer_.PeerAddress()),BtifAvEvent::EventName(event), p_av->start.status,p_av->start.suspending, p_av->start.initiator, peer_.FlagsToString());if ((p_av->start.status == BTA_SUCCESS) && p_av->start.suspending)return true;//  根据对等端类型(宿设备)决定是否暂停流// If remote tries to start A2DP when DUT is A2DP Source, then Suspend.// If A2DP is Sink and call is active, then disconnect the AVDTP// channel.bool should_suspend = false;if (peer_.IsSink()) {if (!peer_.CheckFlags(BtifAvPeer::kFlagPendingStart |BtifAvPeer::kFlagRemoteSuspend)) {log::warn("Peer {} : trigger Suspend as remote initiated",ADDRESS_TO_LOGGABLE_STR(peer_.PeerAddress()));should_suspend = true;} else if (!peer_.IsActivePeer()) {log::warn("Peer {} : trigger Suspend as non-active",ADDRESS_TO_LOGGABLE_STR(peer_.PeerAddress()));should_suspend = true;}// If peer is A2DP Source, do ACK commands to audio HAL and start// media taskif (btif_a2dp_on_started(peer_.PeerAddress(), &p_av->start)) {// Only clear pending flag after acknowledgementpeer_.ClearFlags(BtifAvPeer::kFlagPendingStart);}}// Remain in Open state if status failedif (p_av->start.status != BTA_AV_SUCCESS) return false;if (peer_.IsSource() && peer_.IsActivePeer()) {// Remove flush state, ready for streamingbtif_a2dp_sink_set_rx_flush(false);btif_a2dp_sink_on_start();}if (should_suspend) {btif_av_source_dispatch_sm_event(peer_.PeerAddress(),BTIF_AV_SUSPEND_STREAM_REQ_EVT);}// 转换到“已启动”状态peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateStarted);} break;case BTIF_AV_DISCONNECT_REQ_EVT: // 断开连接请求BTA_AvClose(peer_.BtaHandle()); // 调用BTA接口关闭连接if (peer_.IsSource()) {BTA_AvCloseRc(peer_.BtaHandle()); // 源设备额外关闭RC通道}// Inform the application that we are disconnectingbtif_report_connection_state(peer_.PeerAddress(), BTAV_CONNECTION_STATE_DISCONNECTING,bt_status_t::BT_STATUS_SUCCESS, BTA_AV_SUCCESS); // 通知应用层连接状态变为“断开中”// 转换到“关闭中”状态// Wait in closing state until fully closedpeer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateClosing);break;case BTA_AV_CLOSE_EVT: // 连接关闭事件// 通知应用层连接状态(断开中→已断开)// AVDTP link is closed// Inform the application that we are disconnectingbtif_report_connection_state(peer_.PeerAddress(), BTAV_CONNECTION_STATE_DISCONNECTING,bt_status_t::BT_STATUS_SUCCESS, BTA_AV_SUCCESS);// 处理未完成的启动请求(清除标志位或通知上层失败)// Change state to Idle, send acknowledgement if start is pendingif (peer_.CheckFlags(BtifAvPeer::kFlagPendingStart)) {log::warn("Peer {} : failed pending start request",ADDRESS_TO_LOGGABLE_CSTR(peer_.PeerAddress()));tBTA_AV_START av_start = {.chnl = p_av->close.chnl,.hndl = p_av->close.hndl,.status = BTA_AV_FAIL_STREAM,.initiator = true,.suspending = true};btif_a2dp_on_started(peer_.PeerAddress(), &av_start);  // 通知上层启动失败// Pending start flag will be cleared when exit current state} else if (peer_.IsActivePeer()) {btif_a2dp_on_stopped(nullptr);}// Inform the application that we are disconnectedbtif_report_connection_state(peer_.PeerAddress(), BTAV_CONNECTION_STATE_DISCONNECTED,bt_status_t::BT_STATUS_SUCCESS, BTA_AV_SUCCESS);peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateIdle); // 转换到“空闲”状态break;case BTA_AV_RECONFIG_EVT: // 参数重新配置事件if (p_av->reconfig.status != BTA_AV_SUCCESS) { // 配置失败log::warn("Peer {} : failed reconfiguration",ADDRESS_TO_LOGGABLE_STR(peer_.PeerAddress()));if (peer_.CheckFlags(BtifAvPeer::kFlagPendingStart)) {log::error("Peer {} : cannot proceed to do AvStart",ADDRESS_TO_LOGGABLE_STR(peer_.PeerAddress()));peer_.ClearFlags(BtifAvPeer::kFlagPendingStart);btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE); // 通知上层配置失败}// 断开连接if (peer_.IsSink()) {src_disconnect_sink(peer_.PeerAddress());} else if (peer_.IsSource()) {sink_disconnect_src(peer_.PeerAddress());}break;}if (peer_.IsActivePeer()) {log::info("Peer {} : Reconfig done - calling startSession() to audio HAL",ADDRESS_TO_LOGGABLE_STR(peer_.PeerAddress()));std::promise<void> peer_ready_promise;std::future<void> peer_ready_future = peer_ready_promise.get_future();// 通知音频HAL启动会话btif_a2dp_source_start_session(peer_.PeerAddress(),std::move(peer_ready_promise));}if (peer_.CheckFlags(BtifAvPeer::kFlagPendingStart)) {log::info("Peer {} : Reconfig done - calling BTA_AvStart({})",ADDRESS_TO_LOGGABLE_STR(peer_.PeerAddress()),loghex(peer_.BtaHandle()));BTA_AvStart(peer_.BtaHandle(), peer_.UseLatencyMode()); // 重新启动流}break;case BTIF_AV_CONNECT_REQ_EVT: {log::warn("Peer {} : Ignore {} for same device",ADDRESS_TO_LOGGABLE_CSTR(peer_.PeerAddress()),BtifAvEvent::EventName(event));btif_queue_advance();} break;case BTIF_AV_OFFLOAD_START_REQ_EVT:log::error("Peer {} : event={}: stream is not Started",ADDRESS_TO_LOGGABLE_CSTR(peer_.PeerAddress()),BtifAvEvent::EventName(event));btif_a2dp_on_offload_started(peer_.PeerAddress(), BTA_AV_FAIL);break;case BTIF_AV_AVRCP_REMOTE_PLAY_EVT:if (peer_.CheckFlags(BtifAvPeer::kFlagRemoteSuspend)) {log::verbose("Peer {} : Resetting remote suspend flag on RC PLAY",ADDRESS_TO_LOGGABLE_CSTR(peer_.PeerAddress()));peer_.ClearFlags(BtifAvPeer::kFlagRemoteSuspend);}break;CHECK_RC_EVENT(event, (tBTA_AV*)p_data);case BTIF_AV_SET_LATENCY_REQ_EVT: {const btif_av_set_latency_req_t* p_set_latency_req =static_cast<const btif_av_set_latency_req_t*>(p_data);log::info("Peer {} : event={} flags={} is_low_latency={}",ADDRESS_TO_LOGGABLE_CSTR(peer_.PeerAddress()),BtifAvEvent::EventName(event), peer_.FlagsToString(),p_set_latency_req->is_low_latency ? "true" : "false");BTA_AvSetLatency(peer_.BtaHandle(), p_set_latency_req->is_low_latency);} break;default:log::warn("Peer {} : Unhandled event={}",ADDRESS_TO_LOGGABLE_CSTR(peer_.PeerAddress()),BtifAvEvent::EventName(event));return false;}return true;
}

状态机中 “已打开” 状态(Opened)的事件处理入口,主要包括:

  • 处理蓝牙音频流的启动(BTIF_AV_START_STREAM_REQ_EVT)、暂停(BTIF_AV_SUSPEND_STREAM_REQ_EVT)等操作。

  • 响应 BTA 层的回调事件(如 BTA_AV_START_EVTBTA_AV_CLOSE_EVT),完成流的实际启动或连接关闭。

  • 处理连接断开请求(BTIF_AV_DISCONNECT_REQ_EVT)、参数重新配置(BTA_AV_RECONFIG_EVT)等关键操作。

  • 通过标志位(如 kFlagPendingStart)和状态转换(TransitionTo)管理对等端的状态机生命周期。

通过状态机的 TransitionTo 方法实现状态转换(如从 Opened→Started→Closing→Idle),确保蓝牙音频连接的生命周期(连接→流传输→断开)被正确管理。

三、事件处理时序图(以启动流请求为例)

四、对等端查找与创建流程图


http://www.lryc.cn/news/608776.html

相关文章:

  • 面向智能体的上下文工程:策略、实现与 LangGraph 实践
  • LangChain4J入门:接入大模型
  • 系统学习算法:专题十六 字符串
  • 第三章-提示词-高级:开启智能交互新境界(13/36)
  • 日常--详细介绍qt Designer常用快捷键(详细图文)
  • 【QT】概述
  • 高质量数据集|建设三大难点
  • 01.MySQL 安装
  • 服务器中切换盘的操作指南
  • Android 之 MVVM架构
  • 使用 Docker 部署 Golang 程序
  • 第四章:OSPF 协议
  • Dify中自定义工具类的类型
  • WebMvc自动配置流程讲解
  • MySQL 索引失效的场景与原因
  • 嵌入式开发学习———Linux环境下IO进程线程学习(二)
  • 04.Redis 的多实例
  • 笔试——Day27
  • 前端面试手撕题目全解析
  • 【数据迁移】Windows11 下将 Ubuntu 从 C 盘迁移到 D 盘
  • Redis——常用指令汇总指南(三)(哈希类型)
  • Odoo OWL前端框架全面学习指南 (后端开发者视角)
  • 三角洲行动ACE反作弊VT-d报错?CPU虚拟化如何开启!
  • GitOps:云原生时代的革命性基础设施管理范式
  • Ubuntu20.04 Carla安装与和Ros联合仿真
  • Ubuntu22.4部署大模型前置安装
  • AI + 云原生:正在引爆下一代应用的技术革命
  • LabVIEW小波变换检测信号断点
  • HCIP笔记(第四章)
  • 悬挂的绳子,它的函数方程是什么样子的?