蓝牙,从系统开机说起
蓝牙,信息获取和enable状态切换
在 AdapterService创建时静态加载 jni的库
1//AdapterApp.java
2 System.loadLibrary("bluetooth_jni");
静态初始化
native
1//AdapterService.java
2 classInitNative();
接下来在服务的生命周期方法
onCreate,创建时又再次初始化
native,但是调用的方法不一样
1//AdapterService.java
2initNative();
打住,到此为止先分析一下,已经做了三件事儿
加载jni库libbluetooth_jni
初始化操作classInitNative
初始化操作initNative
方法实现都在 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的作用有两个
映射java层方法
获取协议栈的蓝牙接口对象地址
都在 bluetooth.cc文件中列出来了
另一个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}
主要就是这三件事儿了
init调用蓝牙接口的初始化
set_os_callouts这个主要是对wakelock唤醒锁的管理,目前以功能分析为主,暂时不分析代码设计
获取到socket的profile对象,有何用?继续分析
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相关的文件,比如恢复出厂后需要删除文件重新创建啊,以及文件里边儿现在要写什么啊等等。总之就是管理蓝牙配置文件的一个模块
初始化蓝牙,从这儿开始就会把整个蓝牙协议栈创建起来,为蓝牙的开启做准备工作
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方法用于初始化蓝牙芯片和协议栈
初始化的话主要是三个方面
INTEROP_MODULE初始化interop_module模块,init为空实现,不需要考虑
hci,获取到hci层接口,方法实现位于/system/bt/hci/src/hci_layer.cc文件中
STACK_CONFIG_MODULE初始化,会操作/etc/bluetooth/bt_stack.conf文件,文件中是对协议栈的一些配置,比如log是否开启啊之类
协议栈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过程就三件事儿
执行bt_config_module的start_up方法,但目前源码中该方法是空实现,所以不予考虑
enable蓝牙系统
通知jni层,蓝牙状态发生了变化,新状态为BT_STATE_ON
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的任务
三件事儿
BTSNOOP_MODULE,调用btsnoop_module的start_up方法,会打开一个文件用于存储controller和host交互的log.平常所查询的hci日志说的就是这个了,默认存放路径为/data/misc/bluetooth/logs/btsnoop_hci.log
HCI_MODULE,调用hci的start_up方法,hci准备好,监控host和controller之间的交互。同时,会在这儿开启controller
btu开启,bluetooth upper layer开启,蓝牙上层协议栈开启
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)代码就不再贴出了具体各个协议赋值什么的,目前也不清楚有什么用,需要继续来分析蓝牙的配对,扫描,连接,通信等等功能,才能明白这些初始化的东西有什么用蓝牙开启的流程算是分析完了
总结一下,蓝牙开启中会完成两大任务
init,把基础设施搭起来,
enable,基础设施搭起来之后,要把核心架构都准备好,之后就可以顺利工作了
蓝牙有三大部分,host--hci--controller,蓝牙开启的过程,也是这三部分使能的过程
听说,多多分享转发这只锦鲤,好运会上门~
原创声明
本文为作者原创文章,未经本人同意,禁止转载和挪作他用
往期 精彩回顾我为什么要坚持写笔记?
码农常犯的4个问题,你中招了吗?Android鼠标源码研究(三)---获取输入事件数据结构探究系(七)--二叉树实现
数据结构(八)--平衡二叉树
![56415c1b2a84ed93bb69593379715505.gif](https://i-blog.csdnimg.cn/blog_migrate/66e7baf4552221ff58da15e281f8fd47.gif)