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

【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. 核心作用:

  1. Profile 实现:提供 A2DP、HFP、HID 等标准蓝牙协议的实现(行为逻辑),供上层调用。

  2. 事件派发机制bta_sys_sendmsgbta_sys_event 组成的事件机制,将事件从上层发送到对应模块(例如 A2DP、HFP 等)中。

  3. 定时器调度机制bta_sys_start_timer 提供模块级定时器支持,常用于状态机中等待某些异步事件。

  4. 模块注册和生命周期管理:通过 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_failuresbool是否转发硬件故障信息给上层某些硬件异常时通知 DM 层或 Profile 层作出响应
sys_featuresuint16_t系统支持的功能特性标志位(如支持哪些 Profile)模块间可以查询系统功能支持情况
prm_cbtBTA_SYS_CONN_CBACK*电源角色管理(PRM)回调函数,由 Device Manager 注册DM 层响应主从角色变化、链接断开等事件
ppm_cbtBTA_SYS_CONN_CBACK*电源低功耗管理(PPM)回调函数,由 Device Manager 注册控制蓝牙模块进入低功耗模式
p_sco_cbtBTA_SYS_CONN_CBACK*SCO 音频链接变化回调函数,通常由 A2DP 或 HFP 注册语音通话过程中,当 SCO 音频连接状态发生变化时触发
p_role_cbtBTA_SYS_CONN_CBACK*主从角色切换回调函数,通常由 AV 注册例如 A2DP Sink 在连接多个 Source 时主从角色切换通知
colli_regtBTA_SYS_COLLISION冲突处理模块,例如连接请求冲突时的处理策略两个设备同时发起连接请求时,进行冲突仲裁
eir_cbtBTA_SYS_EIR_CBACK*EIR(Extended Inquiry Response)UUID 添加/删除回调在设备可发现状态下动态调整支持的服务 UUID
cust_eir_cbtBTA_SYS_CUST_EIR_CBACK*客户自定义 UUID 添加/删除回调自定义设备特性时添加私有 UUID 到广播中
p_ssr_cbtBTA_SYS_SSR_CFG_CBACK*SSR(Sniff Subrating)配置回调用于调整低功耗时的通信间隔,常用于 BLE 设备
p_vs_evt_hdlrtBTA_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_AVBTA_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_hdlrtBTA_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_hdlrbta_sys_event() 调用,用于处理模块收到的 BT_HDR 消息
disabletBTA_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)。

核心流程:

  1. 读取 p_msg->event 中的模块 ID(例如 BTA_ID_AV)。
  2. 在全局数组 bta_sys_cb.reg 中查找对应模块的回调函数。
  3. 调用对应模块注册的事件处理器(例如 bta_av_hdl_event())。

场景举例:

  • 当有 BT_HDR 类型消息抵达(可能通过 bta_sys_sendmsg 发来),bta_sys_event() 被调用并分发事件。

5. bta_sys_start_timer

参数名类型含义
alarmalarm_t*由上层分配的定时器对象指针
interval_msuint64_t定时器延时毫秒数
eventuint16_t延时后要发送的事件代码
layer_specificuint16_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 连接过程中的调度

  1. 用户点击播放音乐 → Android Framework 发出 A2DP 连接请求。
  2. JNI → btif层 → 调用 A2DP 初始化函数。
  3. A2DP 调用 bta_sys_register(BTA_ID_AV, &bta_av_reg) 注册自身。
  4. A2DP 通过 bta_sys_sendmsg 发起连接请求事件。
  5. 事件进入 btu_task 循环 → 被 bta_sys_event 分发到 A2DP。
  6. A2DP 状态机进入连接中状态,并设置超时定时器 bta_sys_start_timer
  7. 若超时无响应,则定时器触发事件,再由 bta_sys_event 调度超时逻辑。

相关文章:

  • 深入学习Axios:现代前端HTTP请求利器
  • 打造产教融合高质量范本!麒麟信安入选2024年电子信息产教融合典型案例
  • c++中iota容器和fill的区别
  • 爬虫学习——获取动态网页信息
  • 智能滚动抽奖--测试报告
  • PH传感器详解(STM32)
  • 3DMAX零售商店生成插件RetailStore自定义贴图库方法详解
  • 深度学习优化器和调度器的选择和推荐
  • 【Java面试笔记:基础】13.谈谈接口和抽象类有什么区别?
  • Spring Boot 的配置加载顺序
  • socket编程基础
  • node.js 实战——(fs模块 知识点学习)
  • gem5教程第三章 向配置脚本添加缓存
  • 智启未来|艾博连科技加入奇瑞雄狮科技LION AI联合实验室
  • 机器视觉的智能手机屏贴合应用
  • leetcode-枚举
  • RabbitMQ 详解(核心概念)
  • 蓝桥杯 15.小数第n位
  • 【OSCP-vulnhub】Raven-2
  • 基于nodeJS代码的通过爬虫方式实现tiktok发布视频(2025年4月)
  • 梁启超“失肾记”的余波:中西医论战与最后的真相
  • 与包乐史驾帆航行|航海、钓鱼和写书:一个记者的再就业之路
  • 海南:谈话提醒9名缺点明显或有苗头性、倾向性问题的省管干部
  • 金湘军辞去山西省省长职务
  • 巴基斯坦航天员选拔工作正在进行,1人将以载荷专家身份参加联合飞行
  • 深一度|王励勤二次创业从未停步,带领中国乒乓直面挑战