当前位置:   article > 正文

android蓝牙通信_安卓系统蓝牙协议栈 bluedroid 的使能

android 蓝牙协议栈

安卓系统蓝牙协议栈 bluedroid 使能流程分析

9c31476070011dab4edcded9a03ce40c.png

本文承接上篇文章《安卓中蓝牙系统服务层的使能流程分析》,接续分析协议栈层相关的使能流程,所以蓝牙协议栈bluedroid的使能始于JNI层enableNative()中调用协议栈接口enable()函数。

667e0fe65ba72d7edebb0b2ab4cd5293.png

话不多说,还是按照老规矩我们先从整体上对协议栈的使能有个印象,参考如下时序图

349463a03cde5871437ed2291ca94faa.png

安卓原生的蓝牙协议栈bluedroid在分层上被分为btif、bta、stack、hci这四层,每层的作用各不相同,但实际程序运行是在不同的线程运行的,为了方便大家对使能流程有更为深刻的了解,所以上述的使能时序图是以线程为依据。接下来就按照上述时序分别作出说明。

蓝牙服务层JNI使能协议栈bluedroid,通过interface函数接口下发指令到达协议栈入口。

stack_manager_get_interface()->start_up_stack_async();将使能指令下发到协议栈管理模块,模块内部通过线程stack_manage继续处理。

依次使能btif_config、btsnoop、hci等模块

1、 btsnoop模块:

判断snoop开关是否打开,从而决定是否创建snoop文件来记录hci的交互信息。

snoop开关位置在开发者选项中,打开该关开,则persist.bluetooth.btsnoopenable全局变量会被置为true;反之开关关闭,该变量会被置为false。

snoop文件默认存储位置:/data/misc/bluetooth/logs/

由于打开snoop开关的步骤比较复杂,一般用户根本不会进到开发者选项中,连从哪儿打开开发者选项都是一个难题,所以蓝牙开发过程中可以修改源码或重置persist.bluetooth.btsnoopenable的值来达到创建snoop文件记录hci的交互信息的目的。现提供如下两种方法

方法A:

修改源码中获取 persist.bluetooth.btsnoopenable 值时设置的错误值

bfb0819b8acd270ec6c6021ffd946bdd.png

该全局变量是第一次在开发者选项中打开snoop开关时创建的,所以从来没操作过snoop开关,则该全局变量就没有定义。如果操作过开发者选项中的snoop开关,则获取上述全局变量就可以获取到对应的值,从而错误值不再起作用。

方法B:

通过指令:adb shell setprop persist.bluetooth.btsnoopenable true,开启蓝牙hci-snoop的开关。

persist.bluetooth.btsnoopenable 全局变量的存储路径因安卓版本而有些许差异:

Android 8的存储路径/data/property/persist.bluetooth.btsnoopenable/

Android 9的存储路径/data/property/persistent_properties/

2、 HCI模块:

创建hci_thread线程,专门处理hci相关的流程,并同时初始化蓝牙芯片。

通过HIDL技术获取芯片Controller模块对外提供的接口:

btHci = IBluetoothHci::getService();android::sp callbacks = new BluetoothHciCallbacks();btHci->initialize(callbacks);

HIDL:全称是HAL interface definition language(硬件抽象层接口定义语言),在此之前Android 有AIDL,架构在Android binder 之上,用来定义Android 基于Binder通信的Client 与Service之间的接口。HIDL也是类似的作用,只不过定义的是Android Framework与Android HAL实现之间的接口。

Android HAL的实现方式由于芯片厂商的不同而有差异,实现内容都是类似于安卓源码中hardwareinterfacesbluetooth1.0中的实现方式。厂商然后在HAL的实现中与自家芯片进行交互。这样通过统一的HAL接口就可以实现软硬件分离,安卓系统就可以集成不同厂家的蓝牙芯片。

芯片模块初始化完成后会通过回调告知android层,这样蓝牙协议栈才会继续后面的使能流程。

随着HCI模块使能完成就进入BTU_StartUp( )函数中开始初始化BTU控制模块,包括BTU、BTM、L2CAP、SDP等协议栈关键模块

使能controller模块,实际上就是通过一组HCI命令从芯片层获取支持的功能参数

typedef struct {BT_HDR* (*make_reset)(void);BT_HDR* (*make_read_buffer_size)(void);BT_HDR* (*make_host_buffer_size)(uint16_t acl_size, uint8_t sco_size, uint16_t acl_count, uint16_t sco_count);BT_HDR* (*make_read_local_version_info)(void);BT_HDR* (*make_read_bd_addr)(void);BT_HDR* (*make_read_local_supported_commands)(void);BT_HDR* (*make_read_local_extended_features)(uint8_t page_number);BT_HDR* (*make_write_simple_pairing_mode)(uint8_t mode);BT_HDR* (*make_write_secure_connections_host_support)(uint8_t mode);BT_HDR* (*make_set_event_mask)(const bt_event_mask_t* event_mask);BT_HDR* (*make_ble_write_host_support)(uint8_t supported_host, uint8_t simultaneous_host);BT_HDR* (*make_ble_read_white_list_size)(void);BT_HDR* (*make_ble_read_buffer_size)(void);BT_HDR* (*make_ble_read_supported_states)(void);BT_HDR* (*make_ble_read_local_supported_features)(void);BT_HDR* (*make_ble_read_resolving_list_size)(void);BT_HDR* (*make_ble_read_suggested_default_data_length)(void);BT_HDR* (*make_ble_read_maximum_data_length)(void);BT_HDR* (*make_ble_read_maximum_advertising_data_length)(void);BT_HDR* (*make_ble_read_number_of_supported_advertising_sets)(void);BT_HDR* (*make_ble_set_event_mask)(const bt_event_mask_t* event_mask);BT_HDR* (*make_read_local_supported_codecs)(void);}

HCI层的交互如下图:

497ac62ef570baf86833182a1e79817a.png

Reset完成后协议栈会主动下发HCI命令读取本端的蓝牙名字,并将新的名字下发给芯片,同时通过JNI层的回调将本端的蓝牙名字和地址上报给服务层。如果存在配对的蓝牙设备,也会将该设备信息上报。

紧接着会初始化协议栈的socket模块,这部分主要是为建立OBEX连接和数据交互做准备的。

协议栈所有使能工作完成,通过HAL bt_hal_cbacks->adapter_state_changed_cb回调将蓝牙使能成功的消息上报到JNI层。至此蓝牙协议栈bluedroid的使能流程的全部过程就分析完毕。

本篇协议栈使能的分析就到这儿了,感兴趣的小伙伴欢迎私信留言一起讨论。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/326533
推荐阅读
相关标签
  

闽ICP备14008679号