1. AbstractionLayer 介绍
我们在阅读 native 和 java 层 蓝牙服务代码时,会发现很多 AbstractionLayer.xxxxx 的字段。 这些字段 虽然很容易理解是干什么的。 但是 大家有没有考虑过, 为啥要专门定义一个类来存放他们。 这样设计的意义是什么?
1.字段解释
- packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AbstractionLayer.java
c
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; // bytes
public 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 层交互中非常常见)。