3. Treble架构与HIDL:Treble引入的背景、HIDL接口定义语言基础、服务端与客户端架构
3.1 Treble架构引入的背景与动机
在Android 8.0(Oreo)之前,Android系统的升级面临一个核心痛点:碎片化。OEM厂商(如高通、联发科)将硬件驱动和HAL实现代码深度耦合在Android框架中,导致每次Android大版本升级,OEM都需要花费大量时间适配和验证,用户往往无法获得及时的版本更新。
Treble架构的引入,核心目标是解耦:将Vendor实现(硬件相关)与Android Framework(系统框架)通过一个稳定的接口层隔离开来。这个接口层就是HIDL(HAL Interface Definition Language)。
- 旧架构(Pre-Treble): Framework直接链接到Vendor的.so库,接口不稳定,升级需同步更新所有Vendor库。
- 新架构(Treble): Framework通过HIDL接口与Vendor HAL通信,接口稳定(冻结),Framework可独立升级。
3.2 HIDL接口定义语言基础
HIDL是一种用于定义HAL接口的IDL(Interface Definition Language)。它允许Framework和Vendor进程通过进程间通信(IPC)进行交互,而不是直接链接库。HIDL接口是稳定的,一旦发布,接口签名不可更改,这保证了Framework和Vendor实现的独立演进。
3.2.1 HIDL文件结构
一个典型的HIDL接口文件(.hal)包含包名、版本号、接口定义和方法声明。以下是一个Camera HAL3相关的HIDL接口示例:
// android.hardware.camera.device@3.2 包名和版本
package android.hardware.camera.device@3.2;
// 导入其他HIDL类型
import android.hardware.camera.common@1.0::Status;
import android.hardware.camera.common@1.0::CameraMetadata;
interface ICameraDevice {
// 打开相机设备
open(ICameraDeviceCallback callback) generates (Status status);
// 配置输出流
configureStreams(StreamConfiguration config) generates (Status status);
// 提交捕获请求
processCaptureRequest(CaptureRequest request) generates (Status status);
// 关闭相机设备
close() generates (Status status);
};
- package:定义包名和版本号,格式为
package <name>@<version>; - interface:定义接口,包含一组方法。
- 方法签名:
methodName(输入参数) generates (输出参数); - 单向调用:使用
oneway关键字,不等待返回。
3.2.2 HIDL数据类型
| HIDL类型 | 对应C++类型 | 说明 |
|---|---|---|
int32_t |
int32_t |
32位有符号整数 |
uint64_t |
uint64_t |
64位无符号整数 |
float |
float |
单精度浮点数 |
string |
std::string |
UTF-8字符串 |
vec<T> |
std::vector<T> |
可变长度数组 |
struct |
struct |
自定义结构体 |
enum |
enum class |
枚举类型 |
handle |
native_handle_t* |
原生句柄(如文件描述符) |
3.3 服务端与客户端架构
HIDL采用典型的客户端-服务端(Client-Server)架构。服务端(通常运行在Vendor分区)实现HIDL接口,客户端(通常运行在System分区)通过Binder IPC调用服务端的方法。
3.3.1 架构组件
- 服务端(Server):实现HIDL接口的具体逻辑,例如Camera HAL的实现。服务端通过
registerAsService()注册到hwservicemanager。 - 客户端(Client):通过服务名从hwservicemanager获取服务代理,然后调用接口方法。例如Camera Framework Service。
- hwservicemanager:HIDL服务注册中心,负责管理所有已注册的HIDL服务。
- Binder IPC:底层通信机制,负责序列化/反序列化数据并传递调用。
3.3.2 服务端实现示例(C++)
服务端需要继承HIDL生成的接口桩类(Bn类),并实现所有方法:
// CameraDevice.hal 生成的接口桩
class CameraDeviceImpl : public ICameraDevice {
public:
// 实现 open 方法
Return<Status> open(const sp<ICameraDeviceCallback>& callback) override {
// 打开硬件设备
int fd = open("/dev/video0", O_RDWR);
if (fd < 0) {
return Status::INTERNAL_ERROR;
}
// 保存回调
mCallback = callback;
return Status::OK;
}
// 实现 processCaptureRequest 方法
Return<Status> processCaptureRequest(const CaptureRequest& request) override {
// 处理捕获请求
// ...
return Status::OK;
}
// 注册服务
static void registerService() {
sp<ICameraDevice> service = new CameraDeviceImpl();
// 注册到 hwservicemanager
service->registerAsService("default");
}
};
3.3.3 客户端调用示例(C++)
客户端通过服务名获取服务代理,然后调用方法:
// 获取 CameraDevice 服务
sp<ICameraDevice> cameraDevice;
cameraDevice = ICameraDevice::getService("default");
if (cameraDevice == nullptr) {
// 服务不可用
return;
}
// 创建回调
sp<CameraDeviceCallback> callback = new CameraDeviceCallback();
// 调用 open 方法
Status status;
Return<Status> ret = cameraDevice->open(callback);
if (ret.isOk()) {
status = ret;
if (status == Status::OK) {
// 成功打开相机
}
}
- HIDL接口一旦发布(如
@3.2),其方法签名和类型定义不可修改。如需变更,必须创建新的版本(如@3.3)。 - 客户端和服务端必须使用完全相同的HIDL接口定义,否则IPC会失败。
- 在Camera HAL3中,HIDL接口定义了从Framework到HAL的完整调用路径,包括流配置、请求提交、结果回调等。
3.4 Treble架构对Camera HAL3的影响
Treble架构使得Camera HAL3的实现可以独立于Android Framework升级。OEM厂商只需确保其Vendor分区中的HAL实现符合HIDL接口规范,Framework就可以通过HIDL IPC与之通信。这大大降低了Camera HAL的适配成本,也使得Google能够通过Project Treble快速推送安全补丁和系统更新。
| 特性 | Pre-Treble | Treble |
|---|---|---|
| 接口定义 | 隐式(头文件 + .so) | 显式(.hal文件) |
| 通信方式 | 直接函数调用(同进程) | Binder IPC(跨进程) |
| 接口稳定性 | 不稳定,随Framework变化 | 稳定,版本冻结 |
| 升级影响 | Framework升级需同步更新HAL | Framework可独立升级 |
| 调试难度 | 较低(同进程) | 较高(跨进程,需考虑IPC开销) |
- Treble通过HIDL实现了Framework与Vendor的解耦。
- HIDL接口是版本化和冻结的,保证了长期兼容性。
- 客户端-服务端架构通过hwservicemanager和Binder IPC实现。
- Camera HAL3作为Vendor实现,必须遵循HIDL接口规范,才能与Framework正常通信。