最近在学习HIDL,有很多的疑惑,在这里记录一下,加深自己的理解,以下部分大多来自官网。
官网:https://source.android.com/devices/architecture/hidl
HIDL定义
HAL 接口定义语言(简称 HIDL,发音为“hide-l”)是用于指定 HAL 和其用户之间的接口的一种接口描述语言 (IDL)。HIDL 允许指定类型和方法调用(会汇集到接口和软件包中)。从更广泛的意义上来说,HIDL 是用于在可以独立编译的代码库之间进行通信的系统。
HIDL 旨在用于进程间通信 (IPC)。进程之间的通信经过 Binder 化。对于必须与进程相关联的代码库,还可以使用直通模式(在 Java 中不受支持)。
HIDL 可指定数据结构和方法签名,这些内容会整理归类到接口(与类相似)中,而接口会汇集到软件包中。尽管 HIDL 具有一系列不同的关键字,但 C++ 和 Java 程序员对 HIDL 的语法并不陌生。此外,HIDL 还使用 Java 样式的注释。
HIDL C++
Android O 对 Android 操作系统的架构重新进行了设计,以在独立于设备的 Android 平台与特定于设备和供应商的代码之间定义清晰的接口。Android 已经以 HAL 接口的形式(在 hardware/libhardware
中定义为 C 标头)定义了许多此类接口。HIDL 将这些 HAL 接口替换为稳定的带版本接口,它们可以是采用 C++(如下所述)或 Java 的客户端和服务器端 HIDL 接口。
本部分中的几页内容介绍了 HIDL 接口的 C++ 实现,其中详细说明了 hidl-gen
编译器基于 HIDL .hal
文件自动生成的文件,这些文件如何打包,以及如何将这些文件与使用它们的 C++ 代码集成。
HIDL 设计
HIDL 的目标是,框架可以在无需重新构建 HAL 的情况下进行替换。HAL 将由供应商或 SOC 制造商构建,放置在设备的 /vendor
分区中,这样一来,框架就可以在其自己的分区中通过 OTA 进行替换,而无需重新编译 HAL。
HIDL 设计在以下方面之间保持了平衡:
- 互操作性。在可以使用各种架构、工具链和编译配置来编译的进程之间创建可互操作的可靠接口。HIDL 接口是分版本的,发布后不得再进行更改。
- 效率。HIDL 会尝试尽可能减少复制操作的次数。HIDL 定义的数据以 C++ 标准布局数据结构传递至 C++ 代码,无需解压,可直接使用。此外,HIDL 还提供共享内存接口;由于 RPC 本身有点慢,因此 HIDL 支持两种无需使用 RPC 调用的数据传输方法:共享内存和快速消息队列 (FMQ)。
- 直观。通过仅针对 RPC 使用
in
参数,HIDL 避开了内存所有权这一棘手问题(请参阅 Android 接口定义语言 (AIDL));无法从方法高效返回的值将通过回调函数返回。无论是将数据传递到 HIDL 中以进行传输,还是从 HIDL 接收数据,都不会改变数据的所有权,也就是说,数据所有权始终属于调用函数。数据仅需要在函数被调用期间保留,可在被调用的函数返回数据后立即清除。
HIDL的架构模式
- Passthrough 模式
- Binder 化的 Passthrough HALs
什么是Binder化?
一直以来,供应商进程都使用 Binder 进程间通信 (IPC) 技术进行通信。在 Android O 中,/dev/binder 设备节点成为了框架进程的专属节点,这意味着供应商进程将无法再访问该节点。供应商进程可以访问 /dev/hwbinder,但必须将其 AIDL 接口转为使用 HIDL。
HIDL 语法
根据设计,HIDL 语言与 C 语言类似(但前者不使用 C 预处理器)。下面未描述的所有标点符号(用途明显的 = 和 | 除外)都是语法的一部分。
/** */
表示文档注释。此样式只能应用于类型、方法、字段和枚举值声明。/* */
表示多行注释。//
表示注释一直持续到行结束。除了//
,换行符与任何其他空白一样。- 在以下示例语法中,从
//
到行结束的文本不是语法的一部分,而是对语法的注释。 [empty]
表示该字词可能为空。?
跟在文本或字词后,表示它是可选的。...
表示包含零个或多个项、用指定的分隔符号分隔的序列。HIDL 中不含可变参数。- 逗号用于分隔序列元素。
- 分号用于终止各个元素,包括最后的元素。
- 大写字母是非终止符。
- italics 是一个令牌系列,例如
*integer*
或*identifier*
(标准 C 解析规则)。 - constexpr 是 C 样式的常量表达式(如
1 + 1
和1L << 3
)。 - import_name 是软件包或接口名称,HIDL 版本编号中所述的方式加以限定。
- 小写
words
是文本令牌。
实例:
ROOT =
PACKAGE IMPORTS PREAMBLE {
ITEM ITEM ... } // not for types.hal
PREAMBLE = interface identifier EXTENDS
| PACKAGE IMPORTS ITEM ITEM... // only for types.hal; no method definitions
ITEM =
ANNOTATIONS? oneway? ident