基于Android P版本分析
Bluedroid
针对上层,蓝牙的核心就是AdapterService,它是蓝牙负责BT整个流程调度的中间服务,负责和JNI层进行交互,提供了控制蓝牙状态的调用逻辑;
对应的通过JNI与之交互的底层也有响应的逻辑。一般函数调用流程:APP -> FW -> JNI -> bluetoothinterface -> bluetooth HCI interface;
Bluedroid 架构
bluedroid 作为蓝牙协议栈,实现了蓝牙的所有操作;bluedroid主要分为3个部分:BTIF、BTA、Stack;
- BTIF:作为bluedroid与上层Java层的通道,提供了操作接口;
- BTA:提供各种Profile的实现;
- Stack:协议实现与连接管理;
整体的流转如下:
Bluetooth HAL
一般情况下,Bluetooth HAL层定义了Bluetooth Process和bluedroid之间进行交互的标准接口,即简单的理解为h头文件。其中bluetooth h 头文件定义在/hardware/libhardware目录中,但是在B16项目中,我们使用了在/system/bt目录下也定义了相同的标准接口;
| Interface | Desc |
|---|---|
| bluetooth.h | 包含蓝牙硬件操作,设备管理和设备操作抽象接口 |
| bt_av.h | 包含advanced audio profile的抽象接口 |
| bt_hf.h | 包含handsfree profile的抽象接口 |
| bt_hh.h | 包含hid host profile的抽象接口 |
| bt_bl.h | 包含health profile的抽象接口 |
| bt_pan.h | 包含pan profile的抽象接口 |
| bt_sock.h | 包含socket操作的抽象接口 |
| bt_gatt.h | 包含gatt 操作的抽象接口 |
| bt_hd.h | |
| bt_mce.h | |
| bt_rc.h | 包含 avrcp profile的抽象接口 |
| bt_sdp.h | 包含 sdp 操作的抽象接口 |
bluedroid 目录结构
我们描述几个重要的目录:
-
main:定处理配置信息,各个模块的初始化。链接 btif 和 hci,提供 btif 和 hci 的接口;
-
bta:bta用于Stack和Bluetooth Process层交互,实现蓝牙设备管理、状态管理以及一些Profile的bluedroid实现;
- ag:实现BTA音频网关;
- ar:负责Audio/Video注册;
- av:实现BTA advanced audio/video;
- dm:实现BTA设备管理;
- gatt:实现通用属性配置文件;
- hd:
- hearing_aid:
- hf_client:
- hh:实现HID协议(人机交互);
- hl:实现HDP协议(健康);
- mce:实现MAP协议;
- pan:实现PAN(蓝牙个人局域网)协议;
- pb:实现PBAP协议;
- sdp:实现SDP(简单发现)协议;
- sys:主要实现BTA系统管理;
-
btif:提供所有Bluetooth Process需要的API;
-
hci:HCI library的实现,主要内容包括HCI接口的打开和收/发控制、so的打开和回调注册、LPM的实现、btsnoop的抓取。读取或写入数据到蓝牙hw;
-
stack:协议实现与连接管理,协议包a2dp、avctp、avdtp、avrcp、bnep、gap、gatt、hid、l2cap、pan、rfcomm、sdp、mcap(多通道适配协议)、smp(用于生成对等协议的加密密钥和身份密钥)等;
- btm:bluetooth Manager;
- btu:该功能主要用于核心协议层之间的事件处理与转换,连接btif和HCI;
- gap:通用访问协议,定义了设备如何发现,建立连接,实现绑定;
- gatt:通用属性配置文件实现
- mcap:多通道适配协议
- smp:用于生成对等协议的加密密钥和身份密钥
bluetooth.h
我们现在存在两个bluetooth.h,一个在/hardware目录下,一个在/system/bt/include目录下,根据引入bluetooth.h不同来确定使用bluetooth.c还是bluetooth.cc;
| /system/bt bluetooth.h | /system/bt bluetooth.cc | Desc |
|---|---|---|
| int (*init) | init | 初始化 |
| int (*enable) | enable | 使能/开启 |
| int (*disable) | disable | 释能/关闭 |
| void (*cleanup) | cleanup | 关闭协议栈接口 |
| int (*get_adapter_properties) | get_adapter_properties | 获取所有的Adapter Property |
| int (*get_adapter_property) | get_adapter_property | 根据指定的Type来获取对应的Adapter Property |
| int (*set_adapter_property) | set_adapter_property | 通过指定的Type设置对应的Adapter Property |
| int (*get_remote_device_properties) | get_remote_device_properties | 获取远端设备的所有Property |
| int (*get_remote_device_property) | get_remote_device_property | 根据指定的Type来获取远端设备的Property |
| int (*set_remote_device_property) | set_remote_device_property | 通过指定的Type设置对应远端设备的Property |
| int (*get_remote_service_record) | get_remote_service_record | 根据UUID信息获取远端设备的Service 列表 |
| int (*get_remote_services) | get_remote_services | 开启 SDP 协议获取远程 Service |
| int (*start_discovery) | start_discovery | 开始搜寻发现 |
| int (*cancel_discovery) | cancel_discovery | 终止搜寻发现 |
| int (*create_bond) | create_bond | 创建蓝牙绑定 |
| int (*create_bond_out_of_band) | create_bond_out_of_band | 使用带外数据创建蓝牙绑定 |
| int (*add_out_of_band_bond_device) | add_out_of_band_bond_device | 添加带外绑定设备 |
| void (*get_link_key) | get_link_key | 获取链接key Message |
| int (*remove_bond) | remove_bond | 移除绑定 |
| int (*cancel_bond) | cancel_bond | 终止绑定 |
| int (*get_connection_state) | get_connection_state | 获取连接状态 |
| int (*pin_reply) | pin_reply | BT 传统 PIN码 恢复 |
| int (*ssp_reply) | ssp_reply | |
| const void* (*get_profile_interface) | get_profile_interface | 获取蓝牙配置文件接口 |
| int (*dut_mode_configure) | dut_mode_configure | 配置DUT模式 |
| int (*dut_mode_send) | dut_mode_send | 发送DUT模式 |
| int (*le_test_mode) | le_test_mode | BLE 测试模式 API |
| int (*set_os_callouts) | set_os_callouts | 设置bluedroid用于报警和唤醒锁的操作系统调出功能。应在init执行成功之后立即调用此函数 |
| int (*read_energy_info) | read_energy_info | 读取Energy详细信息 |
| void (*dump) | dump | dump信息 |
| void (*dumpMetrics) | dumpMetrics | |
| int (*config_clear) | config_clear | 清空/data/misc/bt_config.conf文件,其中包含了BT device(localhost and Remote)信息 |
| void (*interop_database_clear) | interop_database_clear | 清除(重置)设备互操作性数据库的动态部分 |
| void (*interop_database_add) | interop_database_add | 添加设备互操作性数据库的动态部分。 |
| bluetooth::avrcp::ServiceInterface* (*get_avrcp_service) | get_avrcp_service | 获取AvrcpTarget服务接口以与Avrcp服务交互 |
| int (*read_local_oob_data) | read_local_oob_data | 读取带外数据 |
| std::string (*get_profiles_version) | get_profiles_version | 获取profiles版本信息 |
| int (*incoming_connection_reply) | incoming_connection_reply | 来电连接回复 |
上述的这些接口,基本上涉及到的都是蓝牙整个流程调度、蓝牙状态控制的逻辑,基本上对应的就是上层AdapterService;
我们可以基于BT的启动流程,追踪分析底层协议栈的加载和启动流程;
HCI Command
Command
Bluetooth HCI Command - Write Class of Device
Command Opcode: Write Class of Device (0x0c24)
0000 11.. .... .... = Opcode Group Field: Host Controller & Baseband Commands (0x03)
.... ..00 0010 0100 = Opcode Command Field: Write Class of Device (0x024)
Parameter Total Length: 3
Class of Device: 0x360408 (Audio/Video:Hands-free Device - services: Networking Rendering ObjectTransfer Audio)
0000 10.. = Minor Device Class: Hands-free Device (0x02)
.... ..00 = Format Type: 0x0
0... .... .... .... = Major Service Classes: Information: False
.0.. .... .... .... = Major Service Classes: Telephony: False
..1. .... .... .... = Major Service Classes: Audio: True
...1 .... .... .... = Major Service Classes: Object Transfer: True
.... 0... .... .... = Major Service Classes: Capturing: False
.... .1.. .... .... = Major Service Classes: Rendering: True
.... ..1. .... .... = Major Service Classes: Networking: True
.... ...0 .... .... = Major Service Classes: Positioning: False
.... .... 00.. .... = Major Service Classes: Reserved: 0x0
.... .... ..0. .... = Major Service Classes: Limited Discoverable Mode: False
.... .... ...0 0100 = Major Device Class: Audio/Video (0x04)
[Response in frame: 96]
[Command-Response Delta: 1.451ms]
我们以Write Class of Device HCI Command为例,说明一下Command Opcode;
Command Opcode分为两个字段:
-
Opcode Group Field(OGF):组域段,高6bit
- Link Control Commands(0x01):链路控制OGF,也就是控制蓝牙芯片跟remote通信的Command;
- Link Policy Commands(0x02):链路策略OGF,也就是写一些Policy,比如转换角色等;
- Host Controller and Baseband Commands(0x03):控制本地芯片和基带的OGF,比如reset 本地芯片;
- Informational Parameters Commands(0x04):读取信息的OGF,比如读取本地芯片的LMP版本、支持的Command、蓝牙地址信息等;
- Status Parameters Commands(0x05):状态参数OGF,例如读取RSSI等;
- Testing commands(0x06):测试命令的OGF,例如让芯片进入测试模式(DUT,Device under test);
- LE Controller Commands(0x08):BLE(低功耗)命令;
- Vendor-Specific Debug Commands(0x3F):该OGF用于特定于供应商的调试指令,此部分是vendor定义的,也就是芯片厂商为了扩展core文档的HCI command定义;
-
Opcode Command Field(OCF):指令域段,低10bit,OCF定义众多,在每个OGF下都有一系列的OCF定义;
Parameter Total Length:后续参数的长度;
传统蓝牙HCI Command
| OGF(Opcode Group Field) | OCF(Opcode Command Field) | Command | Desc |
|---|---|---|---|
| Link Control command(0x01):链路控制指令 | 0x0001 | Inquiry command | 让BR/EDR芯片进行搜索模式,搜索周边的BR/EDR设备 |
| 0x0002 | Inquiry Cancel command | 让BR/EDR芯片进入周期搜索状态 | |
| 0x0003 | Periodic Inquiry Mode command | 让BR/EDR芯片进入周期搜索状态 | |
| 0x0004 | Exit Periodic Inquiry Mode command | 让进入周期搜索状态的BR/EDR蓝牙芯片退出周期搜索状态 | |
| 0x0005 | Create Connection command | 根据参数跟特定的蓝牙地址创建连线 | |
| 0x0006 | Disconnect command | 根据参数跟特定的连接句柄断开连接,可以用来断开ACL,也可以用来断开SCO,eSCO等等 | |
| 0x0008 | Create Connection Cancel command | “连接中”的取消指令 | |
| 0x0009 | Accept Connection Request command | 接受连接请求 | |
| 0x000A | Reject Connection Request command | 拒绝连接请求 | |
| 0x000B | Link Key Request Reply command | 对方请求linkkey的时候,而我们有此link key,我们回复link key | |
| 0x000C | Link Key RequestNegative Reply command | 对方请求linkkey的时候,而我们没有次link key的情形下回复 | |
| 0x000D | PIN Code Request Reply command | 用于应答芯片发送的pincode申请,并把pincode用于连线 | |
| 0x000E | PIN Code RequestNegative Reply command | 不能用于pin code连线 | |
| 0x000F | Change Connection Packet Type command | 改变正在连接的交互封包类型 | |
| 0x0011 | Authentication Requested command | 用于指令连接句柄的两个蓝牙地址进行身份认证 | |
| 0x0013 | Set Connection Encryption command | 建立或者取消连接层次的加密 | |
| 0x0015 | Change Connection Link Key command | 用于指定额链接句柄,生成一组新的link key | |
| 0x0017 | Master Link Key command | 用于强制主设备使用主设备的临时或半永久link key | |
| 0x0019 | Remote Name Request command | 获取远端设备名称 | |
| 0x001A | Remote Name Request Cancel command | 取消获取远端设备名称 | |
| 0x001B | Read Remote Supported Features command | 获取remote端支持的feature | |
| 0x001C | Read Remote Extended Features command | 获取remote端支持的扩展feature | |
| 0x001D | Read Remote Version Information command | 获取remote端版本信息,注意此部分是LMP或者LL的版本 | |
| 0x001F | Read Clock Offset command | 获取时钟偏移 | |
| 0x0020 | Read LMP Handle command | 获取LMP句柄 | |
| 0x0028 | Setup Synchronous Connection command | 建立SCO | |
| 0x0029 | Accept Synchronous Connection Request command | 接受对方SCO建立请求 | |
| 0x002A | Reject SynchronousConnection Request command | 拒绝对方SCO建立请求 | |
| 0x002B | IO Capability Request Reply command | 当在SSP配对模式下,响应芯片IO capability的请求 | |
| 0x002C | User Confirmation Request Reply command | 当在SSP配对模式下,响应芯片IO User Confirmation的请求 | |
| 0x002D | User Confirmation Request Negative Reply command | 当在SSP配对模式下,拒绝芯片IO User Confirmation的请求 | |
| 0x0034 | IO Capability RequestNegative Reply command | 当在SSP配对模式下,拒绝芯片IO capability的请求 | |
| Link Policy commands (0x02):链路策略指令 | 0x0001 | Hold Mode command | 用于更改链接的行为,并让它将指定的Connection_Handle关联的ACL基带连接放置到Holdmode中 |
| 0x0003 | Sniff Mode command | 用于改变该链接的行为管理并让它将与指定Connection_Handle关联的ACL基带连接置于嗅探模式 | |
| 0x0004 | Exit Sniff Mode command | 离开嗅探模式 | |
| 0x0007 | QoS Setup command | 用于为Connection_Handle指定服务质量参数 | |
| 0x0009 | Role Discovery command | 查询当前的连线芯片处于什么角色 | |
| 0x000B | Switch Role command | 进行角色切换 | |
| 0x000C | Read Link Policy Settings command | 读取当前connection_handle的连接策略 | |
| 0x000D | Write Link Policy Settings command | 改变当前连线的连接策略 | |
| 0x000E | Read Default Link Policy Settings command | 读取默认的连接策略 | |
| 0x000F | Write Default Link Policy Settings command | 改变当前默认的连接策略 | |
| 0x0010 | Flow Specification command | 用于指定通过Connection_Handle标识的ACL Connection_Handle传输的流量的流参数 | |
| 0x0011 | Sniff Subrating command | 为给定链接指定用于嗅探子例程的参数 | |
| Control and Baseband commands(0x03):主机控制器与基带指令 | 0x0001 | Set Event Mask command | 用于控制HCI为主机生成哪些事件 |
| 0x0003 | Reset command | reset蓝牙芯片(软复位) | |
| 0x0005 | Set Event Filter command | 设置事件过滤 | |
| 0x0008 | Flush command | 丢弃芯片中正在等待传输的数据 | |
| 0x0009 | Read PIN Type command | 读取PIN 类型 | |
| 0x000A | Write PIN Type command | 写PIN类型 | |
| 0x000D | Read Stored Link Key command | 读取芯片中存储的Link key | |
| 0x0011 | Write Stored Link Key command | 把link key写入到芯片中 | |
| 0x0012 | Delete Stored Link Key command | 删除芯片中的Link key | |
| 0x0013 | Write Local Name command | 写入本地名称到芯片中 | |
| 0x0014 | Read Local Name command | 读取芯片的蓝牙名称 | |
| 0x0015 | Read Connection Accept Timeout command | 读取蓝牙连接接收的超时时间 | |
| 0x0016 | Write Connection Accept Timeout command | 写入蓝牙连接接收的超时时间 | |
| 0x0017 | Read Page Timeout command | 读取page的超时时间 | |
| 0x0018 | Write Page Timeout command | 写page的超时时间 | |
| 0x0019 | Read Scan Enable command | 读取scan enable | |
| 0x001A | Write Scan Enable command | 写scan enable | |
| 0x001B | Read Page Scan Activity command | 读取Page Scan Activity | |
| 0x0023 | Read Class of Device command | 读取芯片的cod | |
| 0x0024 | Write Class of Device command | 把cod写入cod | |
| 0x0025 | Read Voice Setting command | 读取voice setting | |
| 0x0026 | Write Voice Setting command | 把voice setting写入到芯片 | |
| 0x0031 | Set Controller To Host Flow Control command | 启动HCI 流控 | |
| 0x0033 | Host Buffer Size command | 把buffer size写入到芯片中 | |
| 0x0036 | Read Link Supervision Timeout command | 读取Link Supervision timeout时间(也就是Link lost时间) | |
| 0x0037 | Write Link Supervision Timeout command | 把Link Supervision timeout写入到芯片(也就是Link lost时间) | |
| 0x0044 | Read Inquiry Mode command | 读取芯片的搜索模式 | |
| 0x0045 | Write Inquiry Mode command | 把搜索模式写入到芯片中 | |
| 0x0051 | Read Extended Inquiry Response command | 读取芯片的Extended inquiry response | |
| 0x0052 | Write Extended Inquiry Response command | 把Extended inquiry response写入到芯片 | |
| 0x0055 | Read Simple Pairing Mode command | 读取芯片是否支持SSP | |
| 0x0056 | Write Simple Pairing Mode command | 把是否支持SSP写入到蓝牙芯片 | |
| Informational Parameters commands(0x04):信息参数指令 | 0x0001 | Read Local Version Information command | 读取本地芯片的LMP version |
| 0x0002 | Read Local Supported Commands command | 读取本地芯片支持的command | |
| 0x0003 | Read Local Supported Features command | 读取本地芯片支持的feature | |
| 0x0004 | Read Local Extended Features command | 读取本地芯片支持的扩展feature | |
| 0x0005 | Read Buffer Size command | 读取本地芯片的buffer size | |
| 0x0009 | Read BD_ADDR command | 读取本地芯片的蓝牙地址 | |
| 0x000A | Read Data Block Size command | 读取本地芯片的block size | |
| 0x000B/D | Read Local Supported Codecs command | 读取本地芯片支持的编码格式 | |
| 0x000C | Read Local Simple Pairing Options command | 读取本地SSP选项 | |
| 0x000E | Read Local Supported Codec Capabilities command | 读取本地芯片支持的codec capabilities | |
| status parameters commands (0x05):状态参数指令 | 0x0003 | Read Link Quality command | 读取连接质量 |
| 0x0005 | Read RSSI command | 读取接收信号强度 | |
| 0x0007 | Read Clock command | 读取clock | |
| Testing commands (0x06):测试指令 | 0x0001 | Read Loopback Mode command | 去读loopback模式 |
| 0x0002 | Write Loopback Mode command | 写loopback模式 | |
| 0x0003 | Enable Device Under Test Mode command | 使设备进去测试模式 |
HCI Event
理论上,每一个HCI Command都会对应一个HCI Event,很多HCI Command对应的HCI Event为同一个,Command 和 Event的关系为:多对一的关系;
HCI Event同理也分为BLE专用和传统的HCI Event;
传统蓝牙HCI Event
| Event Code | EVENT | Desc |
|---|---|---|
| 0x01 | Inquiry Complete Event | 搜索完成 |
| 0x02 | Inquiry Result Event | 搜索结果 |
| 0x03 | Connection Complete Event | 连接完成 |
| 0x04 | Connection Request Event | 连接请求 |
| 0x05 | Disconnection Complete | 断开完成 |
| 0x06 | Authentication Complete event | 授权完成 |
| 0x07 | Remote Name Request Complete event | 获取远端蓝牙名称完成 |
| 0x08 | Encryption Change event | 加密模式改变完成 |
| 0x09 | Change Connection Link Key Complete event | 改变连接的link key完成 |
| 0x0A | Master Link Key Complete event | 管理Link key完成 |
| 0x0B | Read Remote Supported Features Complete event | 读取远端设备feature完成 |
| 0x0C | Read Remote VersionInformation Complete event | 读取远端版本完成 |
| 0x0D | QoS Setup Complete event | Qos setup完成 |
| 0x0E | Command Complete event | 命令完成 |
| 0x0F | Command Status event | 命令状态消息 |
| 0x10 | Hardware Error event | 蓝牙芯片硬件错误 |
| 0x12 | Role Change event | 角色切换事件 |
| 0x13 | Number Of Completed Packets event | 完成封包个数 |
| 0x14 | Mode Change event | 模式改变 |
| 0x15 | Return Link Keys event | 返回link key |
| 0x16 | PIN Code Request event | PIN code请求 |
| 0x17 | Link Key Request event | Link key请求 |
| 0x18 | Link Key Notification event | Link key通知 |
| 0x19 | Loopback Command event | Loopback模式返回的事件 |
| 0x1A | Data Buffer Overflow event | 芯片buffer爆掉 |
| 0x1B | Max Slots Change event | 最大slot变化 |
| 0x1C | Read Clock Offset Complete event | 读取时钟偏移完成 |
| 0x1D | Connection PacketType Changed event | 连接封包类型变化 |
| 0x1E | QoS Violation event | Qos违规 |
| 0x22 | Inquiry Result with RSSI event | 带RSSI的搜索结果 |
| 0x2C | Synchronous Connection Complete event | SCO连接完成 |
| 0x2F | Extended Inquiry Result event | 带EIR的搜索结果 |
| 0x31 | IO Capability Request event | IO capability请求 |
| 0x32 | IO Capability Response event | IO capability回复 |
| 0x33 | User Confirmation Request event | SSP配对方式用户确认请求 |
| 0x36 | Simple Pairing Complete event | SSP配对完成 |
L2CAP信令指令码
| Code | Previous Name(Core_4.2) | Current Description(Core_5.3) | Desc |
|---|---|---|---|
| 0x00 | RESERVED | RESERVED | 保留 |
| 0x01 | Command reject | L2CAP_COMMAND_REJECT_RSP | 拒绝命令 |
| 0x02 | Connection request | L2CAP_CONNECTION_REQ | 连接请求 |
| 0x03 | Connection response | L2CAP_CONNECTION_RSP | 连接响应 |
| 0x04 | Configure request | L2CAP_CONFIGURATION_REQ | 配置请求 |
| 0x05 | Configure response | L2CAP_CONFIGURATION_RSP | 配置响应 |
| 0x06 | Disconnection request | L2CAP_DISCONNECTION_REQ | 断开请求 |
| 0x07 | Disconnection response | L2CAP_DISCONNECTION_RSP | 断开响应 |
| 0x08 | Echo request | L2CAP_ECHO_REQ | |
| 0x09 | Echo response | L2CAP_ECHO_RSP | |
| 0x0A | Information request | L2CAP_INFORMATION_REQ | 信息请求 |
| 0x0B | Information response | L2CAP_INFORMATION_RSP | 信息响应 |