【android bluetooth 框架分析 03】【Bta 层详解 1】【Bluetooth Application Laye 介绍】
蓝牙协议栈中 Bluetooth Application Layer(蓝牙应用层)是协议栈核心组成部分,它位于协议栈中间偏上的位置,主要负责将底层 Bluetooth Stack(如 L2CAP、AVDTP、RFCOMM、SDP 等)与上层 Profile 和 Android Framework(如 Bluetooth HAL 和系统服务)连接起来。
1. bta
模块的层次定位与作用
1. 所在层次:
-
属于 Bluetooth Protocol Stack 的中间层,介于:
-
底层协议栈(BTU、L2CAP、AVDTP 等)
-
与
-
上层 Profiles(如 A2DP、HFP、HID、PAN)及 Android Bluetooth Framework(如 BluetoothService.java) 之间。
-
2. 核心作用:
-
Profile 实现:提供 A2DP、HFP、HID 等标准蓝牙协议的实现(行为逻辑),供上层调用。
-
事件派发机制:
bta_sys_sendmsg
与bta_sys_event
组成的事件机制,将事件从上层发送到对应模块(例如 A2DP、HFP 等)中。 -
定时器调度机制:
bta_sys_start_timer
提供模块级定时器支持,常用于状态机中等待某些异步事件。 -
模块注册和生命周期管理:通过
bta_sys_register
注册模块(如 A2DP、HFP),包括其事件回调处理函数。
2. 关键函数分析
1. bta_sys_init
event_start_up_stack 调用时机在 bt_stack_manager_thread 线程中有介绍过。
// system/btif/src/stack_manager.cc
static void event_start_up_stack(UNUSED_ATTR void* context) {bta_sys_init(); // 初始化 bta 层
}
// system/bta/sys/bta_sys_main.cctBTA_SYS_CB bta_sys_cb;void bta_sys_init(void) {memset(&bta_sys_cb, 0, sizeof(tBTA_SYS_CB)); // 这里将 全局的 系统管理控制块清零
}
1. tBTA_SYS_CB
(系统管理控制块)
// system/bta/sys/bta_sys_int.h
/* system manager control block */
typedef struct {tBTA_SYS_REG* reg[BTA_ID_MAX]; /* registration structures */bool is_reg[BTA_ID_MAX]; /* registration structures */bool forward_hw_failures;uint16_t sys_features; /* Bitmask of sys features */tBTA_SYS_CONN_CBACK* prm_cb; /* role management callback registered by DM */tBTA_SYS_CONN_CBACK*ppm_cb; /* low power management callback registered by DM */tBTA_SYS_CONN_CBACK*p_sco_cb; /* SCO connection change callback registered by AV */tBTA_SYS_CONN_CBACK* p_role_cb; /* role change callback registered by AV */tBTA_SYS_COLLISION colli_reg; /* collision handling module */
#if (BTA_EIR_CANNED_UUID_LIST != TRUE)tBTA_SYS_EIR_CBACK* eir_cb; /* add/remove UUID into EIR */tBTA_SYS_CUST_EIR_CBACK* cust_eir_cb; /* add/remove customer UUID into EIR */
#endiftBTA_SYS_SSR_CFG_CBACK* p_ssr_cb;/* VS event handler */tBTA_SYS_VS_EVT_HDLR* p_vs_evt_hdlr;} tBTA_SYS_CB;
成员名 | 类型 | 作用说明 | 应用场景 |
---|---|---|---|
reg[BTA_ID_MAX] | tBTA_SYS_REG* 数组 | 用于存储每个模块(如 A2DP、HFP)的注册信息,包括其事件处理函数等 | 在 bta_sys_register() 中注册模块,供 bta_sys_event() 分发事件时使用 |
is_reg[BTA_ID_MAX] | bool 数组 | 记录每个模块是否已经注册,防止重复注册或未注册模块被调用 | 初始化过程中用于检测模块是否已注册 |
forward_hw_failures | bool | 是否转发硬件故障信息给上层 | 某些硬件异常时通知 DM 层或 Profile 层作出响应 |
sys_features | uint16_t | 系统支持的功能特性标志位(如支持哪些 Profile) | 模块间可以查询系统功能支持情况 |
prm_cb | tBTA_SYS_CONN_CBACK* | 电源角色管理(PRM)回调函数,由 Device Manager 注册 | DM 层响应主从角色变化、链接断开等事件 |
ppm_cb | tBTA_SYS_CONN_CBACK* | 电源低功耗管理(PPM)回调函数,由 Device Manager 注册 | 控制蓝牙模块进入低功耗模式 |
p_sco_cb | tBTA_SYS_CONN_CBACK* | SCO 音频链接变化回调函数,通常由 A2DP 或 HFP 注册 | 语音通话过程中,当 SCO 音频连接状态发生变化时触发 |
p_role_cb | tBTA_SYS_CONN_CBACK* | 主从角色切换回调函数,通常由 AV 注册 | 例如 A2DP Sink 在连接多个 Source 时主从角色切换通知 |
colli_reg | tBTA_SYS_COLLISION | 冲突处理模块,例如连接请求冲突时的处理策略 | 两个设备同时发起连接请求时,进行冲突仲裁 |
eir_cb | tBTA_SYS_EIR_CBACK* | EIR(Extended Inquiry Response)UUID 添加/删除回调 | 在设备可发现状态下动态调整支持的服务 UUID |
cust_eir_cb | tBTA_SYS_CUST_EIR_CBACK* | 客户自定义 UUID 添加/删除回调 | 自定义设备特性时添加私有 UUID 到广播中 |
p_ssr_cb | tBTA_SYS_SSR_CFG_CBACK* | SSR(Sniff Subrating)配置回调 | 用于调整低功耗时的通信间隔,常用于 BLE 设备 |
p_vs_evt_hdlr | tBTA_SYS_VS_EVT_HDLR* | 处理厂商自定义 VS(Vendor Specific)事件的回调 | 厂商定制命令、蓝牙芯片事件处理,如 CSR、Broadcom 扩展 |
- 可以参照 system/bta/sys/bta_sys_conn.cc 中定义的接口,来参照如何使用。 由于篇幅原因, 这里暂时不介绍。后面单独抽一个篇幅来介绍。
2. bta_sys_register
// system/bta/sys/bta_sys_main.cc
void bta_sys_register(uint8_t id, const tBTA_SYS_REG* p_reg) {bta_sys_cb.reg[id] = (tBTA_SYS_REG*)p_reg;bta_sys_cb.is_reg[id] = true;
}
如下模块都在使用
功能:
- 注册某个模块(Profile)到 BTA 系统,使其能接收事件并被调度。
参数解释:
id
:模块 ID,如BTA_ID_AV
、BTA_ID_HF
等。p_reg
:包含事件处理函数指针
/* SW sub-systems */
#define BTA_ID_SYS 0 /* system manager */
/* BLUETOOTH PART - from 0 to BTA_ID_BLUETOOTH_MAX */
#define BTA_ID_DM_SEARCH 2 /* device manager search */
#define BTA_ID_DM_SEC 3 /* device manager security */
#define BTA_ID_DG 4 /* data gateway */
#define BTA_ID_AG 5 /* audio gateway */
#define BTA_ID_OPC 6 /* object push client */
#define BTA_ID_OPS 7 /* object push server */
#define BTA_ID_FTS 8 /* file transfer server */
#define BTA_ID_CT 9 /* cordless telephony terminal */
#define BTA_ID_FTC 10 /* file transfer client */
#define BTA_ID_SS 11 /* synchronization server */
#define BTA_ID_PR 12 /* Printer client */
#define BTA_ID_BIC 13 /* Basic Imaging Client */
#define BTA_ID_PAN 14 /* Personal Area Networking */
#define BTA_ID_BIS 15 /* Basic Imaging Server */
#define BTA_ID_ACC 16 /* Advanced Camera Client */
#define BTA_ID_SC 17 /* SIM Card Access server */
#define BTA_ID_AV 18 /* Advanced audio/video */
#define BTA_ID_HD 20 /* HID Device */
#define BTA_ID_CG 21 /* Cordless Gateway */
#define BTA_ID_BP 22 /* Basic Printing Client */
#define BTA_ID_HH 23 /* Human Interface Device Host */
#define BTA_ID_PBS 24 /* Phone Book Access Server */
#define BTA_ID_PBC 25 /* Phone Book Access Client */
#define BTA_ID_JV 26 /* Java */
#define BTA_ID_HS 27 /* Headset */
#define BTA_ID_MSE 28 /* Message Server Equipment */
#define BTA_ID_MCE 29 /* Message Client Equipment */
#define BTA_ID_HL 30 /* Health Device Profile*/
#define BTA_ID_GATTC 31 /* GATT Client */
#define BTA_ID_GATTS 32 /* GATT Client */
#define BTA_ID_SDP 33 /* SDP Client */
#define BTA_ID_BLUETOOTH_MAX 34 /* last BT profile */#define BTA_ID_MAX (44 + BTA_DM_NUM_JV_ID)
内部机制:
- 把
p_reg
保存在bta_sys_cb.reg[id]
中,供bta_sys_event()
调用。
应用场景:
- A2DP 模块初始化时调用:
bta_sys_register(BTA_ID_AV, &bta_av_reg);
- 这样之后所有
BTA_ID_AV
的事件都会由bta_av_hdl_event()
处理。
1. tBTA_SYS_REG
typedef struct {tBTA_SYS_EVT_HDLR* evt_hdlr;tBTA_SYS_DISABLE* disable;
} tBTA_SYS_REG;
成员名 | 类型 | 作用 | 使用场景 | 注册方式 | 调用时机 |
---|---|---|---|---|---|
evt_hdlr | tBTA_SYS_EVT_HDLR* (函数指针) 定义: bool (*tBTA_SYS_EVT_HDLR)(BT_HDR* p_msg) | 事件处理函数,系统通过它将消息分发给对应模块处理 | 模块处理通过 bta_sys_sendmsg 投递的事件,如 A2DP 状态机事件等 | 通过 bta_sys_register(BTA_ID_AV, &bta_av_reg) 注册到 bta_sys_cb.reg[BTA_ID_AV].evt_hdlr | 被 bta_sys_event() 调用,用于处理模块收到的 BT_HDR 消息 |
disable | tBTA_SYS_DISABLE* (函数指针) 定义: void (*tBTA_SYS_DISABLE)(void) | 模块禁用函数,当 BTA 模块整体被禁用时调用,用于释放资源、关闭状态机等 | 关闭蓝牙或卸载模块时,做清理工作,如断开连接、释放内存、复位状态等 | 同样在 bta_sys_register() 时注册 | 被 bta_sys_disable() 调用,用于逐个模块执行注销/清理操作 |
A2DP 模块注册过程(参考 bta_av_api.cc
)
static const tBTA_SYS_REG bta_av_reg = {bta_av_hdl_event, BTA_AvDisable};void BTA_AvEnable(tBTA_AV_FEAT features, tBTA_AV_CBACK* p_cback) {bta_sys_register(BTA_ID_AV, &bta_av_reg);}
- 当
bta_sys_event()
接收到BT_HDR
类型消息,并判断event >> 8 == BTA_ID_AV
时:- 会调用:
bta_sys_cb.reg[BTA_ID_AV].evt_hdlr(p_msg)
→ 即bta_av_hdl_event(p_msg)
- 会调用:
- 当关闭蓝牙模块时:
- 会调用:
bta_sys_cb.reg[BTA_ID_AV].disable()
→ 即bta_av_disable()
- 会调用:
3. bta_sys_sendmsg/bta_sys_sendmsg_delayed
// 向 BTA 系统消息队列(BTU 线程中运行的)发送一条消息事件。
// 本质上是将 p_msg 指向的事件结构体投递到 BTU 线程的任务消息队列。
// 最终由 btu_task 中循环读取并调用对应的事件处理器。
void bta_sys_sendmsg(void* p_msg) {if (do_in_main_thread(FROM_HERE,base::Bind(&bta_sys_event, static_cast<BT_HDR_RIGID*>(p_msg))) !=BT_STATUS_SUCCESS) {LOG(ERROR) << __func__ << ": do_in_main_thread failed";}
}// 延时发送到 BTU 线程中处理
void bta_sys_sendmsg_delayed(void* p_msg, const base::TimeDelta& delay) {if (do_in_main_thread_delayed(FROM_HERE,base::Bind(&bta_sys_event, static_cast<BT_HDR_RIGID*>(p_msg)),delay) != BT_STATUS_SUCCESS) {LOG(ERROR) << __func__ << ": do_in_main_thread_delayed failed";}
}
举例:
- 当 A2DP 解码器准备好音频数据时,通过
bta_sys_sendmsg
发送一个事件(例如BTA_AV_START_EVT
),这个事件最终在bta_av_hdl_event()
中被处理。
4. bta_sys_event
static void bta_sys_event(BT_HDR_RIGID* p_msg) {uint8_t id;bool freebuf = true;APPL_TRACE_EVENT("%s: Event 0x%x", __func__, p_msg->event);/* get subsystem id from event */id = (uint8_t)(p_msg->event >> 8);/* verify id and call subsystem event handler */if ((id < BTA_ID_MAX) && (bta_sys_cb.reg[id] != NULL)) {freebuf = (*bta_sys_cb.reg[id]->evt_hdlr)(p_msg);} else {LOG_INFO("Ignoring receipt of unregistered event id:%s",BtaIdSysText(id).c_str());}if (freebuf) {osi_free(p_msg);}
}
功能:
- BTA 系统的“中央调度函数”,用于分发消息给注册的模块(如 A2DP、HFP)。
核心流程:
- 读取
p_msg->event
中的模块 ID(例如BTA_ID_AV
)。 - 在全局数组
bta_sys_cb.reg
中查找对应模块的回调函数。 - 调用对应模块注册的事件处理器(例如
bta_av_hdl_event()
)。
场景举例:
- 当有
BT_HDR
类型消息抵达(可能通过bta_sys_sendmsg
发来),bta_sys_event()
被调用并分发事件。
5. bta_sys_start_timer
参数名 | 类型 | 含义 |
---|---|---|
alarm | alarm_t* | 由上层分配的定时器对象指针 |
interval_ms | uint64_t | 定时器延时毫秒数 |
event | uint16_t | 延时后要发送的事件代码 |
layer_specific | uint16_t | 附加信息字段(例如状态机实例 ID) |
void bta_sys_start_timer(alarm_t* alarm, uint64_t interval_ms, uint16_t event,uint16_t layer_specific) {// BT_HDR_RIGID 是一种标准事件数据结构(也是 BT_HDR 的变种),用于传递事件。// 动态分配内存,用来保存事件数据。BT_HDR_RIGID* p_buf = (BT_HDR_RIGID*)osi_malloc(sizeof(BT_HDR_RIGID));p_buf->event = event;// event 字段用来指定事件类型(如 `BTA_AV_START_EVT` 等)。p_buf->layer_specific = layer_specific; // layer_specific 字段用于传递额外上下文信息,通常是状态机 ID、连接 handle 等。/* 使用 Android 蓝牙的定时器框架 alarm_set_on_mloop,表示: 在主循环线程(mainloop)中,延迟 interval_ms 毫秒后调用 bta_sys_sendmsg(p_buf)。bta_sys_sendmsg 会把这个事件投递给 BTU 线程的消息队列,最终通过 bta_sys_event()派发到对应模块的事件处理函数*/alarm_set_on_mloop(alarm, interval_ms, bta_sys_sendmsg, p_buf);
}
3. 整体运行流程图(简化)
4.实际场景分析:A2DP 连接过程中的调度
- 用户点击播放音乐 → Android Framework 发出 A2DP 连接请求。
- JNI → btif层 → 调用 A2DP 初始化函数。
- A2DP 调用
bta_sys_register(BTA_ID_AV, &bta_av_reg)
注册自身。 - A2DP 通过
bta_sys_sendmsg
发起连接请求事件。 - 事件进入
btu_task
循环 → 被bta_sys_event
分发到 A2DP。 - A2DP 状态机进入连接中状态,并设置超时定时器
bta_sys_start_timer
。 - 若超时无响应,则定时器触发事件,再由
bta_sys_event
调度超时逻辑。