HIDL C++

Android O 对 Android 操作系统的架构重新进行了设计,以在独立于设备的 Android 平台与特定于设备和供应商的代码之间定义清晰的接口。Android 已经以 HAL 接口的形式(在 hardware/libhardware 下定义为 C 标头)定义了许多此类接口。HIDL 将这些 HAL 接口替换为稳定的带版本接口,它们可以是采用 C++ 的客户端和服务器端 HIDL 接口(如下所述)或 Java 接口。

本部分中的几页内容介绍了 HIDL 接口的 C++ 实现,其中详细说明了 hidl-gen 编译器基于 HIDL .hal 文件自动生成的文件,这些文件如何打包,以及如何将这些文件与使用它们的 C++ 代码集成。

客户端和服务器实现

HIDL 接口具有客户端和服务器实现:

  • HIDL 接口的客户端实现是指通过在该接口上调用方法来使用该接口的代码。
  • 服务器实现是指 HIDL 接口的实现,它可接收来自客户端的调用并返回结果(如有必要)。

在从 libhardware HAL 转换为 HIDL HAL 的过程中,HAL 实现成为服务器,而调用 HAL 的进程则成为客户端。默认实现可提供直通和绑定式 HAL,并可能会随着时间而发生变化:

图 1. 旧版 HAL 的发展历程。

创建 HAL 客户端

首先将 HAL 库添加到 makefile 中:

  • Make:LOCAL_SHARED_LIBRARIES += android.hardware.nfc@1.0
  • Soong:shared_libs: [ …, android.hardware.nfc@1.0 ]

接下来,添加 HAL 头文件:

#include <android/hardware/nfc/1.0/IFoo.h>
…
// in code:
sp<IFoo> client = IFoo::getService();
client->doThing();

创建 HAL 服务器

要创建 HAL 实现,您必须具有表示 HAL 的 .hal 文件并已在 hidl-gen 上使用 -Lmakefile-Landroidbp 为 HAL 生成 makefile(./hardware/interfaces/update-makefiles.sh 会为内部 HAL 文件执行这项操作,这是一个很好的参考)。从 libhardware 通过 HAL 传输时,您可以使用 c2hal 轻松完成许多此类工作。

创建必要的文件来实现您的 HAL:

PACKAGE=android.hardware.nfc@1.0
LOC=hardware/interfaces/nfc/1.0/default/
make hidl-gen -j64
hidl-gen -o $LOC -Lc++-impl -randroid.hardware:hardware/interfaces \
    -randroid.hidl:system/libhidl/transport $PACKAGE
hidl-gen -o $LOC -Landroidbp-impl -randroid.hardware:hardware/interfaces \
    -randroid.hidl:system/libhidl/transport $PACKAGE

为了让 HAL 在直通模式下发挥作用(对于旧版设备),您必须具有 HIDL_FETCH_IModuleName 函数(位于 /system/lib(64)?/hw/android.hardware.package@3.0-impl(-$OPTIONAL_IDENTIFIER).so 下),其中 $OPTIONAL_IDENTIFIER 是一个标识直通实现的字符串。直通模式要求会通过上述命令自动满足,这些命令也会创建 android.hardware.nfc@1.0-impl 目标。

接下来,使用功能填写存根并设置守护进程。守护进程代码(支持直通)示例:

#include <hidl/LegacySupport.h>

int main(int /* argc */, char* /* argv */ []) {
    return defaultPassthroughServiceImplementation<INfc>("nfc");
}

defaultPassthroughServiceImplementation 将对提供的 -impl 库执行 dlopen() 操作,并将其作为绑定式服务提供。守护进程代码(对于纯绑定式服务)示例:

int main(int /* argc */, char* /* argv */ []) {
    Nfc nfc = new Nfc();
    nfc->registerAsService();
}

此守护进程应该存在于 $PACKAGE + "-service"(例如 android.hardware.nfc@1.0-service)中。HAL 的特定类的 sepolicy 是属性 hal_<module>(例如 hal_nfc))。您必须将此属性应用到运行特定 HAL 的守护进程(如果同一进程提供多个 HAL,则可以将多个属性应用到该进程)。