蓝牙地址的name为null_蓝牙, enable协议栈流程
藍牙,從系統開機說起
藍牙,信息獲取和enable狀態切換
在AdapterService創建時靜態加載jni的庫1//AdapterApp.java
2?System.loadLibrary("bluetooth_jni");
靜態初始化native1//AdapterService.java
2?classInitNative();
接下來在服務的生命周期方法onCreate,創建時又再次初始化native,但是調用的方法不一樣1//AdapterService.java
2initNative();
打住,到此為止先分析一下,已經做了三件事兒
加載jni庫libbluetooth_jni
初始化操作classInitNative
初始化操作initNative
方法實現都在jni層
首先是classInitNative方法
1//com_android_bluetooth_btservice_AdapterService.cpp2static?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文件中列出來了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}
主要就是這三件事兒了
init調用藍牙接口的初始化
set_os_callouts這個主要是對wakelock喚醒鎖的管理,目前以功能分析為主,暫時不分析代碼設計
獲取到socket的profile對象,有何用?繼續分析
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相關的文件,比如恢復出廠后需要刪除文件重新創建啊,以及文件里邊兒現在要寫什么啊等等。總之就是管理藍牙配置文件的一個模塊
初始化藍牙,從這兒開始就會把整個藍牙協議棧創建起來,為藍牙的開啟做準備工作
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.cc2//該方法為同步方法
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
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開啟,藍牙上層協議棧開啟
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鼠標源碼研究(三)---獲取輸入事件數據結構探究系(七)--二叉樹實現
數據結構(八)--平衡二叉樹
戳嗨,你還在看嗎?總結
以上是生活随笔為你收集整理的蓝牙地址的name为null_蓝牙, enable协议栈流程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: gamma函数stiriling公式_S
- 下一篇: 剪绳子python_Python剪绳子如