安卓系统bluedroid启用流程分析
在上一篇文章《安卓中蓝牙系统服务层的使能流程分析》的基础上,本文分析了协议栈层的启用流程。 因此,蓝牙协议栈bluedroid的使能以在JNI层enableNative () )上调用协议栈接口enable ) )函数开始。
不言而喻,按照惯例,我们将整个映像协议栈的启用。 请参考以下时序图。
Android本机bluedroid按层次分为btif、bta、stack和hci四个层,每个层的作用不同,但实际程序运行在不同的线程上,对启用过程有更深的了解接下来,按照上述顺序分别进行说明。
蓝牙服务层JNI启用协议栈bluedroid,并通过接口函数接口发出到达协议栈入口的指示。
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 /蓝牙/logs /
打开snoop开关的步骤很复杂,一般用户无法进入开发人员选项,甚至很难从哪里打开开发人员选项,因此在蓝牙开发过程中修改源代码或修改persist.bluetooth 目前有两种方法:
方法a :
修复在源代码中获取persist.bluetooth.btsnoopenable值时设置的错误值
由于此全局变量是在开发人员选项中首次打开snoop交换机时创建的,因此必须从未操作过snoop交换机。 操作开发人员可选的snoop开关时,获取上述全局变量将获取相应的值,错误值将不起作用。
方法b :
命令:在ADB shell setprop persist.bluetooth.btsnoopenabletrue中打开蓝牙HCI-snoop开关。
persist.bluetooth.btsnoopenable全局变量的存储路径因Android版本而稍有不同。
Android 8存储路径:/data/property/persist.bluetooth.btsnoopenable /
Android 9存储路径:/data/property/persistent _ properties /
2、HCI模块:
创建hci_thread线程,专用于hci相关进程,同时初始化蓝牙芯片。
要使用HIDL技术获取芯片控制器模块向外部提供的接口,请:
1.bthci=ibluetoothhci :3360 getservice (;
2.Android :3360 sp callbacks=newbluetoothcicallbacks (;
3.bthci-initialize(callbacks );
全名是hidl (HAL interface definition language,全称是Hal interface definition language ),以前Android有AIDL,Android binder上面有体系结构。 Android曾用于定义基于Binder通信的客户端和服务之间的接口,HIDL也起到了类似的作用,但它定义了Android框架和Android HAL实现之间的接口
Android HAL的实现方式因芯片制造商而异,实现内容都是类似Android源代码的hardwareinterfacesbluetooth1.0 的实现方式。 制造商进一步通过HAL的实现与本公司芯片进行交互。 这样可以通过统一的HAL接口实现软硬件分离,安卓系统可以集成不同厂商的蓝牙芯片。
芯片模块初始化完成后,将通过回调通知android层,让蓝牙协议栈继续后续的启用过程。
启用HCI模块后,它进入BTU_StartUp ()函数,开始初始化BTU控制模块,包括协议栈密钥模块,如BTU、BTM、L2CAP和SDP
启用controller模块实际上是使用一组HCI命令从芯片层获取支持的功能参数
类型定义结构{
Bt_HDR*(make_re
set)(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层的交互如下图:
Reset完成后协议栈会主动下发HCI命令读取本端的蓝牙名字,并将新的名字下发给芯片,同时通过JNI层的回调将本端的蓝牙名字和地址上报给服务层。如果存在配对的蓝牙设备,也会将该设备信息上报。
紧接着会初始化协议栈的socket模块,这部分主要是为建立OBEX连接和数据交互做准备的。
协议栈所有使能工作完成,通过HAL bt_hal_cbacks->adapter_state_changed_cb回调将蓝牙使能成功的消息上报到JNI层。至此蓝牙协议栈bluedroid的使能流程的全部过程就分析完毕。
本篇协议栈使能的分析就到这儿了,感兴趣的小伙伴欢迎私信留言一起讨论。