Android筆記之藍牙enble過程源碼追蹤

前言

在Android開發(fā)異常火熱的如今,各類的Android開發(fā)的文檔也異常豐富,但是很奇怪的是關于android藍牙開發(fā)的文檔確是少之又少,現(xiàn)在android 7都出來好久了,中文社區(qū)藍牙開發(fā)的資料大多都停留在了android 4.3之前,僅有的新鮮的文章也是那幾篇抄來抄去,也沒有相關的書籍作為參考,找點資料也是心累。
所以想要把自己整理的東西慢慢寫下來,除了作為自己知識的沉淀,也希望將能夠分享和交流。

而追蹤藍牙使能過程目的有這么幾個:

  • 增進對藍牙框架的了解
  • 提供了一種Android源碼的閱讀方式
  • 對整個Android的框架和代碼結構有進一步的了解
  • 了解Jni、binder、廣播等機制在其中的運用

Bt框架

BT enable框架

enable的追蹤從settings app開始,一直到最底層的driver,基本按照上圖的框架,把函數(shù)的調(diào)用過程代入圖中有助于理解整個藍牙的架構。

源碼追蹤

以下為Bluetooth的enable從settings app開始往下追蹤的過程,當然僅為調(diào)用過程。

  1. BluetoothEnabler.java(packages\apps\settings\src\com\android\settings\bluetooth)
|onSwitchChanged()
     |mLocalAdapter.setBluetoothEnabled(isChecked);
 

其中BluetoothEnabler實現(xiàn)了SwitchBar.OnSwitchChangeListener監(jiān)聽藍牙開關的狀態(tài)變化;當開關被點擊了,onSwitchChanged被回調(diào)。
查看mLocalAdapter定義:

private final LocalBluetoothAdapter mLocalAdapter;

LocalBluetoothAdapter.java(frameworks\base\packages\settingslib\src\com\android\settingslib\bluetooth)

|setBluetoothEnabled()
     |mAdapter.enable()

查看mAdapter的定義

 private final BluetoothAdapter mAdapter;
  1. BluetoothAdapter.java (frameworks\base\core\java\android\bluetooth)
|enable()
     |mManagerService.enable()

查看mManagerService定義

private final IBluetoothManager mManagerService;

這里是通過AIDL機制完成進程間的通信,調(diào)用的是BluetoothManagerService的enable()函數(shù)。

  1. BluetoothManagerService.java(frameworks\base\services\core\java\com\android\server)
|enable()
     |sendEnableMsg(false);
        |mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE,0, 0));

在他的內(nèi)部類BluetoothHandler繼承了Handler類,處理傳遞的消息:

|handleMessage(Message msg)
     |case MESSAGE_ENABLE   
        |handleEnable(msg.arg1 == 1);
            |mBluetooth.enable()

查看mBluetooth的定義:

private IBluetooth mBluetooth;
  1. AdapterService.java(packages\apps\bluetooth\src\com\android\bluetooth\btservice)
|enable(boolean quietMode)
     |Message m = mAdapterStateMachine.obtainMessage(AdapterState.BLE_TURN_ON);
       |mAdapterStateMachine.sendMessage(m);

查看mAdapterStateMachine的定義:

private AdapterState mAdapterStateMachine;
  1. AdapterState.java(packages\apps\bluetooth\src\com\android\bluetooth\btservice)
|processMessage(Message msg)
     |case BLE_TURN_ON
        |adapterService.processStart();

查看定義:

AdapterService adapterService = mAdapterService;
  1. AdapterService.java (packages\apps\bluetooth\src\com\android\bluetooth\btservice)
|processStart() 
      | mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.STARTED));
  1. AdapterState.java(packages\apps\bluetooth\src\com\android\bluetooth\btservice)
|processMessage(Message msg)
     |case STARTED
        |adapterService.enableNative()
  1. AdapterService.java(packages\apps\bluetooth\src\com\android\bluetooth\btservice)
    其中定義了native函數(shù)enableNative:
 /*package*/ native boolean enableNative();

它加載了動態(tài)鏈接庫libbluetooth_jni.so,也就意味著enableNative函數(shù)的具體實現(xiàn)打包在這個動態(tài)鏈接庫中。
進到目錄packages\apps\bluetooth下,有一個jni的目錄,一般跟bluetooth這個原生應用有關的jni都在這里實現(xiàn);下面有一個Android.mk,查看該文件,其中有打包成庫的名稱

LOCAL_MODULE := libbluetooth_jni

正好是我們要找的動態(tài)鏈接庫,我們要找的函數(shù)就是在這個目錄下了。
mk文件中也提供了編譯的時候包含的源文件:

LOCAL_SRC_FILES:= \
    com_android_bluetooth_btservice_AdapterService.cpp \
    com_android_bluetooth_btservice_QAdapterService.cpp \
    com_android_bluetooth_hfp.cpp \
    com_android_bluetooth_hfpclient.cpp \
    com_android_bluetooth_a2dp.cpp \
    com_android_bluetooth_a2dp_sink.cpp \
    com_android_bluetooth_avrcp.cpp \
    com_android_bluetooth_avrcp_controller.cpp \
    com_android_bluetooth_hid.cpp \
    com_android_bluetooth_hidd.cpp \
    com_android_bluetooth_hdp.cpp \
    com_android_bluetooth_pan.cpp \
    com_android_bluetooth_gatt.cpp \
    android_hardware_wipower.cpp

使用命令抓取一下:

find .|grep "enableNative" -rn .

發(fā)現(xiàn)enable函數(shù)是在com_android_bluetooth_btservice_AdapterService.cpp中實現(xiàn)的。

  1. com_android_bluetooth_btservice_AdapterService.cpp (packages\apps\bluetooth\jni)
|enableNative(JNIEnv* env, jobject obj)
    |sBluetoothInterface->enable()

查看定義

static const bt_interface_t *sBluetoothInterface = NULL;

bt_interface_t是Bluetooth.h (hardware\libhardware\include\hardware)中定義的結構體。
我們需要找到它的實現(xiàn),在文件中查找sBluetoothInterface找到它賦值的地方:

 sBluetoothInterface = btStack->get_bluetooth_interface();

它是由btStack也就是藍牙協(xié)議棧返回的,我們繼續(xù)看btStack的關鍵代碼:

const char *id = (strcmp(value, "1")? BT_STACK_MODULE_ID : BT_STACK_TEST_MODULE_ID);
//這句應該獲得btStack實例
err = hw_get_module(id, (hw_module_t const**)&module);
err = module->methods->open(module, id, &abstraction); 
//最終轉換為btStack結構體
bluetooth_module_t* btStack = (bluetooth_module_t *)abstraction;

找到hw_get_module函數(shù),其中果然有加載btStack模塊:

load(class_id, path, module);
  1. Bluetooth.c (external\bluetooth\bluedroid\btif\src)
    我們知道Bluedroid的代碼在external\bluetooth\bluedroid,因此我們在其中搜索很容易找到sBluetoothInterface的實現(xiàn)代碼。
|static const bt_interface_t bluetoothInterface
      |enable
        |btif_enable_bluetooth()
  1. Btif_core.c (external\bluetooth\bluedroid\btif\src)
|btif_enable_bluetooth(void)
      |bte_main_enable()
  1. Bte_main.c (external\bluetooth\bluedroid\main)
|bte_main_enable()
      |bte_hci_enable() 
         |bt_hc_if->set_power(BT_HC_CHIP_PWR_ON)

查看定義

static bt_hc_interface_t *bt_hc_if=NULL;

以及賦值的語句

bt_hc_if = (bt_hc_interface_t *) bt_hc_get_interface()
  1. Bt_hci_bdroid.c (external\bluetooth\bluedroid\hci\src)
|static const bt_hc_interface_t bluetoothHCLibInterface
      |set_power
        |vendor_send_command(BT_VND_OP_POWER_CTRL, &pwr_state);

hci層發(fā)送了BT_VND_OP_POWER_CTRL的命令。

  1. Vendor.c (external\bluetooth\bluedroid\hci\src)
|vendor_send_command(bt_vendor_opcode_t opcode, void *param)
      |vendor_interface->op(opcode, param)

vendor_interface賦值語句:

VENDOR_LIBRARY_NAME = "libbt-vendor.so";
lib_handle = dlopen(VENDOR_LIBRARY_NAME, RTLD_NOW);
vendor_interface = (bt_vendor_interface_t *)dlsym(lib_handle, VENDOR_LIBRARY_SYMBOL_NAME);

dlsym根據(jù)動態(tài)鏈接庫操作句柄與符號,返回符號對應的地址。
可以得到vendor_interface的實現(xiàn)代碼在libbt-vendor.so這個動態(tài)鏈接庫中。

  1. Bt_vendor_qcom.c (hardware\qcom\bt\libbt-vendor\src)
    全局抓取一下libbt-vendor.so,我們在hardware/qcom/bt/libbt-vendor下的Android.mk中找到了libbt-vendor.so的包含的源文件。
    抓取一下bt_vendor_interface_t,發(fā)現(xiàn)在Bt_vendor_qcom.c找到了它的實現(xiàn):
|const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE
      |op(bt_vendor_opcode_t opcode, void *param)
        |hw_config(nState)
  1. Hardware.c (hardware\qcom\bt\libbt-vendor\src)
|hw_config(int nState)
      |property_set("bluetooth.hciattach", true)

進行芯片framework的config操作。

小結

本文為enable過程的源碼追蹤,總結完了吐了一口老血,但不得不說,android程序員還是厲害啊,基本上一個函數(shù)是干什么的看看函數(shù)名就知道了,以現(xiàn)在的水平還無法對過程進行展開分析,其中也有很多的錯誤,以后慢慢的補充和修改。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,923評論 6 535
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,740評論 3 420
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,856評論 0 380
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,175評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,931評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,321評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,383評論 3 443
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,533評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,082評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,891評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,067評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,618評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,319評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,732評論 0 27
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,987評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,794評論 3 394
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,076評論 2 375

推薦閱讀更多精彩內(nèi)容