适用于 HAL 的 AIDL

Android 11 引入了在 Android 中使用 AIDL 实现 HAL 的功能。这样就可以在不使用 HIDL 的情况下实现 Android 的部分代码。我们强烈建议尽量将 HAL 转换为只使用 AIDL(如果上游 HAL 使用 HIDL,则必须使用 HIDL)。

如果 HAL 使用 AIDL 在框架组件(例如 system.img 中的组件)和硬件组件(例如 vendor.img 中的组件)之间进行通信,则必须使用稳定的 AIDL。不过,如需在分区内进行通信(例如从一个 HAL 到另一个),则对所使用的 IPC 机制没有任何限制。

动机

AIDL 出现在 HIDL 之前,而且在 Android 框架组件之间或应用内等其他很多地方都有使用。现在,由于 AIDL 具备了稳定性支持,就可以只使用一个 IPC 运行时环境实现整个栈。此外,AIDL 的版本控制系统也优于 HIDL。

  • 只使用一种 IPC 语言意味着只需要了解、调试、优化和保护一个运行时环境。
  • AIDL 可为接口所有者提供内建的版本控制机制。
    • 所有者可以将方法添加到 Parcelable 的接口或字段的末尾。这意味着可以在持续多年的开发过程中简化对代码的版本控制,并逐年降低产生的开销(可以就地修改类型,而且更新接口版本不需要新增额外的库)。
    • 扩展接口可以在运行时附加,而不是在类型系统中附加,因此无需将下游扩展 rebase 到新版接口上。
  • 如果现有 AIDL 接口的所有者选择使其稳定化,此类接口可以直接使用。如果是在以前,必须用 HIDL 创建接口的完整副本。

编写 AIDL HAL 接口

为了让系统和供应商都可使用某个 AIDL 接口,需要对该接口进行两项更改:

  • 每个类型定义都需要带有 @VintfStability 注释
  • aidl_interface 声明需要包含 stability: "vintf",

只有接口所有者可以进行这些更改。

此外,为了最大限度地提高代码可移植性并避免出现潜在问题(例如不必要的额外库),建议您停用 CPP 后端。

    aidl_interface: {
        ...
        backends: {
            cpp: {
                enabled: false,
            },
        },
    }

查找 AIDL HAL 接口

AOSP 中 HAL 的稳定 AIDL 接口所在的基础目录与 HIDL 接口所在的基础目录相同,位于 aidl 文件夹中。

  • hardware/interfaces
  • frameworks/hardware/interfaces
  • system/hardware/interfaces

您应将扩展接口放入 vendor 或 hardware 中的其他 hardware/interfaces 子目录。强烈建议您在所有设备之间保持接口一致。扩展可以通过两种不同方式进行注册:

  • 在运行时注册
  • 独立注册(在全局注册和在 VINTF 内注册)

针对 AIDL 运行时环境进行构建

AIDL 具有三个不同的后端:Java、NDK、CPP。如需使用稳定的 AIDL,您必须始终使用位于 system/lib*/libbinder.so 的 libbinder 的系统副本,并能够访问 /dev/binder。对于供应商映像中的代码,这意味着 libbinder(来自 VNDK)无法使用:此库包含不稳定的 C++ API 和不稳定的内件。而原生供应商代码必须使用 AIDL 的 NDK 后端,链接到 libbinder_ndk(由系统 libbinder.so 提供支持),并链接到由 aidl_interface 条目创建的 -ndk_platform 库。

AIDL HAL 服务器实例名称

按照惯例,AIDL HAL 服务的实例名称应采用以下格式:$package.$type/$instance。例如,振动器 HAL 实例的注册名称为 android.hardware.vibrator.IVibrator/default

编写 AIDL HAL 服务器

必须在 VINTF 清单中声明 AIDL 服务器,示例如下:

    <hal format="aidl">
        <name>android.hardware.vibrator</name>
        <fqname>IVibrator/default</fqname>
    </hal>

否则,它们应该正常注册 AIDL 服务。运行 VTS 测试时,所有已声明的 AIDL HAL 应该都是可用的

编写 AIDL 客户端

AIDL 客户端必须在兼容性矩阵中声明自己,示例如下:

    <name>android.hardware.vibrator</name>
    <interface>
        <name>IVibrator</name>
        <instance>default</instance>
    </interface>

将现有 HAL 从 HIDL 转换为 AIDL

使用 hidl2aidl 工具将 HIDL 接口转换为 AIDL。按照下面的步骤操作,将 .hal 文件包转换为 .aidl 文件:

  1. 构建该工具(位于 system/tools/hidl/hidl2aidl 中

    m hidl2aidl
  2. 使用以下命令执行该工具:输出目录,后接要转换的文件包 

    hidl2aidl -o <output directory> <package>
  3. 仔细阅读生成的文件,并解决任何转换方面的问题。
    conversion.log 包含应该先解决的所有尚未解决的问题。
    生成的 .aidl 文件可能包含一些需要您进行相应处理的警告和建议。这些注释以 // 开头。
    请抓住这个机会,对文件包进行清理并加以改进。

适用于 AIDL HAL 的 sepolicy

对供应商代码可见的 AIDL 服务类型必须具有 vendor_service 属性。否则,sepolicy 配置将与任何其他 AIDL 服务相同

    type hal_power_service, service_manager_type, vendor_service;

对于平台定义的大多数服务,已经添加了具有正确类型的服务上下文(例如,android.hardware.power.IPower/default 已标记为 hal_power_service)。但是,如果框架客户端支持多种实例名称,则必须在设备专用 service_contexts 文件中添加其他实例名称

    android.hardware.power.IPower/custom_instance u:object_r:hal_power_service:s0

AIDL 与 HIDL 之间的主要差异

使用 AIDL HAL 或使用 AIDL HAL 接口时,请注意与编写 HIDL HAL 的差异。

  • AIDL 语言的语法更接近 Java。HIDL 语言的语法类似于 C++。
  • 所有 AIDL 接口都具有内置的错误状态。不要创建自定义状态类型,而应在接口文件中创建常量状态 int,并在 CPP/NDK 后端使用 EX_SERVICE_SPECIFIC,在 Java 后端使用 ServiceSpecificException
  • 未经检查的传输错误不会导致 AIDL 终止运行(未经检查的错误会导致 HIDL Return 终止运行)。
  • AIDL 只能为每个文件声明一种类型。
  • 除了 output 参数外,AIDL 参数还可以指定为 in/out/inout(没有“同步回调”)。
  • AIDL 将 fd 用作基元类型,而不是句柄。
  • HIDL 对不兼容的更改使用 Major 版本,对兼容的更改使用 Minor 版本。在 AIDL 中,向后兼容的更改已就位。 AIDL 没有对 Major 版本进行明确定义,而是将其并入软件包名称中。例如,AIDL 可能会使用软件包名称 bluetooth2
  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值