HIDL的全称是HAL interface definition language(硬件抽象层接口定义语言),在此之前Android 有AIDL,架构在Android binder 之上,用来定义Android 基于Binder通信的Client 与Service之间的接口。HIDL也是类似的作用,只不过定义的是Android Framework与Android HAL实现之间的接口,用于指定 HAL 和其用户之间的接口的一种接口描述语言 (IDL)。HIDL 允许指定类型和方法调用(会汇集到接口和软件包中)。从更广泛的意义上来说,HIDL 是用于在可以独立编译的代码库之间进行通信的系统。
HIDL 旨在用于进程间通信 (IPC)。进程之间的通信采用 Binder 机制。对于必须与进程相关联的代码库,还可以使用直通模式(在 Java 中不受支持)。
HIDL 可指定数据结构和方法签名,这些内容会整理归类到接口(与类相似)中,而接口会汇集到软件包中。尽管 HIDL 具有一系列不同的关键字,但 C++ 和 Java 程序员对 HIDL 的语法并不陌生。此外,HIDL 还使用 Java 样式的注释。
在Android O之前,HAL是一个个的.so库,通过dlopen来进行打开,库和framework位于同一个进程。
在Android O之后,framework和hal运行于不同的进程,所有的HAL采用新的HIDL技术来完成。
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对比与AIDL
HIDL工作模式
1:binderized (绑定式 HAL)
使用Binder 方式进行IPC(在不同进程)。在使用HIDL 的时候需要有两个软件包,一个是FQName-impl,一个是FQName-service。FQName-impl一般是HAL 实现的部分或者是链接HAL的部分,FQName-service 就是service 端。
2:passthrough(直通式HAL)
兼容之前的HAL 使用方式(在同一个进程)。要将运行早期版本的 Android 的设备更新为使用 Android O,您可以将惯用的(和旧版)HAL 封装在一个新 HIDL 接口中,该接口将在绑定式模式和同进程(直通)模式提供 HAL。这种封装对于 HAL 和 Android 框架来说都是透明的。
直通模式仅适用于 C++ 客户端和实现。运行早期版本的 Android 的设备没有用 Java 编写的 HAL,因此 Java HAL 自然而然经过 Binder 化。
使用直通模式
要将运行早期版本的 Android 的设备更新为使用 Android O,您可以将惯用的(和旧版)HAL 封装在一个新 HIDL 接口中,该接口将在绑定式模式和同进程(直通)模式提供 HAL。这种封装对于 HAL 和 Android 框架来说都是透明的。
直通模式仅适用于 C++ 客户端和实现。搭载较低版本 Android 的设备没有用 Java 编写的 HAL,因此 Java HAL 本质上经过 Binder 化。
直通式头文件
编译 .hal
文件时,除用于 Binder 通信的头文件之外,hidl-gen
还会生成一个额外的直通式头文件 BsFoo.h
;此头文件定义了要执行 dlopen
操作的函数。由于直通式 HAL 会在调用它们的同一进程中运行,因此在大多数情况下,直通方法由直接函数调用(同一线程)调用。oneway
方法在自身的线程中运行,因为它们不需要等待 HAL 来处理它们(这意味着,在直通模式下使用 oneway
方法的所有 HAL 必须满足线程安全要求)。
如果有一个 IFoo.hal
,BsFoo.h
会封装 HIDL 生成的方法,以提供额外的功能(例如使 oneway
事务在其他线程中运行)。该文件类似于 BpFoo.h
,但是,所需函数是直接调用的,而不是使用 Binder 传递来调用 IPC。未来,HAL 的实现可能会提供多种实现结果,例如 FooFast HAL 和 FooAccurate HAL。在这种情况下,系统会针对每种额外的实现结果创建一个文件(例如 PTFooFast.cpp
和 PTFooAccurate.cpp
)。
Binder 化直通式 HAL
您可以将支持直通模式的 HAL 实现 Binder 化。如果有一个 HAL 接口 a.b.c.d@M.N::IFoo
,系统会创建两个软件包:
a.b.c.d@M.N::IFoo-impl
。该软件包包含 HAL 的实现,并提供函数IFoo* HIDL_FETCH_IFoo(const char* name)
。在旧版设备上,此软件包经过dlopen
处理,且实现使用HIDL_FETCH_IFoo
进行了实例化。您可以使用hidl-gen
、-Lc++-impl
和-Landroidbp-impl
生成基础代码。a.b.c.d@M.N::IFoo-service
。打开直通式 HAL,并将其自身注册为 Binder 化服务,从而使同一 HAL 实现能够同时以直通模式和 Binder 化模式使用。
如果有一个类型 IFoo
,您可以调用 sp<IFoo> IFoo::getService(string name, bool getStub)
,以获取对 IFoo
实例的访问权限。如果 getStub
为 True,getService
会尝试仅在直通模式下打开 HAL。如果 getStub
为 False,getService
会尝试查找 Binder 化服务;如果未找到,则它会尝试查找直通式服务。除了在 defaultPassthroughServiceImplementation
中,其余情况一律不得使用 getStub
参数。(搭载 Android O 的设备是完全 Binder 化的设备,因此不得在直通模式下打开服务。)
HIDL 语法
根据设计,HIDL 语言与 C 语言类似(但前者不使用 C 预处理器)。下面未描述的所有标点符号(用途明显的 =
和 |
除外)都是语法的一部分。
每个 HIDL package包里都含有一个名为types.hal的文件,该文件中定义了这个包里所有 interface 共享的用户自定义数据类型,并且一般也会导入需要用到的其它包里的数据类型。
当前包中新的定义的 interface 可以继承自从其它包里导入的 interface,这样的继承关系可以使用extend关键字实现。
由 Google 提供的包叫做core package,包名始终以android.hardware.开头,以子系统名加以区分。比如 NFC 包的名字就应该为android.hardware.nfc,摄像头包的名字就应该为android.hardware.camera。这些 core包存放于hardware/interfaces/目录下。由各芯片厂商和 ODM厂商提供的包叫做non-core package,包名形式一般以vendor.$(vendorName).hardware.开头,比如vendor.samsung.hardware.。这些 non-core包一般存放于vendor/$(vendorName)/interfaces/目录下。 包的版本使用主、次版本号进行描述,紧随包名之后。比如android.hardware.audio@2.0表述这个 audio 包的版本是 2.0,主版本号是 2,次版本号是 0。
此外,每个 HIDL 包在被发布后就不能再对其内容进行变动了,如果要增加或修改这个包里的接口或数据类型,应该新建一个新版本的包,在这个新版本的包里进行变更。
HIDL分析的博文:
https://source.android.google.cn/devices/architecture/hidl-cpp/
https://justinwei.blog.youkuaiyun.com/article/details/86514997
https://blog.youkuaiyun.com/shift_wwx/article/details/86530600
https://blog.youkuaiyun.com/u013357557/article/details/84561457
https://www.jianshu.com/p/ca6823b897b5
https://blog.youkuaiyun.com/u013357557/article/details/84561652
https://redspider110.github.io/2018/12/27/0110-android-hidl/
https://blog.youkuaiyun.com/solid_sdu/article/details/78518537