蓝牙地址的name为null_蓝牙, enable协议栈流程

f2de73135c1c195d858925e35f613fb6.gif

文章开始之前,先看两张图

a0e0df5d5a5b9f5096d13a0106d534b8.png

86deb0511534167309602051ad4295e7.png

原谅我这个不擅长美工没有艺术细菌的程序媛,图画的很简陋,但也算是勾勒出了大致的流程如果你对这两张图感兴趣,那么欢迎继续阅读本文,也期待多多提出意见如果无感,甚至感觉目前根本没有耐心看下去,那我建议你此时可以放弃阅读本文的想法。每个人的时间都是很宝贵的,没有必要逼着自己,完成这项违背意愿的任务你看或不看,文章就在这里...只有在心情愉悦时,才能创造出令人愉悦的代码接下来的任务,就是和我一起对这两张图进行分析上文分析了 enable的上层的处理蓝牙,信息获取和 enable状态切换,本文分析协议栈的处理分析过程中关于前面两个文章中分析过的代码,就不再进行分析通过两篇文章的分析
  • 蓝牙,从系统开机说起

  • 蓝牙,信息获取和enable状态切换

可以确定 BluetoothManagerService是蓝牙系统级别的服务,运行在 system进程。并且在开机之后长存,与蓝牙的开关状态无关蓝牙开启的第一个服务是 AdapterService,也就是蓝牙的入口。 AdapterService是和蓝牙的开关状态保持一致的在开启蓝牙时最先要 bind起来的就是该服务。所以直接来看该服务的处理蓝牙应用中有一个 Application:AdapterApp.代码很少,一起顺带分析了
在 AdapterService创建时静态加载 jni的库
1//AdapterApp.java
2 System.loadLibrary("bluetooth_jni");
静态初始化 native
1//AdapterService.java
2 classInitNative();
接下来在服务的生命周期方法 onCreate,创建时又再次初始化 native,但是调用的方法不一样
1//AdapterService.java
2initNative();
打住,到此为止先分析一下,已经做了三件事儿
  1. 加载jni库libbluetooth_jni

  2. 初始化操作classInitNative

  3. 初始化操作initNative

库加载过程属于 common的方法就不再分析,重点关注初始化
方法实现都在 jni层

首先是classInitNative方法

 1//com_android_bluetooth_btservice_AdapterService.cpp
2static void classInitNative(JNIEnv* env, jclass clazz) {
3...
4jclass jniCallbackClass =
5  env->FindClass("com/android/bluetooth/btservice/JniCallbacks");
6...
7method_stateChangeCallback =
8  env->GetMethodID(jniCallbackClass, "stateChangeCallback", "(I)V");
9...
10if (hal_util_load_bt_library((bt_interface_t const**)&sBluetoothInterface)) {
11  ALOGE("No Bluetooth Library found");
12}
13...
14}
这个方法关注两件事儿首先是把 java层的方法映射过来,供 jni层调用。映射过来的方法都是 JniCallbacks.java中的方法,用来在 hal层有消息回调时触发给上层另一个操作就是去加载协议栈的 so包,并获取到变量名为 bluetoothInterface的地址以后jni层再往下的调用就要依靠这个 bluetoothInterface了加载的是哪个 so包?拿到的 so包的谁的地址?继续分析
1int hal_util_load_bt_library(const bt_interface_t** interface) {
2  const char* sym = BLUETOOTH_INTERFACE_STRING;//"bluetoothInterface"
3  ...
4  property_get(PROPERTY_BT_LIBRARY_NAME, path, DEFAULT_BT_LIBRARY_NAME);
5  ...
6 (bt_interface_t*)dlsym(handle, sym);
7  ...
8}
加载的是属性值“ ro.bluetooth.library_name”(可以使用 adb命令查看属性值)字段所声明的一个地址下的 so包拿到是 blutoothInterface的地址完事儿了,拿到之后把地址交给 sBluetoothInterface,之后jni就可以通过该字段来访问蓝牙所提供的接口了也即是说, classInitNative的作用有两个
  1. 映射java层方法

  2. 获取协议栈的蓝牙接口对象地址

相当于在 jni层获取两个对象,一个 java层对象,一个是协议栈的 so包中的对象获取对象之后,你就可以调用对象的方法了获取到的蓝牙接口对 jni提供的方法有哪些?
都在 bluetooth.cc文件中列出来了

45048225b52006cd7fa1f6d9a0a54948.png

bluetoothInterface 接口方法如上,就不一一分析了

另一个initNative

在获取到对象之后,需要对这个对象进行初始化,配置一些基本信息。
先看一下代码
 1//com_android_bluetooth_btservice_AdapterService.cpp
2static bool initNative(JNIEnv* env, jobject obj) {
3  ...
4  sBluetoothInterface->init(&sBluetoothCallbacks);
5  ...
6  sBluetoothInterface->set_os_callouts(&sBluetoothOsCallouts);
7  ...
8  sBluetoothSocketInterface =
9   (btsock_interface_t*)sBluetoothInterface->get_profile_interface(
10       BT_PROFILE_SOCKETS_ID);
11   ...
12}
主要就是这三件事儿了
  1. init调用蓝牙接口的初始化

  2. set_os_callouts这个主要是对wakelock唤醒锁的管理,目前以功能分析为主,暂时不分析代码设计

  3. 获取到socket的profile对象,有何用?继续分析

拆开分析,去 bluetooth.cc文件中查看方法的实现第一个, init干了什么?
 1//system/bt/btif/src/bluetooth.cc
2static int init(bt_callbacks_t* callbacks) {
3  ...
4  bt_hal_cbacks = callbacks;
5  ...
6  stack_manager_get_interface()->init_stack();
7  ...
8  btif_debug_init();
9  ...
10}
越往下分析你会发现代码越简单, java层要考虑各种功能和交互而 hal层代码只需要认真的把功能实现就好了,顺便再把状态回调给上层就 ok了所以 init中也很简单,首先是把 jni层的 callback对象拿过来,方便后续进行回调之后,看函数名字应该就是初始化 stack了,也就是蓝牙核心模块要初始化了最后是初始化 log相关的了(初始化 btsnoop)。重点关注 stack的初始化,分析一下对 stack的处理
 1//system/bt/btif/src/stack_manager.cc
2static void event_init_stack(void* context) {
3...
4   module_management_start();
5   module_init(get_module(OSI_MODULE));
6   module_init(get_module(BT_UTILS_MODULE));
7   module_init(get_module(BTIF_CONFIG_MODULE));
8   btif_init_bluetooth();
9...
10}
协议栈的初始化好像东西有点儿多啊,还有三个排比句 get_module 方法其实就是dlsym(RTLD_DEFAULT, name),会在当前进程中按照默认lib包的搜索顺序来搜索name这个symbol  module_init方法就是对所传入的module调用init方法
  • 开启核心模块的管理,这个方法目前是空实现

  • OSI_MODULE,初始化osi模块:搜索到的symbol是osi_module.cc文件中的osi_module,也就是要调用osi_module的init方法。暂时不清楚用处,后续研究

  • BT_UTILS_MODULE,初始化bt_utils模块:搜索到的symbol是bt_utils.cc文件中的bt_utils_module,这个init方法大致看了下,确认过眼神,是我不懂的操作。一些赋值操作,看名字和任务栈有关,后续如果分析到再看吧

  • BTIF_CONFIG_MODULE,初始话蓝牙配置模块:搜索到的symbol是btif_config.cc文件中的btif_config_module,init的目的就是去管理前文说到的bt_config相关的文件,比如恢复出厂后需要删除文件重新创建啊,以及文件里边儿现在要写什么啊等等。总之就是管理蓝牙配置文件的一个模块

  • 初始化蓝牙,从这儿开始就会把整个蓝牙协议栈创建起来,为蓝牙的开启做准备工作

各个模块的初始化如上分析,不再深究了接下来看一下 bt_init_bluetooth,也就是对蓝牙的初始化
1//system/bt/btif/src/btif_core.cc
2bt_status_t btif_init_bluetooth() {
3   //Creates BTIF task and prepares BT scheduler for startup
4   ...
5   bte_main_boot_entry();
6   ...
7}
btif_init_bluetooth方法会创建蓝牙接口任务栈,并且为蓝牙的开启做准备。主要是调用 bte_main_boot_entry方法
 1//system/bt/main/bte_main.cc
2void bte_main_boot_entry(void) {
3  //Entry point for BTE chip/stack initialization
4  ...
5  module_init(get_module(INTEROP_MODULE));
6  ...
7  hci = hci_layer_get_interface();
8  ...
9  module_init(get_module(STACK_CONFIG_MODULE));
10  ...
11}
bte_main_boot_entry方法用于初始化蓝牙芯片和协议栈
初始化的话主要是三个方面
  1. INTEROP_MODULE初始化interop_module模块,init为空实现,不需要考虑

  2. hci,获取到hci层接口,方法实现位于/system/bt/hci/src/hci_layer.cc文件中

  3. STACK_CONFIG_MODULE初始化,会操作/etc/bluetooth/bt_stack.conf文件,文件中是对协议栈的一些配置,比如log是否开启啊之类

这个 btif的 init完成了到目前位置,上层的 initNative的任务已经完成。也就是蓝牙接口中的一些基本模块已经初始化完成,基本上都是一些工具模块和配置模块,也包括把 controller和 host之间的接口 hci给铺好。要依赖的工具和配置都准备好了,小角色都已经暖好场了,大明星们该压轴登场了,接下来 enable的过程就是协议栈的核心角色的初始化了看到这里就有一个疑问了,为什么 initNative是在 onCreate方法中执行,而 classInitNative是在静态代码段中和库加载一起执行?为什么两个不能都放在静态代码块中执行?个人观点是 jni层加载 so包需要一定的时间,需要放在静态代码块中。而 initNative是调用具体的接口方法,而且还需要使用 java层的 callback对象,所以放在 AdapterService的 onCreate中执行 init完成之后,就可以看 enable的过程了

协议栈enable

还记得上一篇文章 蓝牙,信息获取和enable状态切换吗? enable的方法调用是在状态切换过程中发生的,具体可以参考文章描写 enable的第三大部分, enable过程中的状态切换此文不再赘述,上层调用 jni层的 enableNative方法开启 jni层也是直接调用 bluetoothInterface的 enable方法,而 btif只是一个接口而已,方法实现还要去看协议栈
 1//system/bt/btif/src/stack_manager.cc
2//该方法为同步方法
3static void event_start_up_stack(UNUSED_ATTR void* context) {
4 ...
5  module_start_up(get_module(BTIF_CONFIG_MODULE));
6 ...
7  bte_main_enable();
8 ...
9  btif_thread_post(event_signal_stack_up, NULL);
10}
从这儿开始,可以很明显的知道,协议栈的 enable过程就三件事儿
  1. 执行bt_config_module的start_up方法,但目前源码中该方法是空实现,所以不予考虑

  2. enable蓝牙系统

  3. 通知jni层,蓝牙状态发生了变化,新状态为BT_STATE_ON

主要是 enable蓝牙系统啊朋友们,感觉代码分析马上要进入核心了,有些小激动啊不看代码还在等啥捏
1//system/bt/main/bte_main.cc
2void bte_main_enable() {
3  module_start_up(get_module(BTSNOOP_MODULE));
4  module_start_up(get_module(HCI_MODULE));
5  BTU_StartUp();
6}
这个就是该方法的全部代码,用于创建所有bte的任务
三件事儿
  1. BTSNOOP_MODULE,调用btsnoop_module的start_up方法,会打开一个文件用于存储controller和host交互的log.平常所查询的hci日志说的就是这个了,默认存放路径为/data/misc/bluetooth/logs/btsnoop_hci.log

  2. HCI_MODULE,调用hci的start_up方法,hci准备好,监控host和controller之间的交互。同时,会在这儿开启controller

  3. btu开启,bluetooth upper layer开启,蓝牙上层协议栈开启

BTU_StartUp又是一个有很多事儿要做的方法,该方法用于初始化 btu控制块儿。该方法中有一些对线程的控制代码,但是根本功能是会调用 btu_task_start_up方法,继续对bt进行操作,来看看具体实现
 1//system/bt/stack/btu/btu_task.cc
2void btu_task_start_up(UNUSED_ATTR void* context) {
3 /* Initialize the mandatory core stack control blocks 4     (BTU, BTM, L2CAP, and SDP) 5   * 初始化一些必备的核心协议栈控制块儿 6   */
7  btu_init_core();
8
9  /* Initialize any optional stack components10  * 初始化一些可选的组件11  */
12  BTE_InitStack();
13
14  bta_sys_init();
15
16  /* Initialise platform trace levels at this point as BTE_InitStack() and17   * bta_sys_init()18   * reset the control blocks and preset the trace level with19   * XXX_INITIAL_TRACE_LEVEL20   * 初始化bte的log模块21   */
22  module_init(get_module(BTE_LOGMSG_MODULE));
23
24  message_loop_thread_ = thread_new("btu message loop");
25  if (!message_loop_thread_) {
26    LOG(FATAL) <" unable to create btu message loop thread.";
27  }
28
29  thread_set_rt_priority(message_loop_thread_, THREAD_RT_PRIORITY);
30  thread_post(message_loop_thread_, btu_message_loop_run, nullptr);
31}
蓝牙芯片厂商在做蓝牙芯片时,必须要遵循 SIG给出的蓝牙规范就像是现在大家公认的 tcp/ip模型是统一的蓝牙协议栈有些协议是必须支持的,也就是 mandatory强制要求必备的通过 btu_init_core来初始化这些核心协议有些协议是可选的 BTE_InitStack来初始化
 1//system/bt/stack/btu/btu_init.cc
2void btu_init_core(void) {
3  /* Initialize the mandatory core stack components */
4  btm_init();//bluetoothManager初始化
5
6  l2c_init();//l2cap初始化
7
8  sdp_init();//sdp服务发现协议初始化
9
10  gatt_init();//gatt初始化
11
12  SMP_Init();//SecurityManager初始化
13
14  btm_ble_init();//bluetoothManager ble初始化
15}
好熟悉,初始化 l2cap,sdp,gatt,smp,ble同样的,可以看到 BTE_InitStack方法中会初始化 rfcomm,bnep,pan,a2dp,avrc,gap,hid_host,mca(multi-channels application)代码就不再贴出了具体各个协议赋值什么的,目前也不清楚有什么用,需要继续来分析蓝牙的配对,扫描,连接,通信等等功能,才能明白这些初始化的东西有什么用蓝牙开启的流程算是分析完了
总结一下,蓝牙开启中会完成两大任务
  1. init,把基础设施搭起来,

  2. enable,基础设施搭起来之后,要把核心架构都准备好,之后就可以顺利工作了

蓝牙有三大部分,host--hci--controller,蓝牙开启的过程,也是这三部分使能的过程

听说,多多分享转发这只锦鲤,好运会上门~

原创声明

本文为作者原创文章,未经本人同意,禁止转载和挪作他用

往期 精彩回顾

我为什么要坚持写笔记?

码农常犯的4个问题,你中招了吗?Android鼠标源码研究(三)---获取输入事件数据结构探究系(七)--二叉树实现

数据结构(八)--平衡二叉树

062390b4b31521b1d1d9ed603a63fa14.png

56415c1b2a84ed93bb69593379715505.gif戳嗨,你还在看吗?
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值