【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 调度超时逻辑。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/77949.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

单片机获取真实时间的实现方法

单片机获取真实时间&#xff08;即当前的年月日、时分秒等&#xff09;通常需要依赖外部时间源或模块&#xff0c;因为单片机本身没有内置的实时时钟&#xff08;RTC&#xff09;功能。 在 C 语言环境下&#xff0c;单片机获取真实时间通常需要依赖 外部硬件模块&#xff08;如…

Linux——进程优先级/切换/调度

1.进程优先级 1.进程优先级是什么&#xff1a;进程获取CPU资源的先后顺序 2.为什么要有进程优先级&#xff1a;因为一般CPU只有一块&#xff0c;资源短缺&#xff0c;所以就需要优先级来确定谁先谁后的问题 3.值越低 进程的优先级越高 ps -l进行查看 UID&#xff1a;user id …

铸铁划线平板:多行业的精密测量工具(北重十字滑台加工厂家)

铸铁划线平板是一种用于精密测量和校准的工具&#xff0c;广泛应用于各个行业。它通常由铸铁制成&#xff0c;表面经过精密加工&#xff0c;能够保证较高的平整度和准确度。铸铁划线平板的主要作用是用来检验工件的平整度和垂直度&#xff0c;也常用于划线、校准和测量工件的平…

Excel/WPS表格中图片链接转换成对应的实际图片

Excel 超链图变助手&#xff08;点击下载可免费试用&#xff09; 是一款将链接转换成实际图片&#xff0c;批量下载表格中所有图片的转换工具&#xff0c;无需安装&#xff0c;双击打开即可使用。 表格中链接如下图所示&#xff1a; 操作方法&#xff1a; 1、双击以下图标&a…

STM32---串口通信USART

目录 一、串口通信协议 二、USART模块介绍 &#xff08;1&#xff09;移位寄存器 &#xff08;2&#xff09;控制电路 &#xff08;3&#xff09;波特率 &#xff08;4&#xff09;C语言接口 三、串口的引脚初始化 &#xff08;1&#xff09;引脚分布表 &…

流程架构是什么?为什么要构建流程架构,以及如何构建流程结构?

本文从&#xff1a;流程架构是什么&#xff1f;为什么要构建流程架构&#xff1f;如何构建流程结构三个方面来介绍。 一、首先&#xff0c;我们来了解流程架构是什么&#xff1f; 流程架构是人体的骨架&#xff0c;是大楼的砌筑&#xff0c;是课本的目录&#xff0c;是流程管理…

网络结构及安全科普

文章目录 终端联网网络硬件基础网络协议示例&#xff1a;用户访问网页 OSI七层模型网络攻击&#xff08;Hack&#xff09;网络攻击的主要类别&#xff08;一&#xff09;按攻击目标分类&#xff08;二&#xff09;按攻击技术分类 网络安全防御 典型攻击案例相关名词介绍网络连接…

同z科技面经

同z科技-2025-4-23 1.自我介绍 个人信息 校园经历 实习经历 项目经历 个人技能掌握 目前学习技术 2.封装缓存工具类怎么封装的 先介绍使用缓存的问题 解决的逻辑 封装的逻辑 应用 缓存穿透&#xff1a; 缓存雪崩&#xff1a; 缓存击穿&#xff1a; https://www…

基于LoRA的Llama 2二次预训练实践:高效低成本的大模型领域适配

引言 近年来&#xff0c;大语言模型&#xff08;LLM&#xff09;如Meta的Llama 2系列凭借其强大的生成和理解能力成为NLP领域的核心工具。然而&#xff0c;直接将通用预训练模型应用于垂直领域&#xff08;如医疗、法律、金融&#xff09;时&#xff0c;常面临领域知识不足的问…

Python爬虫(2)Python爬虫入门:从HTTP协议解析到豆瓣电影数据抓取实战

目录 一、背景与需求‌二、 Web基础与HTTP协议核心解析‌2.1 HTTP协议&#xff1a;数据交互的基石‌2.2 为何爬虫需理解HTTP协议&#xff1f;‌ 三、 Python爬虫实战&#xff1a;Requests库核心用法‌3.1 安装与环境配置‌3.2 案例1&#xff1a;GET请求抓取豆瓣电影Top250‌3.3…

深度学习--ResNet残差神经网络解析

文章目录 前言一、什么是ResNet网络二、传统卷积神经网络存在的问题1、梯度消失和梯度爆炸2、退化问题 三、如何解决问题四、残差结构五、18层残差网络1、解释2、隔层相加优点3、隔层相加数值增大问题 六、18层残差网络以外的表格示例七、BN层&#xff08;Batch Normalization&…

【go】go run-gcflags常用参数归纳,go逃逸分析执行语句,go返回局部变量指针是安全的

go官方参考文档&#xff1a; https://pkg.go.dev/cmd/compile 基本语法 go run 命令用来编译并运行Go程序&#xff0c;-gcflags 后面可以跟一系列的编译选项&#xff0c;多个选项之间用空格分隔。基本语法如下&#xff1a; go run -gcflags "<flags>" main.…

K8S探针的应用

目录&#xff1a; 1、探针的简介2、启用探针2.1、启用就绪探针2.2、启用存活探针2.3、启用启动探针&#xff08;可选&#xff09; 1、探针的简介 在Kubernetes中&#xff0c;探针&#xff08;Probes&#xff09;是用来检查容器健康状况的工具&#xff0c;它们帮助Kubernetes了…

体积小巧的 Word 转 PDF 批量工具

软件介绍 今天给大家介绍一款能批量把 Word 文档转换成 PDF 的实用小工具。 软件特点 这款 Word 批量转 PDF 软件&#xff0c;身材小巧&#xff0c;体积不到 1M&#xff0c;还没界面呢&#xff01;使用时&#xff0c;只要把软件和要转换的 Word 文档放在一个文件夹&#xff…

JMeter介绍

文章目录 1. JMeter简介2. JMeter 下载3. JMeter修改编码集4. 启动并运行JMeter 1. JMeter简介 JMeter 是 Apache 组织使用 Java 开发的一款测试工具&#xff1a; 1、可以用于对服务器、网络或对象模拟巨大的负载 2、通过创建带有断言的脚本来验证程序是否能返回期望的结果 优…

URP-UGUI相关知识

一、UGUI的基本组成部分 Canvas &#xff08;画布&#xff09;所有UI都需要放在Canvas画布下面&#xff0c;不然无法显示EventSystem 所有的事件响应系统都需要依赖于EventSystem,若删除该组件&#xff0c;交互效果就 不会显示 1.Canvas(画…

ShenNiusModularity项目源码学习(20:ShenNius.Admin.Mvc项目分析-5)

ShenNiusModularity项目的系统管理模块主要用于配置系统的用户、角色、权限、基础数据等信息&#xff0c;上篇文章中学习的日志列表页面相对独立&#xff0c;而后面几个页面之间存在依赖关系&#xff0c;如角色页面依赖菜单页面定义菜单列表以便配置角色的权限&#xff0c;用户…

JavaFX 实战:从零打造一个功能丰富的英文“刽子手”(Hangman)游戏

大家好&#xff01;今天我们要挑战一个经典的单词猜谜游戏——“刽子手”&#xff08;Hangman&#xff09;&#xff0c;并使用 JavaFX 这个强大的 GUI 工具包来赋予它现代化的交互体验。这个项目不仅有趣&#xff0c;而且是学习和实践 JavaFX 核心概念的绝佳途径&#xff0c;涵…

【自我介绍前端界面分享】附源码

我用夸克网盘分享了「800套HTML模板」&#xff0c;链接&#xff1a;https://pan.quark.cn/s/a205a794552c <!DOCTYPE HTML> <html> <head> <title>Miniport</title> <meta http-equiv"content-type" content&q…

安宝特分享|AR智能装备赋能企业效率跃升

AR装备开启智能培训新时代 在智能制造与数字化转型浪潮下&#xff0c;传统培训体系正面临深度重构。安宝特基于工业级AR智能终端打造的培训系统&#xff0c;可助力企业构建智慧培训新生态。 AR技术在不同领域的助力 01远程指导方面 相较于传统视频教学的单向输出模式&#x…