蓝牙地址的name为null_蓝牙, enable协议栈流程
藍(lán)牙,從系統(tǒng)開(kāi)機(jī)說(shuō)起
藍(lán)牙,信息獲取和enable狀態(tài)切換
在AdapterService創(chuàng)建時(shí)靜態(tài)加載jni的庫(kù)1//AdapterApp.java
2?System.loadLibrary("bluetooth_jni");
靜態(tài)初始化native1//AdapterService.java
2?classInitNative();
接下來(lái)在服務(wù)的生命周期方法onCreate,創(chuàng)建時(shí)又再次初始化native,但是調(diào)用的方法不一樣1//AdapterService.java
2initNative();
打住,到此為止先分析一下,已經(jīng)做了三件事兒
加載jni庫(kù)libbluetooth_jni
初始化操作classInitNative
初始化操作initNative
方法實(shí)現(xiàn)都在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}
這個(gè)方法關(guān)注兩件事兒首先是把java層的方法映射過(guò)來(lái),供jni層調(diào)用。映射過(guò)來(lái)的方法都是JniCallbacks.java中的方法,用來(lái)在hal層有消息回調(diào)時(shí)觸發(fā)給上層另一個(gè)操作就是去加載協(xié)議棧的so包,并獲取到變量名為bluetoothInterface的地址以后jni層再往下的調(diào)用就要依靠這個(gè)bluetoothInterface了加載的是哪個(gè)so包?拿到的so包的誰(shuí)的地址?繼續(xù)分析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命令查看屬性值)字段所聲明的一個(gè)地址下的so包拿到是blutoothInterface的地址完事兒了,拿到之后把地址交給sBluetoothInterface,之后jni就可以通過(guò)該字段來(lái)訪問(wèn)藍(lán)牙所提供的接口了也即是說(shuō),classInitNative的作用有兩個(gè)
映射java層方法
獲取協(xié)議棧的藍(lán)牙接口對(duì)象地址
都在bluetooth.cc文件中列出來(lái)了bluetoothInterface接口方法如上,就不一一分析了
另一個(gè)initNative
在獲取到對(duì)象之后,需要對(duì)這個(gè)對(duì)象進(jìn)行初始化,配置一些基本信息。先看一下代碼 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調(diào)用藍(lán)牙接口的初始化
set_os_callouts這個(gè)主要是對(duì)wakelock喚醒鎖的管理,目前以功能分析為主,暫時(shí)不分析代碼設(shè)計(jì)
獲取到socket的profile對(duì)象,有何用?繼續(xù)分析
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}
越往下分析你會(huì)發(fā)現(xiàn)代碼越簡(jiǎn)單,java層要考慮各種功能和交互而hal層代碼只需要認(rèn)真的把功能實(shí)現(xiàn)就好了,順便再把狀態(tài)回調(diào)給上層就ok了所以init中也很簡(jiǎn)單,首先是把jni層的callback對(duì)象拿過(guò)來(lái),方便后續(xù)進(jìn)行回調(diào)之后,看函數(shù)名字應(yīng)該就是初始化stack了,也就是藍(lán)牙核心模塊要初始化了最后是初始化log相關(guān)的了(初始化btsnoop)。重點(diǎn)關(guān)注stack的初始化,分析一下對(duì)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}
協(xié)議棧的初始化好像東西有點(diǎn)兒多啊,還有三個(gè)排比句get_module方法其實(shí)就是dlsym(RTLD_DEFAULT, name),會(huì)在當(dāng)前進(jìn)程中按照默認(rèn)lib包的搜索順序來(lái)搜索name這個(gè)symbol?module_init方法就是對(duì)所傳入的module調(diào)用init方法
開(kāi)啟核心模塊的管理,這個(gè)方法目前是空實(shí)現(xiàn)
OSI_MODULE,初始化osi模塊:搜索到的symbol是osi_module.cc文件中的osi_module,也就是要調(diào)用osi_module的init方法。暫時(shí)不清楚用處,后續(xù)研究
BT_UTILS_MODULE,初始化bt_utils模塊:搜索到的symbol是bt_utils.cc文件中的bt_utils_module,這個(gè)init方法大致看了下,確認(rèn)過(guò)眼神,是我不懂的操作。一些賦值操作,看名字和任務(wù)棧有關(guān),后續(xù)如果分析到再看吧
BTIF_CONFIG_MODULE,初始話藍(lán)牙配置模塊:搜索到的symbol是btif_config.cc文件中的btif_config_module,init的目的就是去管理前文說(shuō)到的bt_config相關(guān)的文件,比如恢復(fù)出廠后需要?jiǎng)h除文件重新創(chuàng)建啊,以及文件里邊兒現(xiàn)在要寫什么啊等等。總之就是管理藍(lán)牙配置文件的一個(gè)模塊
初始化藍(lán)牙,從這兒開(kāi)始就會(huì)把整個(gè)藍(lán)牙協(xié)議棧創(chuàng)建起來(lái),為藍(lán)牙的開(kāi)啟做準(zhǔn)備工作
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方法會(huì)創(chuàng)建藍(lán)牙接口任務(wù)棧,并且為藍(lán)牙的開(kāi)啟做準(zhǔn)備。主要是調(diào)用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方法用于初始化藍(lán)牙芯片和協(xié)議棧
初始化的話主要是三個(gè)方面
INTEROP_MODULE初始化interop_module模塊,init為空實(shí)現(xiàn),不需要考慮
hci,獲取到hci層接口,方法實(shí)現(xiàn)位于/system/bt/hci/src/hci_layer.cc文件中
STACK_CONFIG_MODULE初始化,會(huì)操作/etc/bluetooth/bt_stack.conf文件,文件中是對(duì)協(xié)議棧的一些配置,比如log是否開(kāi)啟啊之類
協(xié)議棧enable
還記得上一篇文章藍(lán)牙,信息獲取和enable狀態(tài)切換嗎?enable的方法調(diào)用是在狀態(tài)切換過(guò)程中發(fā)生的,具體可以參考文章描寫enable的第三大部分,enable過(guò)程中的狀態(tài)切換此文不再贅述,上層調(diào)用jni層的enableNative方法開(kāi)啟jni層也是直接調(diào)用bluetoothInterface的enable方法,而btif只是一個(gè)接口而已,方法實(shí)現(xiàn)還要去看協(xié)議棧 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}
從這兒開(kāi)始,可以很明顯的知道,協(xié)議棧的enable過(guò)程就三件事兒
執(zhí)行bt_config_module的start_up方法,但目前源碼中該方法是空實(shí)現(xiàn),所以不予考慮
enable藍(lán)牙系統(tǒng)
通知jni層,藍(lán)牙狀態(tài)發(fā)生了變化,新?tīng)顟B(tài)為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}
這個(gè)就是該方法的全部代碼,用于創(chuàng)建所有bte的任務(wù)
三件事兒
BTSNOOP_MODULE,調(diào)用btsnoop_module的start_up方法,會(huì)打開(kāi)一個(gè)文件用于存儲(chǔ)controller和host交互的log.平常所查詢的hci日志說(shuō)的就是這個(gè)了,默認(rèn)存放路徑為/data/misc/bluetooth/logs/btsnoop_hci.log
HCI_MODULE,調(diào)用hci的start_up方法,hci準(zhǔn)備好,監(jiān)控host和controller之間的交互。同時(shí),會(huì)在這兒開(kāi)啟controller
btu開(kāi)啟,bluetooth upper layer開(kāi)啟,藍(lán)牙上層協(xié)議棧開(kāi)啟
2void?btu_task_start_up(UNUSED_ATTR?void*?context)?{
3?/*?Initialize?the?mandatory?core?stack?control?blocks 4?????(BTU,?BTM,?L2CAP,?and?SDP) 5???*?初始化一些必備的核心協(xié)議棧控制塊兒 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}
藍(lán)牙芯片廠商在做藍(lán)牙芯片時(shí),必須要遵循SIG給出的藍(lán)牙規(guī)范就像是現(xiàn)在大家公認(rèn)的tcp/ip模型是統(tǒng)一的藍(lán)牙協(xié)議棧有些協(xié)議是必須支持的,也就是mandatory強(qiáng)制要求必備的通過(guò)btu_init_core來(lái)初始化這些核心協(xié)議有些協(xié)議是可選的BTE_InitStack來(lái)初始化 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服務(wù)發(fā)現(xiàn)協(xié)議初始化
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方法中會(huì)初始化rfcomm,bnep,pan,a2dp,avrc,gap,hid_host,mca(multi-channels application)代碼就不再貼出了具體各個(gè)協(xié)議賦值什么的,目前也不清楚有什么用,需要繼續(xù)來(lái)分析藍(lán)牙的配對(duì),掃描,連接,通信等等功能,才能明白這些初始化的東西有什么用藍(lán)牙開(kāi)啟的流程算是分析完了
總結(jié)一下,藍(lán)牙開(kāi)啟中會(huì)完成兩大任務(wù)
init,把基礎(chǔ)設(shè)施搭起來(lái),
enable,基礎(chǔ)設(shè)施搭起來(lái)之后,要把核心架構(gòu)都準(zhǔn)備好,之后就可以順利工作了
藍(lán)牙有三大部分,host--hci--controller,藍(lán)牙開(kāi)啟的過(guò)程,也是這三部分使能的過(guò)程
聽(tīng)說(shuō),多多分享轉(zhuǎn)發(fā)這只錦鯉,好運(yùn)會(huì)上門~
原創(chuàng)聲明
本文為作者原創(chuàng)文章,未經(jīng)本人同意,禁止轉(zhuǎn)載和挪作他用
往期精彩回顧我為什么要堅(jiān)持寫筆記?
碼農(nóng)常犯的4個(gè)問(wèn)題,你中招了嗎?Android鼠標(biāo)源碼研究(三)---獲取輸入事件數(shù)據(jù)結(jié)構(gòu)探究系(七)--二叉樹(shù)實(shí)現(xiàn)
數(shù)據(jù)結(jié)構(gòu)(八)--平衡二叉樹(shù)
戳嗨,你還在看嗎?總結(jié)
以上是生活随笔為你收集整理的蓝牙地址的name为null_蓝牙, enable协议栈流程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: gamma函数stiriling公式_S
- 下一篇: 关键词热度分析工具_干货分享丨关键词热度