【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::FindOrCreatePeer | BtifAvSink::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_EVT
、BTA_AV_CLOSE_EVT
),完成流的实际启动或连接关闭。处理连接断开请求(
BTIF_AV_DISCONNECT_REQ_EVT
)、参数重新配置(BTA_AV_RECONFIG_EVT
)等关键操作。通过标志位(如
kFlagPendingStart
)和状态转换(TransitionTo
)管理对等端的状态机生命周期。
通过状态机的
TransitionTo
方法实现状态转换(如从 Opened→Started→Closing→Idle),确保蓝牙音频连接的生命周期(连接→流传输→断开)被正确管理。