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

【Bluedroid】btif_av_sink_execute_service之服务器禁用源码流程解析

本文围绕 Bluedroid 蓝牙协议栈中音频接收端(Sink)服务的禁用流程展开,系统解析从 BTIF 层触发注销到 BTA 层状态机驱动、底层协议栈(AVDT/AVCT)解注册的完整链路。重点分析DeregisterAllBtaHandles触发 BTA 层消息分发、bta_av_api_deregister启动流会话注销、bta_av_do_close关闭音频流、bta_av_dereg_comp清理资源及底层协议栈解注册等核心步骤,揭示蓝牙服务禁用过程中 “分层协作、状态机驱动、资源安全释放” 的设计逻辑。

一、概述

蓝牙音频接收端的服务禁用是资源管理的关键环节,涉及多模块协作:从 BTIF 层感知禁用事件并触发 BTA 层注销,到 BTA 层通过状态机驱动流会话关闭、清理 SDP 记录及连接,最终到底层协议栈(AVDT/AVCT)解注册,确保所有资源(如连接、定时器、缓冲区)彻底释放。流程核心目标是:避免资源泄漏、保持状态一致、保障协议交互可靠性。

1.1 触发阶段:BTIF 层发起注销

BTIF 层通过DeregisterAllBtaHandles遍历维护的设备 ID 与 BTA 句柄映射表(peer_id2bta_handle_),调用BTA_AvDeregister触发 BTA 层注销流程,并清空映射表避免资源残留。

1.2 消息分发:BTA 层异步处理

BTA_AvDeregister将注销请求封装为BTA_AV_API_DEREGISTER_EVT消息,通过bta_sys_sendmsg提交至 BTA 主线程消息队列。主线程事件循环分发事件至bta_av_hdl_event,最终调用bta_av_api_deregister启动流会话(SCB)注销。

1.3 流会话注销:状态机驱动关闭

bta_av_api_deregister通过句柄定位流会话控制块(SCB),标记deregistering状态后,调用bta_av_ssm_execute触发状态机的BTA_AV_API_CLOSE_EVT事件,驱动bta_av_do_close执行流关闭:

  • 停止运行中的流(bta_av_str_stopped);

  • 取消信令定时器、清理流状态;

  • 刷新 L2CAP 通道、发送 AVDT 关闭请求;

  • 设置超时定时器处理关闭失败。

1.4 资源清理:SDP 记录与 SCB 释放

流关闭完成后,bta_av_dereg_comp执行最终清理:

  • 释放 SCB 关联的音频缓冲区队列;

  • 删除无活跃流时的 A2DP/AVRCP SDP 记录;

  • 释放 SCB 内存并更新全局状态(bta_av_cb);

  • 从 AVDT/AVCT 底层协议栈解注册(AVDT_Deregister/AVCT_Deregister),释放 L2CAP 资源。

1.5 全局状态重置:服务禁用完成

最终通过bta_av_disable关闭所有 AVRC 控制连接、释放设备发现数据库,并标记禁用状态为完成,确保系统回到初始一致状态。

二、源码解析

btif_av_sink_execute_service 禁用服务

【Bluedroid】btif_av_sink_execute_service之服务器启用源码流程解析-CSDN博客主要分析了btif_av_sink_execute_service的启用服务部分的流程,本篇主要分析btif_av_sink_execute_service禁用服务的流程。

btif_av_sink.DeregisterAllBtaHandles

packages/modules/Bluetooth/system/btif/src/btif_av.cc
std::map<uint8_t, tBTA_AV_HNDL> peer_id2bta_handle_;void BtifAvSink::DeregisterAllBtaHandles() {// 1. 遍历映射表,注销所有 BTA 句柄for (auto it : peer_id2bta_handle_) {tBTA_AV_HNDL bta_handle = it.second;BTA_AvDeregister(bta_handle);}// 2. 清空映射表peer_id2bta_handle_.clear();
}

当蓝牙音频接收端需要清理资源(如设备断开连接、模块卸载或系统关闭)时,遍历全局维护的对等设备 ID 与 BTA 音频 / 视频句柄的映射表(peer_id2bta_handle_),调用 BTA 层的注销接口(BTA_AvDeregister)注销所有已注册的音频 / 视频服务,并清空映射表,避免资源泄漏。

BTA_AvDeregister
packages/modules/Bluetooth/system/bta/av/bta_av_api.cc
/********************************************************************************* Function         BTA_AvDeregister** Description      Deregister the audio or video service** Returns          void*******************************************************************************/
void BTA_AvDeregister(tBTA_AV_HNDL hndl) {BT_HDR_RIGID* p_buf = (BT_HDR_RIGID*)osi_malloc(sizeof(BT_HDR_RIGID));p_buf->layer_specific = hndl;p_buf->event = BTA_AV_API_DEREGISTER_EVT;bta_sys_sendmsg(p_buf);
}

蓝牙 AV 子系统的 “注销入口函数”,其核心作用是:

  • 接口抽象:向上层应用提供简单的注销接口,隐藏底层复杂逻辑。

  • 消息封装:将注销请求参数封装为 BTA 层可识别的消息,确保跨线程传递的可靠性。

  • 流程触发:触发 BTA 层的注销流程(bta_av_api_deregister),最终实现服务的资源释放、SDP 记录删除及连接关闭。

体现了蓝牙协议栈 “接口简洁性” 和 “底层复杂性封装” 的设计思想,是音频 / 视频服务生命周期管理的关键纽带。

bta_sys_sendmsg(BTA_AV_API_DEREGISTER_EVT)

BTA 系统的消息发送函数(【Bluedroid】btif_av_sink_execute_service之服务器启用源码流程解析-CSDN博客分析过),将消息提交到 BTA 主线程的消息队列。BTA 主线程通过事件循环(bta_sys_event)分发事件到 AV 子系统的事件处理函数(bta_av_hdl_event),最终调用 bta_av_api_deregister 执行具体的注销逻辑。

bta_av_api_deregister
packages/modules/Bluetooth/system/bta/av/bta_av_main.cc
/********************************************************************************* Function         bta_av_api_deregister** Description      de-register a channel*** Returns          void*******************************************************************************/
void bta_av_api_deregister(tBTA_AV_DATA* p_data) {tBTA_AV_SCB* p_scb = bta_av_hndl_to_scb(p_data->hdr.layer_specific);if (p_scb) {p_scb->deregistering = true; // 标记SCB正在注销bta_av_ssm_execute(p_scb, BTA_AV_API_CLOSE_EVT, p_data); // 执行状态机的关闭事件} else {bta_av_dereg_comp(p_data); // SCB不存在时,直接完成注销}
}// 句柄掩码(二进制低6位)
#define BTA_AV_HNDL_MSK 0x3F/* maximum number of streams created */
#ifndef BTA_AV_NUM_STRS
#define BTA_AV_NUM_STRS 6
#endif// 服务句柄(tBTA_AV_HNDL)转换为对应的 SCB 指针,实现 “句柄→SCB” 的快速映射
/********************************************************************************* Function         bta_av_hndl_to_scb** Description      find the stream control block by the handle** Returns          void*******************************************************************************/
tBTA_AV_SCB* bta_av_hndl_to_scb(uint16_t handle) {tBTA_AV_HNDL hndl = (tBTA_AV_HNDL)handle;tBTA_AV_SCB* p_scb = NULL;uint8_t idx = (hndl & BTA_AV_HNDL_MSK); // 提取句柄的低6位作为索引if (idx && (idx <= BTA_AV_NUM_STRS)) {p_scb = bta_av_cb.p_scb[idx - 1];}return p_scb;
}

通过服务句柄(tBTA_AV_HNDL)定位对应的流控制块(SCB,tBTA_AV_SCB,并触发 SCB 的注销流程(如断开连接、释放资源),确保音频 / 视频服务的完整退出。

bta_av_do_close
packages/modules/Bluetooth/system/bta/av/bta_av_aact.cc
/* the timer in milliseconds to guard against link busy and AVDT_CloseReq failed* to be sent */
#ifndef BTA_AV_CLOSE_REQ_TIME_VAL
#define BTA_AV_CLOSE_REQ_TIME_VAL 4000
#endif/********************************************************************************* Function         bta_av_do_close** Description      Close stream.** Returns          void*******************************************************************************/
void bta_av_do_close(tBTA_AV_SCB* p_scb, UNUSED_ATTR tBTA_AV_DATA* p_data) {log::verbose("p_scb->co_started={}", p_scb->co_started);// 1. 停止运行中的流(若已启动)/* stop stream if started */if (p_scb->co_started) {bta_av_str_stopped(p_scb, NULL);}// 2. 取消信令定时器alarm_cancel(p_scb->link_signalling_timer);// 3. 清理流状态/* close stream */p_scb->started = false;p_scb->use_rtp_header_marker_bit = false;// 4. 刷新 L2CAP 通道,丢弃队列数据/* drop the buffers queued in L2CAP */L2CA_FlushChannel(p_scb->l2c_cid, L2CAP_FLUSH_CHANS_ALL);// 5. 发送 AVDT 关闭请求AVDT_CloseReq(p_scb->avdt_handle);// 6. 设置超时定时器,处理关闭请求失败/* just in case that the link is congested, link is flow controled by peer or* for whatever reason the the close request can not be sent in time.* when this timer expires, AVDT_DisconnectReq will be called to disconnect* the link*/bta_sys_start_timer(p_scb->avrc_ct_timer, BTA_AV_CLOSE_REQ_TIME_VAL,BTA_AV_API_CLOSE_EVT, p_scb->hndl);
}

当需要关闭音频流(如设备断开连接、用户主动停止播放)时,通过一系列操作(停止流、清理状态、刷新通道、发送关闭请求)确保音频流的彻底终止,并通过定时器机制处理可能的延迟或失败,避免连接残留或资源泄漏。它是音频流生命周期管理(启动→运行→关闭)的 “终止环节”。

其核心作用是:

  • 流停止:终止音频数据传输,释放运行时资源(如编解码器、定时器)。

  • 通道清理:刷新 L2CAP 通道,丢弃残留数据,保障数据完整性。

  • 连接关闭:通过 AVDT 层通知对端关闭流,并通过定时器处理可能的失败,确保连接可靠释放。

体现了蓝牙协议栈 “优雅关闭”“可靠性保障” 和 “状态严谨性” 的设计原则,是音频流稳定运行的关键保障。

bta_av_dereg_comp
packages/modules/Bluetooth/system/bta/av/bta_av_act.cc
/********************************************************************************* Function         bta_av_dereg_comp** Description      deregister complete. free the stream control block.** Returns          void*******************************************************************************/
void bta_av_dereg_comp(tBTA_AV_DATA* p_data) {tBTA_AV_CB* p_cb = &bta_av_cb;tBTA_AV_SCB* p_scb;tBTA_UTL_COD cod = {.minor = BTM_COD_MINOR_UNCLASSIFIED,.major = BTM_COD_MAJOR_UNCLASSIFIED,.service = 0,};uint8_t mask;BT_HDR* p_buf;// 1. 查找流控制块(SCB)/* find the stream control block */p_scb = bta_av_hndl_to_scb(p_data->hdr.layer_specific);if (p_scb) {log::verbose("deregistered {}(h{})", p_scb->chnl, p_scb->hndl);// 2. 清理音频流注册 / 连接状态mask = BTA_AV_HNDL_TO_MSK(p_scb->hdi);p_cb->reg_audio &= ~mask;if ((p_cb->conn_audio & mask) && p_cb->audio_open_cnt) {/* this channel is still marked as open. decrease the count */p_cb->audio_open_cnt--;}p_cb->conn_audio &= ~mask;// 3. 释放音频缓冲区队列if (p_scb->q_tag == BTA_AV_Q_TAG_STREAM && p_scb->a2dp_list) {/* make sure no buffers are in a2dp_list */while (!list_is_empty(p_scb->a2dp_list)) {p_buf = (BT_HDR*)list_front(p_scb->a2dp_list);list_remove(p_scb->a2dp_list, p_buf);osi_free(p_buf);}}// 4. 删除 A2DP/SDP 记录(无活跃流时)/* remove the A2DP SDP record, if no more audio stream is left */if (!p_cb->reg_audio) {  // 无注册的音频流时// 若未启用新AVRCP,删除AVRC SDP记录/* Only remove the SDP record if we're the ones that created it */if (is_new_avrcp_enabled()) {log::verbose("newavrcp is the owner of the AVRCP Target SDP record. Don't dereg ""the SDP record");} else {log::verbose("newavrcp is not enabled. Remove SDP record");bta_ar_dereg_avrc(UUID_SERVCLASS_AV_REMOTE_CONTROL);}// 删除A2DP源的SDP记录(若存在)if (p_cb->sdp_a2dp_handle) {bta_av_del_sdp_rec(&p_cb->sdp_a2dp_handle);p_cb->sdp_a2dp_handle = 0;bta_sys_remove_uuid(UUID_SERVCLASS_AUDIO_SOURCE); // 从系统中移除源UUID}// 删除A2DP接收端的SDP记录(若存在)if (p_cb->sdp_a2dp_snk_handle) {bta_av_del_sdp_rec(&p_cb->sdp_a2dp_snk_handle);p_cb->sdp_a2dp_snk_handle = 0;bta_sys_remove_uuid(UUID_SERVCLASS_AUDIO_SINK);}}// 5. 释放流控制块(SCB)bta_av_free_scb(p_scb);}log::verbose("audio 0x{:x}, disable:{}", p_cb->reg_audio, p_cb->disabling);// 6. 从底层协议栈解注册(无活跃流时)/* if no stream control block is active */if (p_cb->reg_audio == 0) {/* deregister from AVDT */bta_ar_dereg_avdt();/* deregister from AVCT */bta_ar_dereg_avrc(UUID_SERVCLASS_AV_REM_CTRL_TARGET);bta_ar_dereg_avct();// 7. 重置系统状态(禁用时)if (p_cb->disabling) {p_cb->disabling = false;// reset enabling parametersp_cb->features = 0;p_cb->sec_mask = 0;bta_av_cb.sink_features = 0;bta_av_cb.reg_role = 0;}// 8. 更新设备服务类信息/* Clear the Capturing service class bit */cod.service = BTM_COD_SERVICE_CAPTURING;utl_set_device_class(&cod, BTA_UTL_CLR_COD_SERVICE_CLASS);}
}

在服务注销流程的最后阶段,清理与音频流相关的所有资源(如缓冲区、SDP 记录、流控制块),并更新全局状态,确保系统回到一致的初始状态。其核心职责是:

  1. 资源清理:释放流控制块(SCB)关联的缓冲区、SDP 记录等资源。

  2. 状态重置:更新全局控制块(bta_av_cb)中的注册 / 连接状态,确保系统状态一致性。

  3. 模块解注册:从 AVDT(音频 / 视频分发传输协议)、AVCT(音频 / 视频控制传输协议)等底层模块注销,释放协议栈资源。

bta_ar_dereg_avrc

packages/modules/Bluetooth/system/bta/ar/bta_ar.cc
/******************************************************************************** Function         bta_ar_dereg_avrc** Description      This function is called to de-register/delete an SDP record*                  for AVRCP.** Returns          void******************************************************************************/
void bta_ar_dereg_avrc(uint16_t service_uuid) {uint8_t mask = BTA_AR_AV_MASK;uint16_t categories = 0;uint8_t temp[8], *p;// 场景 1:注销 AVRCP 目标设备(Target)的 SDP 记录if (service_uuid == UUID_SERVCLASS_AV_REM_CTRL_TARGET) {if (bta_ar_cb.sdp_tg_handle && mask == bta_ar_cb.tg_registered) {bta_ar_cb.tg_registered = 0;get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(bta_ar_cb.sdp_tg_handle); // 删除目标设备的 SDP 记录bta_ar_cb.sdp_tg_handle = 0; // 清除目标设备的注册状态bta_sys_remove_uuid(service_uuid); // 从系统中移除该服务 UUID}} // 场景 2:注销 AVRCP 控制器(Controller)的 SDP 记录else if (service_uuid == UUID_SERVCLASS_AV_REMOTE_CONTROL) {if (bta_ar_cb.sdp_ct_handle) {bta_ar_cb.ct_categories[mask - 1] = 0;categories = bta_ar_cb.ct_categories[0] | bta_ar_cb.ct_categories[1];if (!categories) {// 彻底删除控制器的 SDP 记录,清空句柄并移除 UUID/* no CT is still registered - cleaup */get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(bta_ar_cb.sdp_ct_handle);bta_ar_cb.sdp_ct_handle = 0;bta_sys_remove_uuid(service_uuid);} else { // 仍有其他类别注册/* change supported categories to the remaning one */p = temp;UINT16_TO_BE_STREAM(p, categories);// 将剩余类别写入get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(bta_ar_cb.sdp_ct_handle, ATTR_ID_SUPPORTED_FEATURES, UINT_DESC_TYPE,(uint32_t)2, (uint8_t*)temp);}}}
}

根据服务类型(目标 / 控制器)和当前注册状态,决定是彻底删除 SDP 记录还是仅更新属性,确保资源高效利用和状态同步。

bta_sys_remove_uuid

packages/modules/Bluetooth/system/bta/sys/bta_sys_conn.cc
/********************************************************************************* Function         bta_sys_remove_uuid** Description      Called by BTA subsystems to indicate to DM that the service*                  class UUID is removed.** Returns          void*******************************************************************************/
void bta_sys_remove_uuid(uint16_t uuid16) {if (bta_sys_cb.eir_cb) {bta_sys_cb.eir_cb(uuid16, false);}
}

当 AVRCP 的 SDP 记录被删除后(如目标设备或控制器的服务不再可用),必须同步通知系统移除该服务的 UUID:

  • 避免其他设备通过蓝牙查询(如 Inquiry 过程)发现已失效的服务,导致错误的连接尝试。

  • 确保设备广播的 EIR 数据(包含支持的服务 UUID 列表)与实际运行的服务状态一致,提升互操作性。

bta_av_free_scb

packages/modules/Bluetooth/system/bta/av/bta_av_main.cc
void bta_av_free_scb(tBTA_AV_SCB* p_scb) {if (p_scb == nullptr) return;uint8_t scb_index = p_scb->hdi;CHECK(scb_index < BTA_AV_NUM_STRS);CHECK(p_scb == bta_av_cb.p_scb[scb_index]);bta_av_cb.p_scb[scb_index] = nullptr;alarm_free(p_scb->avrc_ct_timer);list_free(p_scb->a2dp_list);p_scb->a2dp_list = NULL;// TODO: After tBTA_AV_SCB is changed to a proper class, the entry// here should be de-allocated by C++ 'delete' statement.osi_free(p_scb);
}

通过严格的状态校验、资源分级释放、全局状态同步,确保了 AV 会话销毁时的资源完整性:

  • 防御性检查(空指针、索引越界、状态一致性)避免了运行时崩溃;

  • 资源分层释放(定时器→列表→SCB 本体)确保所有关联资源被回收,防止内存泄漏;

  • 全局状态清理(置空全局数组指针)保证了模块上下文的准确性,为后续会话分配提供可靠的状态基础。

bta_ar_dereg_avdt

packages/modules/Bluetooth/system/bta/ar/bta_ar.cc
/********************************************************************************* Function         bta_ar_dereg_avdt** Description      This function is called to de-register from AVDTP.** Returns          void*******************************************************************************/
void bta_ar_dereg_avdt() {// 1. 清理回调指针bta_ar_cb.p_av_conn_cback = NULL;// 2. 更新 AVDTP 注册状态bta_ar_cb.avdt_registered &= ~BTA_AR_AV_MASK;// 3. 触发底层注销(仅当无剩余服务时)if (bta_ar_cb.avdt_registered == 0) AVDT_Deregister();
}

通过清理回调、更新状态、条件触发底层注销三步操作,实现了 AVDTP 服务的高效注销管理,确保资源释放的准确性和协议栈交互的可靠性。

AVDT_Deregister

packages/modules/Bluetooth/system/stack/avdt/avdt_api.cc
/* PSM for AVDT */
#define AVDT_PSM 0x0019/********************************************************************************* Function         AVDT_Deregister** Description      This function is called to deregister use AVDTP protocol.*                  It is called when AVDTP is no longer being used by any*                  application in the system.  Before this function can be*                  called, all streams must be removed with*                  AVDT_RemoveStream().*** Returns          void*******************************************************************************/
void AVDT_Deregister(void) {/* deregister PSM with L2CAP */L2CA_Deregister(AVDT_PSM);
}

当系统中所有使用 AVDTP 的应用(如 AR 模块、A2DP 音频流)均已停止,且所有 AVDTP 流(Stream)已通过 AVDT_RemoveStream() 移除后调用。从 L2CAP 层注销 AVDTP 的协议标识(PSM),释放底层传输资源(如通道、端口),确保协议栈资源的彻底回收。

bta_ar_dereg_avct

packages/modules/Bluetooth/system/bta/ar/bta_ar.cc
/********************************************************************************* Function         bta_ar_dereg_avct** Description      This function is called to deregister from AVCTP.** Returns          void*******************************************************************************/
void bta_ar_dereg_avct() {// 清除 AV 类型服务的注册标志bta_ar_cb.avct_registered &= ~BTA_AR_AV_MASK;// 触发底层注销(仅当无剩余服务时)if (bta_ar_cb.avct_registered == 0) AVCT_Deregister();
}

通过位掩码状态管理和条件触发底层注销,实现了 AVCTP 服务的高效注销逻辑。其核心是通过精细化的状态标记,避免冗余操作,确保协议栈资源释放的准确性和高效性,是蓝牙协议栈中 “多服务类型动态管理” 的典型实现。

AVCT_Deregister

packages/modules/Bluetooth/system/stack/avct/avct_api.c
/* PSM for AVCT. */
#define AVCT_PSM 0x0017/********************************************************************************* Function         AVCT_Deregister** Description      This function is called to deregister use AVCTP protocol.*                  It is called when AVCTP is no longer being used by any*                  application in the system.  Before this function can be*                  called, all connections must be removed with*                  AVCT_RemoveConn().*** Returns          void*******************************************************************************/
void AVCT_Deregister(void) {log::verbose("AVCT_Deregister");/* deregister PSM with L2CAP */L2CA_Deregister(AVCT_PSM);
}

当系统中所有使用 AVCTP 的应用(如 AR 模块、AVRCP 控制器)均停止使用该协议,且所有 AVCTP 连接已通过 AVCT_RemoveConn() 移除后调用。从 L2CAP 层注销 AVCTP 的协议标识(PSM),释放底层控制传输资源(如控制通道、端口),确保协议栈资源的彻底回收。

utl_set_device_class(BTA_UTL_CLR_COD_SERVICE_CLASS)

packages/modules/Bluetooth/system/bta/sys/utl.cc
/********************************************************************************* Function         utl_set_device_class** Description      This function updates the local Device Class.** Parameters:*                  p_cod   - Pointer to the device class to set to**                  cmd     - the fields of the device class to update.*                            BTA_UTL_SET_COD_MAJOR_MINOR, - overwrite major,*                                                           minor class*                            BTA_UTL_SET_COD_SERVICE_CLASS - set the bits in*                                                            the input*                            BTA_UTL_CLR_COD_SERVICE_CLASS - clear the bits in*                                                            the input*                            BTA_UTL_SET_COD_ALL - overwrite major, minor, set*                                                  the bits in service class*                            BTA_UTL_INIT_COD - overwrite major, minor, and*                                               service class** Returns          true if successful, Otherwise false*******************************************************************************/
bool utl_set_device_class(tBTA_UTL_COD* p_cod, uint8_t cmd) {uint16_t service;uint8_t minor, major;DEV_CLASS old_class;old_class = BTM_ReadDeviceClass(); // 读取当前设备类BTM_COD_SERVICE_CLASS(service, old_class); // 提取当前服务类位(service)BTM_COD_MINOR_CLASS(minor, old_class);BTM_COD_MAJOR_CLASS(major, old_class);switch (cmd) {case BTA_UTL_SET_COD_MAJOR_MINOR:minor = p_cod->minor & BTM_COD_MINOR_CLASS_MASK;major = p_cod->major & BTM_COD_MAJOR_CLASS_MASK;break;case BTA_UTL_SET_COD_SERVICE_CLASS:/* clear out the bits that is not SERVICE_CLASS bits */p_cod->service &= BTM_COD_SERVICE_CLASS_MASK;service = service | p_cod->service;break;case BTA_UTL_CLR_COD_SERVICE_CLASS:// 输入服务类位的有效性过滤p_cod->service &= BTM_COD_SERVICE_CLASS_MASK;//  清除当前服务类中的指定位// 当前服务类位与取反后的输入位按位与,结果是将当前服务类中与输入位对应的位置 0,其他位保持不变service = service & (~p_cod->service);break;case BTA_UTL_SET_COD_ALL:minor = p_cod->minor & BTM_COD_MINOR_CLASS_MASK;major = p_cod->major & BTM_COD_MAJOR_CLASS_MASK;p_cod->service &= BTM_COD_SERVICE_CLASS_MASK;service = service | p_cod->service;break;case BTA_UTL_INIT_COD:minor = p_cod->minor & BTM_COD_MINOR_CLASS_MASK;major = p_cod->major & BTM_COD_MAJOR_CLASS_MASK;service = p_cod->service & BTM_COD_SERVICE_CLASS_MASK;break;default:return false;}/* convert the fields into the device class type */DEV_CLASS dev_class;FIELDS_TO_COD(dev_class, minor, major, service); // 组合为设备类格式if (BTM_SetDeviceClass(dev_class) == BTM_SUCCESS) return true; // 写入蓝牙底层模块return false;
}

BTA_UTL_CLR_COD_SERVICE_CLASS 是蓝牙协议栈中精确清除设备服务类能力的核心命令,通过位运算和有效性校验,确保设备类的服务信息与实际功能一致,是蓝牙设备对外能力宣称的关键管理接口。

应用场景示例:

假设设备当前通过服务类位宣称支持 “音频(0x0020)” 和 “信息(0x0010)” 服务(service = 0x0030):

  • 当设备停止提供音频服务时,上层模块调用 utl_set_device_class,传入 p_cod->service = 0x0020(要清除的音频服务位),命令为 BTA_UTL_CLR_COD_SERVICE_CLASS

  • 函数执行后,服务类位变为 0x0010(仅保留信息服务),设备广播 / 查询响应中的服务类将更新,其他设备发现该设备时,将不再感知到音频服务能力。

BTA_AvDisable

packages/modules/Bluetooth/system/bta/av/bta_av_api.cc
/********************************************************************************* Function         BTA_AvDisable** Description      Disable the advanced audio/video service.** Returns          void*******************************************************************************/
void BTA_AvDisable(void) {BT_HDR_RIGID* p_buf = (BT_HDR_RIGID*)osi_malloc(sizeof(BT_HDR_RIGID));// 注销系统服务注册bta_sys_deregister(BTA_ID_AV);p_buf->event = BTA_AV_API_DISABLE_EVT;//  发送异步消息bta_sys_sendmsg(p_buf);
}

禁用高级音频 / 视频(A2DP/AVRCP 等)服务,主要通过系统级注销和消息机制触发服务的异步清理流程。

bta_sys_deregister
packages/modules/Bluetooth/system/bta/sys/bta_sys_main.cc
/********************************************************************************* Function         bta_sys_deregister** Description      Called by other BTA subsystems to de-register*                  handler.*** Returns          void*******************************************************************************/
void bta_sys_deregister(uint8_t id) { bta_sys_cb.is_reg[id] = false; }

维护全局的子系统注册状态表,确保系统模块(如消息分发、服务发现)能正确识别活跃子系统,避免处理已注销子系统的请求。

bta_sys_sendmsg(BTA_AV_API_DISABLE_EVT)

BTA 系统的消息发送函数(【Bluedroid】btif_av_sink_execute_service之服务器启用源码流程解析-CSDN博客分析过),将消息提交到 BTA 主线程的消息队列。BTA 主线程通过事件循环(bta_sys_event)分发事件到 AV 子系统的事件处理函数(bta_av_hdl_event),最终调用 bta_av_disable 执行具体的注销逻辑。

bta_av_disable
packages/modules/Bluetooth/system/bta/av/bta_av_act.cc
/********************************************************************************* Function         bta_av_disable** Description      disable AV.** Returns          void*******************************************************************************/
void bta_av_disable(tBTA_AV_CB* p_cb, UNUSED_ATTR tBTA_AV_DATA* p_data) {BT_HDR_RIGID hdr;bool disabling_in_progress = false;uint16_t xx;// 1. 标记禁用状态p_cb->disabling = true;// 2. 关闭所有远程控制连接bta_av_close_all_rc(p_cb);// 3. 释放设备发现数据库osi_free_and_reset((void**)&p_cb->p_disc_db);// 4. 遍历并注销所有流通道/* disable audio/video - de-register all channels,* expect BTA_AV_DEREG_COMP_EVT when deregister is complete */for (xx = 0; xx < BTA_AV_NUM_STRS; xx++) {if (p_cb->p_scb[xx] != NULL) { // 存在活跃的流会话控制块(SCB)// Free signalling timersalarm_free(p_cb->p_scb[xx]->link_signalling_timer);p_cb->p_scb[xx]->link_signalling_timer = NULL;alarm_free(p_cb->p_scb[xx]->accept_signalling_timer);p_cb->p_scb[xx]->accept_signalling_timer = NULL;// 构造消息并触发底层注销hdr.layer_specific = xx + 1;bta_av_api_deregister((tBTA_AV_DATA*)&hdr);disabling_in_progress = true;}}// Since All channels are deregistering by API_DEREGISTER, the DEREG_COMP_EVT// would come first before API_DISABLE if there is no connections, and it is// no needed to setup this disabling flag.// 5. 更新禁用状态标志p_cb->disabling = disabling_in_progress;}

关闭所有活跃的 AV 连接(如 AVRCP 控制、A2DP 流),释放关联资源,并通知底层协议栈注销通道。

分阶段清理 AV 服务的核心资源(控制连接→发现数据→传输流),通过标记状态、释放定时器、触发底层注销,确保服务禁用的可靠性和资源释放的彻底性。

bta_av_close_all_rc

packages/modules/Bluetooth/system/bta/av/bta_av_act.cc
/* maximum number of streams created */
#ifndef BTA_AV_NUM_STRS
#define BTA_AV_NUM_STRS 6
#endif#define BTA_AV_NUM_RCB (BTA_AV_NUM_STRS + 2)/********************************************************************************* Function         bta_av_close_all_rc** Description      close the all AVRC handle.** Returns          void*******************************************************************************/
static void bta_av_close_all_rc(tBTA_AV_CB* p_cb) {int i;// 遍历所有 AVRC 控制块for (i = 0; i < BTA_AV_NUM_RCB; i++) {// 检查是否需要关闭当前控制块if ((p_cb->disabling) || (bta_av_cb.rcb[i].shdl != 0))bta_av_del_rc(&bta_av_cb.rcb[i]);  // 关闭具体连接}
}

在 AV 服务禁用或清理时,遍历并断开所有活跃的 AVRC 控制连接。

bta_av_del_rc

packages/modules/Bluetooth/system/bta/av/bta_av_act.cc
/********************************************************************************* Function         bta_av_del_rc** Description      delete the given AVRC handle.** Returns          void*******************************************************************************/
void bta_av_del_rc(tBTA_AV_RCB* p_rcb) {tBTA_AV_SCB* p_scb;uint8_t rc_handle; /* connected AVRCP handle */// 1. 校验 AVRC 句柄有效性p_scb = NULL;if (p_rcb->handle != BTA_AV_RC_HANDLE_NONE) {// 2. 清理关联的流会话控制块(SCB)if (p_rcb->shdl) {/* Validate array index*/if ((p_rcb->shdl - 1) < BTA_AV_NUM_STRS) {p_scb = bta_av_cb.p_scb[p_rcb->shdl - 1];}if (p_scb) {log::verbose("shdl:{}, srch:{} rc_handle:{}", p_rcb->shdl,p_scb->rc_handle, p_rcb->handle);// 清除SCB中对当前AVRC句柄的引用if (p_scb->rc_handle == p_rcb->handle)p_scb->rc_handle = BTA_AV_RC_HANDLE_NONE;/* just in case the RC timer is activeif (bta_av_cb.features & BTA_AV_FEAT_RCCT && p_scb->chnl ==BTA_AV_CHNL_AUDIO) */alarm_cancel(p_scb->avrc_ct_timer);  // 取消AVRC控制定时器(避免后续触发)}}log::verbose("handle: {} status=0x{:x}, rc_acp_handle:{}, idx:{}",p_rcb->handle, p_rcb->status, bta_av_cb.rc_acp_handle,bta_av_cb.rc_acp_idx);// 3. 根据状态清理 RCBrc_handle = p_rcb->handle;if (!(p_rcb->status & BTA_AV_RC_CONN_MASK) || // 未连接状态((p_rcb->status & BTA_AV_RC_ROLE_MASK) == BTA_AV_RC_ROLE_INT)) { // 内部角色p_rcb->status = 0;p_rcb->handle = BTA_AV_RC_HANDLE_NONE;p_rcb->shdl = 0;p_rcb->lidx = 0;}// 4. 调用底层协议栈关闭 AVRC 连接/* else ACP && connected. do not clear the handle yet */AVRC_Close(rc_handle);// 5. 清理 ACPH 句柄引用if (rc_handle == bta_av_cb.rc_acp_handle)bta_av_cb.rc_acp_handle = BTA_AV_RC_HANDLE_NONE;log::verbose("end del_rc handle: {} status=0x{:x}, rc_acp_handle:{}, lidx:{}",p_rcb->handle, p_rcb->status, bta_av_cb.rc_acp_handle, p_rcb->lidx);}
}

清理 AVRC 控制块(RCB)关联的资源(如会话引用、定时器),并调用底层协议栈关闭连接。

AVRC_Close

packages/modules/Bluetooth/system/stack/avrc/avrc_api.cc
/******************************************************************************** Function         AVRC_Close** Description      Close a connection opened with AVRC_Open().*                  This function is called when the*                  application is no longer using a connection.**                  Input Parameters:*                      handle: Handle of this connection.**                  Output Parameters:*                      None.** Returns          AVRC_SUCCESS if successful.*                  AVRC_BAD_HANDLE if handle is invalid.******************************************************************************/
uint16_t AVRC_Close(uint8_t handle) {log::verbose("handle:{}", handle);avrc_flush_cmd_q(handle);return AVCT_RemoveConn(handle);
}

理本层未完成的命令队列,并通过底层 AVCTP 协议栈移除控制连接。

avrc_flush_cmd_q

packages/modules/Bluetooth/system/stack/avrc/avrc_api.cc
/* Flags for avrc_cb.ccb_int[].flags */
#define AVRC_CB_FLAGS_RSP_PENDING 0x01 /* Waiting for AVRC response *//******************************************************************************** Function         avrc_flush_cmd_q** Description      Flush command queue for the specified avrc handle** Returns          Nothing.******************************************************************************/
void avrc_flush_cmd_q(uint8_t handle) {log::verbose("AVRC: Flushing command queue for handle=0x{:02x}", handle);avrc_cb.ccb_int[handle].flags &= ~AVRC_CB_FLAGS_RSP_PENDING;alarm_cancel(avrc_cb.ccb_int[handle].tle);// 彻底清理该连接的未处理命令(如 “暂停”“下一曲” 等未发送或未确认的命令),避免内存泄漏fixed_queue_free(avrc_cb.ccb_int[handle].cmd_q, osi_free);avrc_cb.ccb_int[handle].cmd_q = NULL;
}

通过清理标志→取消定时器→释放队列的流程,实现 AVRC 连接命令队列的安全清空。在连接关闭前清理未处理的命令,避免资源泄漏或状态混乱。

AVCT_RemoveConn

根据连接句柄定位控制块,触发逻辑链路解绑定或直接释放资源,确保连接的安全移除。

bta_av_api_deregister
packages/modules/Bluetooth/system/bta/av/bta_av_main.cc
/********************************************************************************* Function         bta_av_api_deregister** Description      de-register a channel*** Returns          void*******************************************************************************/
void bta_av_api_deregister(tBTA_AV_DATA* p_data) {// 1. 定位目标流会话(SCB)tBTA_AV_SCB* p_scb = bta_av_hndl_to_scb(p_data->hdr.layer_specific);// 2. 标记流会话为 “注销中”if (p_scb) {p_scb->deregistering = true;// 3. 触发状态机执行关闭事件bta_av_ssm_execute(p_scb, BTA_AV_API_CLOSE_EVT, p_data);} // 4. 处理 SCB 不存在的情况else {bta_av_dereg_comp(p_data);}
}

AV 服务注销流程的 “启动器”,通过定位流会话→标记状态→状态机驱动关闭→异常处理的流程,确保音频 / 视频流通道的安全注销。

三、总结

禁用服务本质是逆向的生命周期管理:

1. 分层解耦设计

  • BTIF提供简洁接口 → BTA封装复杂状态机 → 底层协议栈执行资源释放

  • 通过bta_sys_sendmsg实现跨线程异步通信

2. 防御性资源管理

  • 句柄有效性校验(bta_av_hndl_to_scb

  • 定时器守护关闭流程(BTA_AV_CLOSE_REQ_TIME_VAL

  • 位掩码跟踪状态(reg_audio标记活跃流)

3. 关键优化点

  • 条件解注册:仅当无活跃流时删除SDP记录(避免冗余操作)

  • 资源分级释放:先停流→清缓冲区→删SDP→最后解注册协议

  • COD动态更新:按需清除服务类位,确保设备能力实时同步

架构启示:协议栈通过SCB状态机驱动注销流程,以peer_id2bta_handle_全局映射表为核心枢纽,结合bta_av_cb统一管理跨层状态,实现高可靠的服务生命周期管理。

四、蓝牙音频接收端服务禁用流程

五、模块间协作时序


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

相关文章:

  • 【架构师从入门到进阶】第五章:DNSCDN网关优化思路——第十节:网关安全-单向加密
  • Item11:在operator=中处理自我赋值
  • Go-Elasticsearch v9 安装与版本兼容性
  • 全文检索官网示例
  • “给予” 超越 “莲花”,支持图片在线编辑
  • [论文阅读] 人工智能 + 软件工程 | NoCode-bench:评估LLM无代码功能添加能力的新基准
  • SSRF_XXE_RCE_反序列化学习
  • 面试实战,问题十三,Redis在Java项目中的作用及使用场景详解,怎么回答
  • 大语言模型 LLM 通过 Excel 知识库 增强日志分析,根因分析能力的技术方案(3):使用云平台最小外部依赖方案
  • GMP模型
  • 深入解析Java内存模型:原理与并发优化实践
  • Oracle 误删数据恢复
  • ClickHouse高性能实时分析数据库-高性能的模式设计
  • 学习随想录-- web3学习入门计划
  • 50道JavaScript基础面试题:从基础到进阶
  • haproxy原理及实战部署
  • 根本是什么
  • 统计学07:概率论基础
  • Chukonu 阅读笔记
  • 分类预测 | MATLAB实现DBO-SVM蜣螂算法优化支持向量机分类预测
  • 深入解析YARN中的FairScheduler与CapacityScheduler:资源分配策略的核心区别
  • 检索召回率优化探究一:基于 LangChain 0.3集成 Milvus 2.5向量数据库构建的智能问答系统
  • 微信小程序 自定义带图片弹窗
  • 数据存储:OLAP vs OLTP
  • Flutter实现Retrofit风格的网络请求封装
  • Apache Doris Data Agent 解决方案:开启智能运维与数据治理新纪元
  • RS485转Profinet网关配置指南:高效启动JRT激光测距传感器测量模式
  • React入门学习——指北指南(第四节)
  • SQL Developer Data Modeler:一款免费跨平台的数据库建模工具
  • Flutter 提取图像主色调 ColorScheme.fromImageProvider