聊一聊藍牙名字和地址的來龍去脈

藍牙名字和地址

藍牙設備作爲一種短距離無線連接的載體,由於其體積小、操作方便等優點,在耳機、車載和電腦鍵鼠等應用方面被越來越多的消費者所青睞,漸漸走入大衆視野中。
在這裏插入圖片描述

作爲藍牙設備的使用者,我們的第一想法往往是這個藍牙設備的名字是什麼,這樣才知道去連接哪個藍牙設備,而一個藍牙名字又對應着全球唯一的藍牙地址,這其實才是藍牙設備的關鍵。本篇文章我們就來聊聊藍牙名字和地址的這些事。

  • 藍牙名字:藍牙設備的名稱,代表這個藍牙設備,類似於我們的姓名
  • 藍牙地址:一組由48位(6字節)二進制表示的數據,是藍牙設備的唯一標識。每一個藍牙設備的地址都是不一致的(就好比世上沒有兩片相同的落葉),類似於我們的基因
    在這裏插入圖片描述

所以市面上衆多的藍牙設備儘管名字是有可能相同的,但藍牙地址基本上是不一致的。但也有另外,因爲從上圖可以知道LAP部分雖然有24位二進制來進行分配,但如果這家廠商的設備數量太多,超過了2的24次方(哈哈,概率極小),就會出現藍牙地址重複的現象。

現在我們大概瞭解了藍牙Name和Address的關係,那在安卓源碼中我們一般是如何獲取這兩個值的呢?這就隨我接着往下看。

獲取這兩個值需要分情況來討論,因爲藍牙設備首次開機和重啓開機的獲取流程有差異,所以接下來分別作出分析。

1、首次開機(fastboot刷機完成後首次開機)
這種情況下,應用獲取到藍牙名字和地址一般是從藍牙協議棧bluedroid獲取來的,詳情可以參照如下時序圖來分析:
在這裏插入圖片描述

從上圖可以明顯得知,底層bluedroid上報的藍牙名字和地址最終都會存儲於全局變量Settings的xml文件中:/data/system/users/0/settings_secure.xml,索引名分別爲bluetooth_namebluetooth_address

第三方應用通過藍牙適配器BluetoothAdapter對外提供的接口getName( )和getAddress( )就可以獲取到存儲於BluetoothManagerService中的藍牙名字和地址。

但是這裏還有如下幾個問題需要解決:

問題1:首次開機,上述時序圖中BluetoothManagerService.handleOnBootPhase()的處理中爲什麼是打開藍牙的操作而不是主動去獲取藍牙的Name和Address ?

解答:系統開機會根據關機前的藍牙狀態來決定開機後是否自動打開藍牙。
那重新刷機後的首次開機會根據配置文件的值來決定是否默認打開藍牙。
配置文件路徑:frameworks/base/packages/SettingsProvider/res/values/defaults.xml

該文件中的 name=“def_bluetooth_on” 的值會在刷機後的首次開機創建安卓數據庫時寫入Setting中的settings_global.xml文件中,索引值爲 name=“bluetooth_on”。

執行寫入數據的處理函數爲:frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java中的
loadBooleanSetting(stmt,Settings.Global.BLUETOOTH_ON,R.bool.def_bluetooth_on)。

其他情況下的系統重啓後,根據settings_global.xml文件中存儲的關機前的藍牙狀態來做處理。

因此刷完系統首次開機後,程序會根據配置文件中的默認值來決定是否打開藍牙,如果默認不打開藍牙,則程序也會主動讀取Name和Address,這個操作其實是bind藍牙服務及初始化底層的藍牙模塊,等獲取到這兩個值後再執行unbind藍牙服務的動作。

問題2:藍牙名字的原始定義在哪?

解答:上面時序圖中獲取到的藍牙名字也只是從藍牙協議棧的內存裏獲取到的值,那這個值是從哪兒來的呢?

分析協議棧的代碼,有這幾個地方可以獲取到Name

  • 步驟A:cfg2prop( )->btif_config_get_str()查找/data/misc/bluedroid/bt_config.conf文件中[Adapter]是否包含Name,該文件是協議棧初始化時創建的,保存相關變量
  • 步驟B:如果步驟A沒有獲取到Name,則從btif_dm_get_adapter_property( )函數中通過接口btif_get_default_local_name()中獲取到宏定義的變量BTM_DEF_LOCAL_NAME的值作爲藍牙名字。
    該宏定義的路徑爲:
    device\generic\common\bluetooth\bdroid_buildcfg.h

所以獲取藍牙名字的流程圖大概如下所示:
在這裏插入圖片描述

問題3:藍牙地址從哪兒獲取的?

解答:類似於藍牙名字是從協議棧相關的配置文件中獲取的,藍牙地址則是從藍牙芯片獲取上來的。

btif_storage_get_adapter_property( )中通過controller_get_interface()->get_address()獲取地址值。
而controller.c中的address賦值於:
在這裏插入圖片描述
HCI交互爲:
在這裏插入圖片描述

第三方應用需要獲取藍牙地址的話,該應用除了“LOCAL_MAC_ADDRESS”的權限外,還需具備系統權限,否則獲取到的地址爲默認的錯誤值:“02:00:00:00:00:00”

2、重啓開機
從以上分析可以知道,系統重啓前會將藍牙狀態、名字和地址等參數存儲於Setting的xml文件中,所以系統重啓後,會首先從這些xml文件中讀取參數,進而BluetoothManagerService在初始化時就已經獲取了這些參數值。

現在我們已經分析完成了兩種場景下的藍牙名字和地址的獲取流程,至此安卓系統中的藍牙Name和Adress就會一直存儲於Settings的xml文件中。

使用藍牙設備過程中,藍牙地址一經固件寫入基本上是不可更改的。但藍牙名字卻是可以修改的,第三方應用使用BluetoothAdapter對外提供的接口setName()將新名字寫入藍牙協議棧,存儲於bt_config.conf中,這樣保證後續主動讀取名字時先讀取出更改後的名字。同時協議棧也會將最新的Name上報給服務層,通過廣播通知BluetoothManagerService更改Settings中的Name值。

好了,本篇的藍牙名字和地址的分析就到這裏,感興趣的小夥伴歡迎私信留言一起討論。

更多互聯互通技術,歡迎關注微信公衆號:Connectivity
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章