1. AbstractionLayer 介紹
我們在閱讀 native 和 java 層 藍牙服務代碼時,會發現很多 AbstractionLayer.xxxxx 的字段。 這些字段 雖然很容易理解是干什么的。 但是 大家有沒有考慮過, 為啥要專門定義一個類來存放他們。 這樣設計的意義是什么?
1.字段解釋
- packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AbstractionLayer.java
package com.android.bluetooth.btservice;/** @hide*/public final class AbstractionLayer {// Do not modify without upating the HAL files.// TODO: Some of the constants are repeated from BluetoothAdapter.java.// Get rid of them and maintain just one.static final int BT_STATE_OFF = 0x00;static final int BT_STATE_ON = 0x01;static final int BT_SCAN_MODE_NONE = 0x00;static final int BT_SCAN_MODE_CONNECTABLE = 0x01;static final int BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE = 0x02;static final int BT_PROPERTY_BDNAME = 0x01;static final int BT_PROPERTY_BDADDR = 0x02;static final int BT_PROPERTY_UUIDS = 0x03;static final int BT_PROPERTY_CLASS_OF_DEVICE = 0x04;static final int BT_PROPERTY_TYPE_OF_DEVICE = 0x05;static final int BT_PROPERTY_SERVICE_RECORD = 0x06;static final int BT_PROPERTY_ADAPTER_SCAN_MODE = 0x07;static final int BT_PROPERTY_ADAPTER_BONDED_DEVICES = 0x08;static final int BT_PROPERTY_ADAPTER_DISCOVERABLE_TIMEOUT = 0x09;static final int BT_PROPERTY_REMOTE_FRIENDLY_NAME = 0x0A;static final int BT_PROPERTY_REMOTE_RSSI = 0x0B;static final int BT_PROPERTY_REMOTE_VERSION_INFO = 0x0C;static final int BT_PROPERTY_LOCAL_LE_FEATURES = 0x0D;static final int BT_PROPERTY_DYNAMIC_AUDIO_BUFFER = 0x10;static final int BT_PROPERTY_REMOTE_IS_COORDINATED_SET_MEMBER = 0x11;public static final int BT_DEVICE_TYPE_BREDR = 0x01;public static final int BT_DEVICE_TYPE_BLE = 0x02;public static final int BT_DEVICE_TYPE_DUAL = 0x03;static final int BT_PROPERTY_LOCAL_IO_CAPS = 0x0e;static final int BT_PROPERTY_LOCAL_IO_CAPS_BLE = 0x0f;static final int BT_BOND_STATE_NONE = 0x00;static final int BT_BOND_STATE_BONDING = 0x01;static final int BT_BOND_STATE_BONDED = 0x02;static final int BT_SSP_VARIANT_PASSKEY_CONFIRMATION = 0x00;static final int BT_SSP_VARIANT_PASSKEY_ENTRY = 0x01;static final int BT_SSP_VARIANT_CONSENT = 0x02;static final int BT_SSP_VARIANT_PASSKEY_NOTIFICATION = 0x03;static final int BT_DISCOVERY_STOPPED = 0x00;static final int BT_DISCOVERY_STARTED = 0x01;static final int BT_ACL_STATE_CONNECTED = 0x00;static final int BT_ACL_STATE_DISCONNECTED = 0x01;static final int BT_UUID_SIZE = 16; // bytespublic static final int BT_STATUS_SUCCESS = 0;public static final int BT_STATUS_FAIL = 1;public static final int BT_STATUS_NOT_READY = 2;public static final int BT_STATUS_NOMEM = 3;public static final int BT_STATUS_BUSY = 4;public static final int BT_STATUS_DONE = 5;public static final int BT_STATUS_UNSUPPORTED = 6;public static final int BT_STATUS_PARM_INVALID = 7;public static final int BT_STATUS_UNHANDLED = 8;public static final int BT_STATUS_AUTH_FAILURE = 9;public static final int BT_STATUS_RMT_DEV_DOWN = 10;public static final int BT_STATUS_AUTH_REJECTED = 11;public static final int BT_STATUS_AUTH_TIMEOUT = 12;
}
這段代碼 用于定義藍牙 HAL 與上層服務之間的通用常量(狀態、屬性、錯誤碼等)。這些常量的設計目的是提供一個統一的“抽象層接口”,便于 Bluetooth HAL(C/C++ 層)與 Java 層進行交互時傳遞標準化信息。
下面用表格的方式對這些常量的用途和適用場景進行整理說明:
類別 | 常量名 | 數值 | 含義/用途說明 | 使用場景示例 |
---|---|---|---|---|
藍牙狀態 | BT_STATE_OFF | 0x00 | 藍牙關閉狀態 | 通知 Java 層當前藍牙關閉 |
BT_STATE_ON | 0x01 | 藍牙開啟狀態 | 通知 Java 層當前藍牙開啟 | |
掃描模式 | BT_SCAN_MODE_NONE | 0x00 | 不可連接也不可被發現 | 設置藍牙掃描策略時 |
BT_SCAN_MODE_CONNECTABLE | 0x01 | 可被連接但不可被發現 | 廣播連接狀態變化 | |
BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE | 0x02 | 可被連接也可被發現 | 配對時開啟可發現 | |
屬性類型 | BT_PROPERTY_BDNAME | 0x01 | 本地設備名稱 | 設置/獲取本地藍牙名稱 |
BT_PROPERTY_BDADDR | 0x02 | 本地設備地址 | 獲取本地地址 | |
BT_PROPERTY_UUIDS | 0x03 | 支持的服務 UUID 列表 | SDP 結果上報 | |
BT_PROPERTY_CLASS_OF_DEVICE | 0x04 | 設備類型編碼 | 配對時判斷設備類別 | |
BT_PROPERTY_TYPE_OF_DEVICE | 0x05 | 藍牙設備類型(BR/EDR、BLE、Dual) | 設置設備屬性時 | |
BT_PROPERTY_SERVICE_RECORD | 0x06 | 遠端設備服務記錄(SDP) | 服務搜索時返回 | |
BT_PROPERTY_ADAPTER_SCAN_MODE | 0x07 | 當前掃描模式 | 獲取當前適配器屬性 | |
BT_PROPERTY_ADAPTER_BONDED_DEVICES | 0x08 | 獲取已配對設備列表 | 啟動時獲取已配對設備 | |
BT_PROPERTY_ADAPTER_DISCOVERABLE_TIMEOUT | 0x09 | 可被發現模式的超時時長 | 設置發現超時 | |
BT_PROPERTY_REMOTE_FRIENDLY_NAME | 0x0A | 遠程設備名稱 | 獲取遠端名稱 | |
BT_PROPERTY_REMOTE_RSSI | 0x0B | 遠程設備信號強度 | BLE 掃描中上報 | |
BT_PROPERTY_REMOTE_VERSION_INFO | 0x0C | 協議版本號(HCI/LMP) | 配對成功后回調 | |
BT_PROPERTY_LOCAL_LE_FEATURES | 0x0D | 本地 LE 特性 | 初始化時上報 | |
BT_PROPERTY_DYNAMIC_AUDIO_BUFFER | 0x10 | 音頻緩沖設置 | Audio streaming 配置 | |
BT_PROPERTY_REMOTE_IS_COORDINATED_SET_MEMBER | 0x11 | 是否為協調播放組成員(如多設備音頻) | LE Audio 使用 | |
設備類型 | BT_DEVICE_TYPE_BREDR | 0x01 | 傳統藍牙設備 | 設置設備屬性 |
BT_DEVICE_TYPE_BLE | 0x02 | 低功耗藍牙設備 | BLE 配對等場景 | |
BT_DEVICE_TYPE_DUAL | 0x03 | 同時支持 BR/EDR 與 BLE 的雙模設備 | 常見手機 | |
本地 I/O 能力 | BT_PROPERTY_LOCAL_IO_CAPS | 0x0e | 本地 IO 能力(配對時使用) | SSP 配對時 |
BT_PROPERTY_LOCAL_IO_CAPS_BLE | 0x0f | 本地 BLE IO 能力 | BLE 設備配對時 | |
配對狀態 | BT_BOND_STATE_NONE | 0x00 | 未配對 | 配對流程中狀態變化 |
BT_BOND_STATE_BONDING | 0x01 | 正在配對 | 顯示進度 | |
BT_BOND_STATE_BONDED | 0x02 | 配對完成 | 保存設備記錄 | |
SSP 配對類型 | BT_SSP_VARIANT_PASSKEY_CONFIRMATION | 0x00 | 確認配對碼 | 人機交互確認界面 |
BT_SSP_VARIANT_PASSKEY_ENTRY | 0x01 | 輸入配對碼 | 輸入框場景 | |
BT_SSP_VARIANT_CONSENT | 0x02 | 用戶授權同意 | 彈窗授權 | |
BT_SSP_VARIANT_PASSKEY_NOTIFICATION | 0x03 | 顯示配對碼 | 顯示數字碼 | |
發現流程狀態 | BT_DISCOVERY_STOPPED | 0x00 | 發現已停止 | 搜索過程 |
BT_DISCOVERY_STARTED | 0x01 | 發現已開始 | 搜索開始時廣播 | |
ACL 鏈接狀態 | BT_ACL_STATE_CONNECTED | 0x00 | ACL 已連接 | ACL 連接建立后通知 |
BT_ACL_STATE_DISCONNECTED | 0x01 | ACL 已斷開 | ACL 斷開后通知 | |
UUID 尺寸 | BT_UUID_SIZE | 16 | UUID 長度為 16 字節(128 bit) | UUID 檢查或轉換時使用 |
狀態碼(返回值) | BT_STATUS_SUCCESS | 0 | 操作成功 | HAL 接口返回 |
BT_STATUS_FAIL | 1 | 操作失敗 | 錯誤處理 | |
BT_STATUS_NOT_READY | 2 | 適配器未準備好 | 藍牙未初始化時返回 | |
BT_STATUS_NOMEM | 3 | 內存不足 | 動態分配失敗 | |
BT_STATUS_BUSY | 4 | 當前操作繁忙 | 多任務沖突時 | |
BT_STATUS_DONE | 5 | 操作已完成 | 異步操作結束 | |
BT_STATUS_UNSUPPORTED | 6 | 不支持的功能 | 某些設備不支持特性 | |
BT_STATUS_PARM_INVALID | 7 | 參數無效 | 參數檢查失敗 | |
BT_STATUS_UNHANDLED | 8 | 沒有處理該情況 | 框架遺漏處理邏輯 | |
BT_STATUS_AUTH_FAILURE | 9 | 認證失敗 | 配對失敗 | |
BT_STATUS_RMT_DEV_DOWN | 10 | 遠程設備斷開 | 狀態同步失敗 | |
BT_STATUS_AUTH_REJECTED | 11 | 認證被拒絕 | 用戶取消 | |
BT_STATUS_AUTH_TIMEOUT | 12 | 認證超時 | 藍牙連接不響應 |
-
當 HAL 層通過 JNI 通知 Java 藍牙服務狀態時,會使用這些常量進行信息編碼。
-
例如:
-
bt_property_type
用于表示 Bluetooth HAL 上報的屬性類型; -
BT_DISCOVERY_STARTED
會在onDiscoveryStateChanged()
中通過廣播發送; -
BT_STATUS_SUCCESS
是很多 native 回調函數中的返回碼,表示調用成功。
-
2. 設計的意義
這個 AbstractionLayer
類的設計在 AOSP 藍牙服務中提供了一個“抽象層常量集中地”,它本身不包含行為邏輯,而是定義了一批與藍牙 HAL(Hardware Abstraction Layer)通信的核心常量。這樣的設計有以下幾個 重要好處:
1. 設計好處匯總表
設計目的/優勢 | 說明 |
---|---|
統一管理常量,避免魔法數字 | 所有關鍵狀態、屬性、錯誤碼、設備類型等都使用命名常量,避免代碼中出現“0x03”、“0x0C”這類不可讀的“魔法數字”。 |
代碼可讀性提升 | 例如 BT_STATUS_AUTH_TIMEOUT 比 12 更清晰表達“認證超時”的語義,使維護者無需查表也能讀懂邏輯。 |
易于維護和擴展 | 如果底層 HAL 接口更新(例如新增屬性),只需在這里添加新常量,其他代碼不需修改多處。 |
確保與 HAL 保持同步 | HAL 和 Java 層可能用 AIDL 或 JNI 通信,必須確保狀態碼一致;集中定義可減少錯漏風險。注釋中也明確寫道:“Do not modify without updating the HAL files”。 |
方便封裝抽象 | 該類名為 AbstractionLayer ,意圖明確:它作為 Bluetooth native 層與 framework 層的橋梁,封裝底層值定義,避免上層代碼直接接觸 native 細節。 |
跨模塊復用性強 | 同一套常量可以在多個模塊中共享,比如 BluetoothAdapter、BluetoothService、JNI 等模塊都能引用這組常量,避免重復定義。 |
支持雙向通信 | 常量可用于 Java → native 下發請求(如 scan mode 設置),也可用于 native → Java 回調(如 discovery started 通知),有助于狀態映射和協議一致性。 |
3. 典型使用場景
這些常量通常用于以下幾個場景:
場景 | 舉例 | 涉及常量 |
---|---|---|
設備屬性設置與讀取 | 讀取本地設備名、地址等 | BT_PROPERTY_BDNAME , BT_PROPERTY_BDADDR |
狀態通知與回調 | 藍牙開關、掃描模式變化通知 | BT_STATE_ON , BT_SCAN_MODE_CONNECTABLE |
配對與綁定流程 | 顯示綁定狀態或配對方式提示 | BT_BOND_STATE_BONDING , BT_SSP_VARIANT_PASSKEY_ENTRY |
錯誤處理與狀態返回 | 藍牙操作失敗時給上層狀態反饋 | BT_STATUS_FAIL , BT_STATUS_AUTH_TIMEOUT |
連接狀態監控 | 連接建立或斷開通知 | BT_ACL_STATE_CONNECTED , BT_ACL_STATE_DISCONNECTED |
設備類型識別 | 判斷是 BLE 還是 BR/EDR 設備 | BT_DEVICE_TYPE_BLE , BT_DEVICE_TYPE_DUAL |
4. 總結:
AbstractionLayer
的設計是面向 HAL 與 Framework 解耦的一種“常量協議集中定義”模式,既提升了可讀性和維護性,也為不同層間通信提供了統一語言,符合 AOSP 架構的一貫風格(尤其在 HAL / JNI 層交互中非常常見)。