Skip to content

AIDL与HAL迁移

以 power HAL 为主线,对照 Android 17 中 HIDL 与 Stable AIDL 的声明、服务注册、VINTF 和测试路径。

基于android-17.0.0_r1
AndroidAIDLHALHIDLVINTF

AIDL与HAL迁移 ​

HIDL 到 AIDL 的迁移不是只改接口文件后缀,它同时改变构建模块、服务注册 API、manifest 声明、客户端库和 VTS 契约。下面的对照图用于定位后文每一层的真实源码入口。

本文面向已经读过 Stable AIDL 和 AIDL后端生成 的读者。迁移不是把 .hal 后缀改成 .aidl:它会同时改变接口版本表达、生成库、服务注册 API、VINTF manifest 格式和 VTS 客户端。本文以 Android 17 的 hardware/interfaces/power 为主线,对照仍保留的 HIDL 1.0 服务和 AIDL V7 服务。

1. 两份接口 ​

1.1 HIDL声明 ​

源码文件:hardware/interfaces/power/1.0/IPower.hal

c
package android.hardware.power@1.0;

interface IPower {
    setInteractive(bool interactive);
    powerHint(PowerHint hint, int32_t data);
    setFeature(Feature feature, bool activate);
}

HIDL 用 package@version 命名空间表达版本,后续 1.1、1.2、1.3 通过 extends 继承前一版本接口。版本是类型名的一部分,客户端编译时就选择具体 V1_0::IPower。

1.2 AIDL声明 ​

源码文件:hardware/interfaces/power/aidl/android/hardware/power/IPower.aidl

AIDL 使用单一包名 android.hardware.power,版本由 aidl_interface 的快照和生成模块后缀 -V7 管理。接口演进不再创建 @1.1 命名空间,而是向当前快照追加兼容声明并冻结新版本。

2. 构建模块 ​

2.1 HIDL模块 ​

源码文件:hardware/interfaces/power/1.0/Android.bp

HIDL 模块名为 android.hardware.power@1.0,依赖 hidlbase/hidltransport 生成的 C++ 类型和服务支持库。每个接口版本有单独的模块与 VTS 目标,依赖关系沿版本继承展开。

2.2 AIDL模块 ​

源码文件:hardware/interfaces/power/aidl/Android.bp

make
aidl_interface {
    name: "android.hardware.power",
    vendor_available: true,
    stability: "vintf",
    backend: {
        cpp: { enabled: false },
        ndk: { enabled: true },
        java: { enabled: true, sdk_version: "module_current" },
        rust: { enabled: true },
    },
    versions_with_info: [
        { version: "1", imports: [] },
        { version: "7", imports: ["android.hardware.common.fmq-V1", "android.hardware.common-V2"] },
    ],
    frozen: true,
}

AIDL HAL 关闭 CPP backend,选择 NDK/Rust/Java;这不是语言偏好,而是 vendor 可用性与稳定 ABI 的构建边界。stability: "vintf"、版本列表和 frozen: true 把接口接入 Stable AIDL 的 API/hash 门禁。

3. 服务启动 ​

3.1 HIDL入口 ​

源码文件:hardware/interfaces/power/1.0/default/service.cpp

cpp
using android::hardware::power::V1_0::IPower;
int main() {
    return defaultPassthroughServiceImplementation<IPower>();
}

HIDL 服务入口交给 defaultPassthroughServiceImplementation,实例名和注册细节由 HIDL 支持层处理;对应 init rc 使用 android.hardware.power@1.0::IPower default 接口名。

3.2 AIDL入口 ​

源码文件:hardware/interfaces/power/aidl/default/main.cpp

cpp
ABinderProcess_setThreadPoolMaxThreadCount(0);
std::shared_ptr<Power> service = ndk::SharedRefBase::make<Power>();
const std::string instance = std::string() + Power::descriptor + "/default";
binder_status_t status = AServiceManager_addService(
        service->asBinder().get(), instance.c_str());
CHECK_EQ(status, STATUS_OK);
ABinderProcess_joinThreadPool();

AIDL NDK 服务显式创建实现对象、拼出 descriptor/default、调用 AServiceManager_addService,再进入 NDK Binder 线程池。这里的 owner 已从 HIDL passthrough wrapper 变成 AIDL Bn 实现对象。

4. 清单注册 ​

4.1 HIDL片段 ​

源码文件:hardware/interfaces/power/1.0/default/android.hardware.power@1.0-service.rc

text
service vendor.power-hal-1-0 /vendor/bin/hw/android.hardware.power@1.0-service
    interface android.hardware.power@1.0::IPower default

HIDL 的接口声明包含 @1.0 版本,服务管理器可按版本化接口名发现实例。

4.2 AIDL片段 ​

源码文件:hardware/interfaces/power/aidl/default/power-default.xml

xml
<manifest version="1.0" type="device">
    <hal format="aidl">
        <name>android.hardware.power</name>
        <version>7</version>
        <fqname>IPower/default</fqname>
    </hal>
</manifest>

AIDL manifest 把包名、版本和 fully-qualified instance 分成三个字段;服务进程注册的 android.hardware.power.IPower/default 必须与 manifest 的 fqname 对齐。只改二进制路径而不改清单,会导致 VINTF/服务发现不一致。

5. 客户端获取 ​

5.1 HIDL客户端 ​

源码文件:hardware/interfaces/power/1.2/vts/functional/VtsHalPowerV1_2TargetTest.cpp

cpp
power = IPower::getService(GetParam());
ASSERT_NE(nullptr, power);

客户端类型是 android::hardware::power::V1_2::IPower,getService 由 HIDL transport 查询版本化 descriptor 和 instance。

5.2 AIDL客户端 ​

源码文件:hardware/interfaces/power/aidl/vts/Android.bp、hardware/interfaces/power/aidl/vts/VtsHalPowerTargetTest.cpp

AIDL VTS 链接 android.hardware.power-V7-ndk,通过 NDK AServiceManager_waitForService/生成接口获取 IPower/default。客户端不再用 V1_2 C++ namespace,而是把版本选择落实在链接模块和生成 API 上。

6. 数据演进 ​

6.1 HIDL继承 ​

hardware/interfaces/power/1.1/IPower.hal 直接 extends android.hardware.power@1.0::IPower,新增方法出现在新 C++ interface 类型中;旧服务继续实现旧版本。

6.2 AIDL冻结 ​

AIDL aidl_api/android.hardware.power/{1..7} 保存完整快照。新版本通过 checkapi=compatible、hash 和冻结命令生成;旧客户端可链接旧 -Vn 版本,新服务通过生成的版本兼容逻辑处理旧事务。迁移后不能把“方法加到文件末尾”当作唯一兼容策略,必须让 API dump 看到它是兼容扩展。

7. 测试边界 ​

7.1 HIDL VTS ​

HIDL VTS 按 V1_1、V1_2、V1_3 分目录编译,每个测试使用对应生成接口和继承链,验证 transport 能否取得该版本实例。

7.2 AIDL VTS ​

源码文件:hardware/interfaces/power/aidl/vts/VtsHalPowerTargetTest.cpp

AIDL VTS 绑定 Stable AIDL V7 NDK 产物,同时由 power-default.xml 的 manifest 约束实际设备必须暴露 IPower/default。因此测试失败可能来自实现逻辑、服务注册、manifest 版本或生成库选择,不能只看方法返回值。

8. 迁移检查 ​

迁移一个 HAL 时,按源码顺序核对:接口包名与版本模型、Android.bp 的 backend/stability/versions、生成服务基类、main.cpp 的注册实例、VINTF manifest 的 format/name/version/fqname、VTS 客户端链接版本。若只替换接口文件而保留 HIDL 的 getService、rc interface 名称或版本继承假设,服务可能成功编译却无法被系统发现。