1. 概述
- system/stack/btu/btu_task.cc
bt_main_thread
是 Android Bluetooth 协议栈中的核心线程,负责处理蓝牙协议栈中的大部分关键任务和事件。它相当于蓝牙协议栈的"大脑",协调各种蓝牙功能的运行。
2. 重要性
bt_main_thread
的重要性体现在以下几个方面:
-
中央调度中心:几乎所有蓝牙协议栈的关键操作都要经过这个线程
-
线程安全保证:通过将所有关键操作集中在一个线程处理,避免了多线程并发问题
-
事件顺序保证:确保蓝牙协议栈的事件按正确顺序处理
-
实时性要求:蓝牙协议对时间敏感,专门线程可以保证及时响应
3. 运行机制
3.1 基本架构
-
基于
MessageLoopThread
实现,这是一个封装了消息循环的线程类 -
使用
base::OnceClosure
作为任务单元 -
支持即时任务和延迟任务
3.2 启动与关闭
- 启动:通过
main_thread_start_up()
启动线程并尝试启用实时调度 - 关闭:通过
main_thread_shut_down()
关闭线程
1. 启动
// system/btif/src/stack_manager.cc
static void event_start_up_stack(UNUSED_ATTR void* context) {main_thread_start_up();}// system/stack/btu/btu_task.ccstatic MessageLoopThread main_thread("bt_main_thread", true);void main_thread_start_up() {main_thread.StartUp();if (!main_thread.IsRunning()) {LOG(FATAL) << __func__ << ": unable to start btu message loop thread.";}if (!main_thread.EnableRealTimeScheduling()) {
#if defined(OS_ANDROID)LOG(FATAL) << __func__ << ": unable to enable real time scheduling";
#elseLOG(ERROR) << __func__ << ": unable to enable real time scheduling";
#endif}
}
- 当系统调用 开启蓝牙后, 各个profile 服务启动时,就会触发,bt_stack_manager_thread 线程调用 event_start_up_stack
- 在 event_start_up_stack 中就会 触发 main_thread_start_up ,启动 bt_main_thread 线程
2. 关闭
static void event_shut_down_stack(UNUSED_ATTR void* context){main_thread_shut_down();
}void main_thread_shut_down() { main_thread.ShutDown(); }
- 同样也是 在关闭蓝牙时 bt_stack_manager_thread 线程调用 event_shut_down_stack 时触发的 关闭
3.3 任务调度
有三种主要方式将任务放入主线程执行:
-
do_in_main_thread()
- 立即执行任务 -
do_in_main_thread_delayed()
- 延迟执行任务 -
post_on_bt_main()
- 通过闭包方式提交任务
4. 主要职责和功能
4.1 HCI 消息处理 (btu_hci_msg_process
)
这是最重要的功能,处理来自蓝牙控制器的各种消息:
消息类型 (p_msg->event) | 处理方式 | 说明 |
---|---|---|
BT_EVT_TO_BTU_HCI_ACL | 转发给 ACL 模块 | 处理 ACL 数据包 (普通蓝牙数据传输) |
BT_EVT_TO_BTU_L2C_SEG_XMIT | 转发给 ACL 模块 | L2CAP 分段传输完成通知 |
BT_EVT_TO_BTU_HCI_SCO | 转发给 SCO 模块 | 处理 SCO 数据 (语音数据) |
BT_EVT_TO_BTU_HCI_EVT | 处理 HCI 事件 | 处理来自控制器的各种事件 |
BT_EVT_TO_BTU_HCI_CMD | 发送 HCI 命令 | 向控制器发送命令 |
BT_EVT_TO_BTU_HCI_ISO | 转发给 ISO 模块 | 处理 LE Audio 等 ISO 数据 |
- system/btif/src/stack_manager.cc
static void event_init_stack(void* context) {bte_main_init();}
-
当 bt_stack_manager_thread 线程调用 event_init_stack 函数时, 会触发 bte_main_init
-
system/main/bte_main.cc
static void post_to_main_message_loop(const base::Location& from_here,BT_HDR* p_msg) {if (do_in_main_thread(from_here, base::Bind(&btu_hci_msg_process, p_msg)) !=BT_STATUS_SUCCESS) {LOG(ERROR) << __func__ << ": do_in_main_thread failed from "<< from_here.ToString();}
}void bte_main_init(void) {// 获取 hci 层接口hci = bluetooth::shim::hci_layer_get_interface();if (!hci) {LOG_ERROR("%s could not get hci layer interface.", __func__);return;}// 向hci 层注册 回调函数 post_to_main_message_loophci->set_data_cb(base::Bind(&post_to_main_message_loop));
}
- 在 bte_main_init 函数中, 通过 hci->set_data_cb 向hci 层注册回调 post_to_main_message_loop
- 当 hci 收到数据后, 就会回调到 post_to_main_message_loop 函数。
- 在 post_to_main_message_loop 中通过 do_in_main_thread 将 hci 执行路径切换到 bt_main_thread 线程中, 并执行 btu_hci_msg_process 函数
此时所有 hci 层上来的数据 全部在 bt_main_thread 线程中执行, 并通过 btu_hci_msg_process 函数分发到 各个子模块中。 例如 l2cap 例如 sco 例如 ISO 等, 具体处理。
- system/stack/btu/btu_task.cc
void btu_hci_msg_process(BT_HDR* p_msg) {/* Determine the input message type. */switch (p_msg->event & BT_EVT_MASK) {case BT_EVT_TO_BTU_HCI_ACL:/* All Acl Data goes to ACL */acl_rcv_acl_data(p_msg);break;case BT_EVT_TO_BTU_L2C_SEG_XMIT:/* L2CAP segment transmit complete */acl_link_segments_xmitted(p_msg);break;case BT_EVT_TO_BTU_HCI_SCO:btm_route_sco_data(p_msg);break;case BT_EVT_TO_BTU_HCI_EVT:btu_hcif_process_event((uint8_t)(p_msg->event & BT_SUB_EVT_MASK), p_msg);osi_free(p_msg);break;case BT_EVT_TO_BTU_HCI_CMD:btu_hcif_send_cmd((uint8_t)(p_msg->event & BT_SUB_EVT_MASK), p_msg);break;case BT_EVT_TO_BTU_HCI_ISO:IsoManager::GetInstance()->HandleIsoData(p_msg);osi_free(p_msg);break;default:osi_free(p_msg);break;}
}
4.2 线程管理
-
确保任务在正确的线程执行 (
is_on_main_thread()
) -
提供线程切换机制 (
do_in_main_thread
系列函数)
4.3 模块协调
协调蓝牙协议栈各模块的工作,包括:
-
BTA (Bluetooth Application Layer)
-
BTIF (Bluetooth Interface)
-
BTM (Bluetooth Manager)
-
L2CAP
-
ACL
-
ISO (LE Audio)
5. 设计原因与解决的问题
5.1 为什么这样设计?
-
简化并发控制:蓝牙协议栈涉及多个层次和模块,单线程模型避免了复杂的锁机制
-
保证事件顺序:蓝牙协议对事件顺序敏感,单线程处理确保顺序正确
-
实时性要求:专用线程可以优先处理蓝牙任务,满足蓝牙的实时性需求
-
资源效率:避免了为每个模块创建单独线程的开销
5.2 解决了什么问题?
-
竞态条件:通过单线程模型避免了多线程并发问题
-
死锁风险:减少了模块间相互调用导致的死锁可能性
-
事件顺序混乱:确保蓝牙协议栈事件按正确顺序处理
-
响应延迟:专用线程可以及时响应蓝牙事件
6. 状态切换
system/stack/btu/btu_task.cc 没有直接的状态机实现,但可以理解其工作原理:
-
事件驱动:所有状态切换都由 HCI 消息触发
-
模块协作:主线程将消息路由到相应模块,各模块内部维护自己的状态机
-
顺序处理:由于单线程模型,状态转换是确定性的
例如:
-
当收到连接事件时,主线程将其路由到 ACL 模块
-
ACL 模块处理连接状态变化
-
可能需要通知上层 L2CAP 或应用层
-
所有状态转换都在主线程中顺序完成
7. 上下行数据处理
7.1 上行数据 (从控制器到主机)
所有上行数据都在主线程处理:
-
HCI 事件
-
ACL 数据
-
SCO 数据
-
ISO 数据
7.2 下行数据 (从主机到控制器)
大部分下行数据也通过主线程:
-
HCI 命令通过主线程发送 (
BT_EVT_TO_BTU_HCI_CMD
) -
数据传输完成通知 (
BT_EVT_TO_BTU_L2C_SEG_XMIT
)
8. 处理的具体任务
-
ACL 数据传输
-
接收来自控制器的 ACL 数据
-
处理分段传输完成通知
-
-
SCO 语音数据路由
- 将 SCO 数据路由到语音处理模块
-
HCI 事件处理
-
连接事件
-
断开事件
-
各种状态通知
-
-
HCI 命令发送
- 向蓝牙控制器发送控制命令
-
ISO 数据传输 (LE Audio)
- 处理 LE Audio 等基于 ISO 通道的数据
-
模块间协调
- 协调 BTA、BTIF、BTM 等模块的工作
-
定时任务
- 处理各种超时和延迟任务
9. 总结
bt_main_thread
是 Android Bluetooth 协议栈的核心线程,它通过单线程模型简化了蓝牙协议栈的复杂性,同时保证了事件的顺序性和实时性。它负责处理所有关键的蓝牙操作,包括数据传输、事件处理和命令发送等,是蓝牙协议栈能够正确工作的基础保障。这种设计在保证功能正确性的同时,也兼顾了性能和资源效率。