4. Vendor接口基础
在 Android 系统架构中,Vendor 接口是连接 Framework 层与 Vendor 实现层的关键契约。理解 HAL 接口的分类方式、HIDL 与 AIDL 的差异,以及 Vendor 接口的边界定义,是进行 VINTF 适配的前提。本章将从接口形态、语言演进和边界划分三个维度展开。
一、HAL 接口的两种形态:Binderized 与 Passthrough
Android 8.0 引入 Treble 架构后,HAL 接口被明确划分为两种运行形态:Binderized(绑定式)和 Passthrough(直通式)。这两种形态决定了 HAL 实现与调用方之间的通信方式、进程边界和生命周期管理。
Binderized HAL 运行在独立的 Vendor 进程中,通过 Binder IPC 与 Framework 通信。调用方通过 getService() 获取接口代理,所有调用都跨越进程边界。这种形态的优势是隔离性强、可独立更新、支持权限控制,是 Android 8.0 之后的主流形态。
Passthrough HAL 则以共享库形式被加载到调用方进程中,通常用于兼容旧版 HAL 或对性能敏感的场景。它通过 dlopen 加载 .so 文件,直接进行函数调用,不涉及 IPC 开销。Passthrough 模式在 Android 8.0 到 10 之间作为过渡方案存在,Android 11 之后逐步被 Binderized 取代。
核心区别:Binderized 是跨进程调用,Passthrough 是同进程调用。前者通过 hwservicemanager 注册和发现服务,后者通过 hw_get_module() 加载共享库。
二、HIDL 与 AIDL 的区别
HIDL(HAL Interface Definition Language)是 Android 8.0 为 Treble 架构设计的接口描述语言,而 AIDL(Android Interface Definition Language)原本用于应用层 Binder 通信,从 Android 11 开始被引入 HAL 领域。两者在语法、版本管理、类型系统和适用场景上存在显著差异。
| 对比维度 | HIDL | AIDL (HAL 场景) |
|---|---|---|
| 引入版本 | Android 8.0 | Android 11 起支持 HAL |
| 语法风格 | 类 C++,使用 interface、package |
类 Java/C++,使用 interface、parcelable |
| 版本管理 | 包名中嵌入主版本号,如 android.hardware.camera@2.4 |
通过 @VintfStability 和版本化接口管理 |
| 数据类型 | 自定义类型系统,支持 vec、fmq、memory |
复用 AIDL 类型系统,支持 Parcelable、List |
| 通信机制 | Binder + hwbinder 域 | Binder + 标准 binder 域(可配置) |
| Passthrough 支持 | 原生支持 @passthrough |
不支持 Passthrough,仅 Binderized |
| 当前状态 | 维护阶段,新 HAL 不推荐 | 推荐方向,Android 13+ 主推 |
从代码风格看,HIDL 接口定义如下:
// HIDL 示例:android.hardware.camera.provider@2.4
package android.hardware.camera.provider@2.4;
interface ICameraProvider {
getCameraIdList() generates (vec<string> cameraDeviceNames);
getCameraDeviceInterface_V3_x(string cameraDeviceName)
generates (ICameraDevice cameraDevice);
};
而 AIDL 的 HAL 接口定义更接近应用层写法:
// AIDL 示例:android.hardware.camera.provider.ICameraProvider
@VintfStability
interface ICameraProvider {
String[] getCameraIdList();
ICameraDevice getCameraDeviceInterface(String cameraDeviceName);
}
迁移建议:新项目应优先使用 AIDL 定义 HAL 接口,并添加 @VintfStability 注解以确保 VINTF 兼容性。已有 HIDL 接口可继续维护,但需在 manifest.xml 中正确声明。
三、Vendor 接口的边界定义
Vendor 接口的边界是指 Framework 与 Vendor 之间必须严格遵守的隔离线。这条边界不仅体现在代码层面,还体现在进程、分区、版本和兼容性声明中。
分区边界:Framework 代码位于 system 分区,Vendor 实现位于 vendor 分区。两者通过 /vendor/etc/vintf/manifest.xml 和 /system/etc/vintf/manifest.xml 声明各自提供的接口。
进程边界:Binderized HAL 运行在独立 Vendor 进程中,Framework 不能直接链接 Vendor 的 .so 文件。所有交互必须通过 Binder 接口完成。
版本边界:Vendor 接口必须声明版本号,Framework 根据版本号决定调用哪个接口。VINTF 兼容性矩阵(compatibility matrix)定义了 Framework 要求的接口版本范围与 Vendor 实际提供的版本之间的匹配规则。
类型边界:跨边界传递的数据类型必须是 VINTF 稳定的(VintfStability),不能使用仅 Framework 可见的内部类型。AIDL 中通过 @VintfStability 标记,HIDL 中通过 @1.0 等版本化包名保证。
常见误区:很多开发者认为只要接口定义正确就能通过 VINTF 检查,实际上还需要在 manifest.xml 中声明接口、在 compatibility matrix 中匹配版本,并确保 SELinux 策略允许跨分区访问。三者缺一不可。
四、案例与复盘:Camera HAL 的接口演进
以 Camera HAL 为例,Android 8.0 使用 android.hardware.camera.provider@2.4 HIDL 接口,运行在独立进程中,通过 hwbinder 通信。Android 11 开始引入 AIDL 版本的 android.hardware.camera.provider.ICameraProvider,Android 13 全面转向 AIDL。
在适配过程中,常见问题包括:
- manifest 中声明了 HIDL 接口但未声明 AIDL 接口,导致新 Framework 找不到服务;
- compatibility matrix 中版本范围写错,如将
2.4写成2.5,导致匹配失败; - Passthrough 模式下未正确设置
hw_get_module的模块 ID,导致加载失败; - AIDL 接口未添加
@VintfStability,导致 VINTF 检查报错。
复盘要点:Vendor 接口适配的核心是“声明—匹配—访问”三步闭环。声明在 manifest,匹配在 compatibility matrix,访问在 SELinux 策略。任何一步缺失都会导致接口不可用。理解 Binderized 与 Passthrough 的差异、HIDL 与 AIDL 的演进方向,以及边界的严格定义,是完成 VINTF 适配的基础能力。