HIDL 简介
HIDL 即HAL interface definition language,在 Android Project Treble 中被起草,在 Android O 中被全面使用。
HIDL用于进程间通信(IPC)。对于c++和Java程序员来说,HIDL的语法看起来会很熟悉,即使它有一系列不同的关键字。HIDL还使用java风格的注解。
Project Treble
Project treble是Android O中引入的特性.
主要的目标是Android模块化,根据谷歌、SoC供应商和OEM的需求分离所有权和分配不同的模块。
Vendor 模块被分离到一个独立的可单独更新的image,从而改进了软件升级发布的过程
Treble由以下几部分组成:
-
Kernel modularization
-
HAL re-architecture (binderization)
-
Separation of the vendor and OEM modules from the system image
关于HIDL的设计
HIDL的设计目的是为了能够在不重新编译HALs的情况下能够替换framework。HALs将由供应商或SOC制造商构建,并放在设备的vendor下的分区中,而framework框架在它自己的分区中发挥作用,能够被OTA替换而不重新编译HALs。
HIDL的设计平衡了以下问题:
共用性
在进程间创建可靠的共用接口,而这些进程可能有不同的架构、工具链和构建配置。HIDL接口是版本化的,在发布后不能更改。
效率
HIDL会将复制的次数最小化。HIDL定义的数据以C++标准layout data structures的形式传递给c++代码,这种数据结构可以不打包的情况下使用。HIDL还提供共享内存接口,由于RPCs天生有点慢,HIDL无需使用RPC调用,而支持两种传输数据的方法:shared memory (共享内存)和 Fast Message Queue (FMQ).
直观
对于RPC,HIDL只使用参数(参见AIDL),避免了内存所有权的棘手问题;不能有效通过方法返回的值通过回调函数返回。既不将数据传递到HIDL,也不从HIDL接收数据,改变数据的所有权。数据只需要在被调用函数的持续时间内存在,并且可以在被调用函数返回后立即销毁。
使用 passthrough 模式
为了更新运行在Android系统早期版本的设备到Android O操作系统,你可以将传统的(和 legacy遗留的)HALs封装在新的HIDL接口中,这一接口以binderized 和same-process (passthrough)的模式服务于HAL。这种封装对HAL和Android框架都是透明的。
Passthrough模式仅适用于c++的客户端和实现。运行Android早期版本的设备没有Java编写的HALs,因此Java HALs必然使用binderized 的模式。
Passthrough header files
当一个.hal文件被编译后, hidl-gen除了用于binder通信的头文件外,还生成一个额外的 passthrough 头文件 BsFoo.h ;这个头文件定义了dlopened的函数. 由于passthrough HALs 运行在调用它们的相同的进程中,大多数情况下 passthrough 方法被直接通过函数调用 (相同线程)。oneway 方法在他们自己的线程中运行,因为它们并不打算等待HAL来处理它们(这意味着任何在passthrough模式中使用oneway方法的HAL必须是线程安全的)。
给定一个IFoo.hal文件,BsFoo.h封装了hidl生成的方法以提供额外的特性(比如在另一个线程中运行oneway事务)。这个文件类似于BpFoo。但是,不是通过binder进行IPC调用,而是直接调用所需的函数。未来HALs可能提供多种实现,例如FooFast HAL和FooAccurate HAL。在这种情况下,将创建每个额外实现的文件(例如:PTFooFast.cpp和PTFooAccurate.cpp)。
Binderizing passthrough HALs
支持passthrough 模式的HAL实现可以binderized 。对于一个HAL 接口a.b.c.d@M.N::IFoo,需要创建两个包:
- a.b.c.d@M.N::IFoo-impl. 包含HAL的实现,并暴露函数IFoo * HIDL_FETCH_IFoo(const char * name)。在legacy hal设备上,这个包是dlopened 的,实现是使用HIDL_FETCH_IFoo实例化的。 您可以使用hidl - gen和- lc + + - impl和- landroidbp - impl生成基本代码。
- a.b.c.d@M.N::IFoo-service. 打开passthrough HAL并将其注册为一个binder化服务,使相同的HAL实现被用作passthrough 和binderized。
给定类型IFoo,您可以调用sp < IFoo > IFoo::getService(string name, bool getStub)来获取IFoo的实例。
如果getStub值是true,getService尝试只以passthrough模式打开HAL。如果getStub为false,则getService尝试查找到一个binderized 服务;如果失败,则尝试找到passthrough服务。getStub参数除了defaultPassthroughServiceImplementation不应使用。(使用Android O的设备是完全binderized 的设备,因此不允许以passthrough模式打开一个服务。)
HIDL 语法
HIDL语言类似于C(但不使用C预处理器)
- /* / 表示文档注释.
- /* */ 表示文档多行注释.
- // 表示在一行结束后注释
- [empty] 表明当前项的值为空
- ? 放置在项前,表明该项为可选项.
- … 表明该序列包含0个或多个如前述使用分隔符隔开的项
- , 逗号用于分隔序列中的元素
- ; 分号用于标记每个元素的结束位置.
- @entry 当前HAL模块被使用时应当被最先调用的接口
- @exit 当前HAL模块被调用时应当被最后调用的接口
- @callflow(next={“name_a”, “name_b”, “name_c”}) 当前接口被调用后可能被调用的接口列表。其中name_a接口被调用的概率最大,name_c接口被调用的概率最小。如果只存在1个可能被调用的接口,那么花括号{ }可以省略不写。如果给定的接口名无效,则会导致VTS编译失败。
- @callflow(next={“*”}) 当前接口被调用后可能会调用任意接口
Example:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
原文地址: http://blog.csdn.net/ch853199769/article/details/77840099