安卓系統藍牙服務com.android.bluetooth的使能

藍牙系統服務層的使能流程分析

在這裏插入圖片描述

藍牙服務層的使能基礎是其初始化完成,也就是AdapterService通過onBind()將AdapterServiceBinder上報給bind該服務的調用者。我們現在應該都知道在安卓系統中bind該服務的爲BluetoothManagerService。本篇我們就從藍牙服務管理收到bind的回調開啓藍牙使能流程的分析。

熟悉安卓系統中bind服務機制的小夥伴應該都知道,該bind調用會連同回調函數ServiceConnection一起下發給系統,這樣服務bind成功後通過該回調上報到對應的調用層,在藍牙系統裏就是藍牙服務管理。通過如下轉換藍牙服務管理就獲取到藍牙服務層AdapterService的函數接口:

IBinder service = (IBinder) msg.obj;
mBluetooth = IBluetooth.Stub.asInterface(Binder.allowBlocking(service))

隨着藍牙服務層接口的取得,就會接着執行藍牙使能的操作
在這裏插入圖片描述

服務層使能的具體流程可以參照如下時序圖:
在這裏插入圖片描述

從以上時序圖大概能總結出藍牙服務層使能基本上分爲三個步驟:

  1. 使能低功耗藍牙,也就是GattService
  2. 使能藍牙協議棧
  3. 使能配置文件中支持的各項其他協議的服務

藍牙狀態涉及到如下狀態值及含義:

  • public static final int STATE_OFF = 10,藍牙關閉
  • public static final int STATE_TURNING_ON = 11,藍牙正在打開
  • public static final int STATE_ON = 12,藍牙打開
  • public static final int STATE_TURNING_OFF = 13,藍牙正在關閉
  • public static final int STATE_BLE_TURNING_ON = 14,藍牙BLE正在打開
  • public static final int STATE_BLE_ON = 15,藍牙BLE打開
  • public static final int STATE_BLE_TURNING_OFF = 16,藍牙BLE正在關閉

集合整個藍牙打開基本上先打開低功耗藍牙BLE,再打開傳統藍牙BT,所以藍牙的狀態變化爲:
10 -> 14 -> 15 -> 11 ->12

反之,藍牙關閉的狀態變化爲:
12 -> 13 -> 15 -> 16 -> 10

因此藍牙整個的狀態機就會根據不同場景和消息來及時切換到正確的狀態機下執行相應的處理流程。

藍牙服務層中定時器的設定有兩個,分別對應低功耗BLE使能和傳統藍牙BT使能,超時時間都是4s,所以藍牙底層在使能過程中耗費太長時間會同樣會導致藍牙打開失敗(即使4s超時後底層藍牙使能成功,也算失敗)。
在這裏插入圖片描述

從時序圖上可以看到BluetoothManagerService收到4次藍牙狀態的變化回調,但是一般應用在監聽藍牙狀態變化的廣播時,只能收到兩次廣播,分別爲10 -> 1111 -> 12 這2次藍牙狀態變化的廣播。但這明明和時序圖上的4次狀態回調不一致啊?

其實是BluetoothManagerService自己做了處理,如果第三方應用是監聽如下BLE狀態改變的廣播,則能完全一致的收到這4次廣播。
在這裏插入圖片描述

但如果監聽的是傳統藍牙狀態改變的廣播,則只能收到上述的10 -> 11和11 -> 12這2次廣播。
在這裏插入圖片描述

BluetoothManagerService實例對象中對藍牙狀態廣播的處理邏輯可以參考該方法bluetoothStateChangeHandler(),安卓系統裏藍牙狀態改變的廣播都是在這裏廣播出去的。

經過以上的分析,藍牙服務層的使能我們已經有了一定的瞭解。流程是這麼設計的,但有時還是會遇到些使能相關的莫名其妙的問題,根據過往的工作經驗,我主要總結了如下幾種問題:

  1. 藍牙服務層使能BLE就超時失敗,大概率當前系統有點卡,線程間消息傳遞太費時間,最終觸發4s定時器。
  2. 使能藍牙協議棧遲遲沒有完成的回調上報。由於協議棧是藍牙系統中最複雜的模塊,在使能過程中還會依賴串口的打開與操作,從而使能芯片Controller模塊,串口打開卡死也會導致藍牙打開超時。
  3. 使能傳統BT觸發4s定時器,由於使能傳統BT需要依次初始化協議配置文件中支持的各個協議,所以如果有哪個協議服務的ProfileService.doStart()慢一步,沒有及時告知AdapterService協議服務已初始化完成,也可能導致藍牙打開失敗。

所以藍牙開發過程中遇到類似問題,還需一步步分析流程,確定問題根因發生在哪個環節並給出解決方案。

上述的藍牙服務使能時序圖只是簡單梳理了下大概流程,其中的知識點甚多,比如各個支持的藍牙協議服務的初始化我就一筆帶過了,感興趣的小夥伴不妨自己動起手來,一覽安卓源碼的設計之美,也歡迎私信留言一起討論。

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

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