快捷搜索: 王者荣耀 脱发

传统蓝牙搜索流程分析

传统蓝牙搜索流程分析

本期承接上篇分享《传统蓝牙BR/EDR的搜索Inquiry》来聊聊安卓系统中传统蓝牙搜索是如何实现的。

安卓系统中应用Application通过蓝牙适配器接口BluetoothAdapter.startDiscovery() 的调用触发搜索流程的开始,我们的分析也就从这里开启。

安卓源码版本:Android 9,P(Pie馅饼)版本

在分析之前对第三方应用有如下几个要求:

  1. 确保蓝牙状态打开
  2. 确保应用的清单文件 AndroidManifest.xml 中具有如下几个权限(也可动态申请)
  3. 注册了设备发现的广播接收处理,这样才能接收扫描到的蓝牙设备信息

Application通过满足上述三个条件后,只要触发搜索流程开启就可以等待设备信息的上报再做进一步处理,先让我们整体看下搜索流程的时序图:

以上就是传统蓝牙查询的完整流程,其实在开始传统蓝牙查询的同时,安卓系统也会开启低功耗蓝牙BLE的scan流程,时序图中将这部分内容去掉了,留待以后分析BLE扫描时再做分析(挖个坑…)。

从时序图中可以看出应用Application调用完BluetoothAdapter.startDiscovery() 后不需要其他操作了,只需耐心等待相关的系统广播即可。

指令一直被下发到协议栈bluedroid后,开始封装数据,并且中间的处理过程都是在协议栈中进行的,所以接下来重点分析下协议栈内部是如何玩转扫描流程的。

1、 首先指令到达协议栈btif_dm_start_discovery()处理函数中,设置了查询必要的相关参数 filter_type设置为0,传统蓝牙的查询Inquiry过滤关闭。

2、 指令进一步被下发到协议栈的stack层中的 BTM_StartInquiry() 继续处理,在这里判断查询模式参数如果包含ble,则发起ble的scan扫描。

3、 首先通过HCI指令 HCI_SET_EVENT_FILTER 设置Inquiry的过滤器

4、 设置过滤器的完成事件处理中调用 btm_initiate_inquiry() 开启真正的查询

5、 btm_acl_update_busy_level()中 event= BTM_BLI_INQ_EVT 更新当前协议栈的繁忙等级,并且通过JNI层的回调上报蓝牙服务层传统蓝牙查询开始。

6、 通过设置的查询模式确定Inquiry指令中的查询访问代码LAP值

7、 安卓系统蓝牙协议栈bluedroid中默认采用One-Time Inquiry查询方式,且该方式的查询结果上报的数量限制默认为 0 ,也就是不限制上报的数量。

8、 蓝牙控制器Controller通过(Inquiry Result、Inquiry Result with RSSI或者Extended Inquiry Result)三种上报事件中的一种依次上报查询到的设备结果到协议栈

9、 协议栈解析出设备信息后最后在btif_dm_search_devices_evt()函数中通过 event= BTA_DM_INQ_RES_EVT 将查询到的设备信息上报到蓝牙服务层

10、 服务层的RemoteDevices远端蓝牙设备管理类通过广播 “android.bluetooth.device.action.FOUND” 将设备信息广播出去

11、 查询时间12.8s触发,控制器Controller通过Inquiry Complete事件通知协议栈查询Inquiry流程完成。但协议栈在收到该完成事件时,不会立即上报服务层查询结束。

12、 协议栈会先通过查询记录对每一个设备发起Discovery流程(主要通过请求远端名)。

13、 最后所有查询记录中的设备都Discovery完成后,才会上报传统蓝牙查询结束。

经过以上这些步骤,安卓系统中的搜索流程成功完成。流程对应的HCI交互如下:

经验分享 程序员 微信小程序 职场和发展