hidl 摘抄

2024-04-28 02:08
文章标签 摘抄 hidl

本文主要是介绍hidl 摘抄,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Android HAL类型
在此之前的ANDROID版本当中Android HAL没有什么特殊的特殊的,也么有什么分类,但是从android 8.0开始,Android重构了HAL与Android FW之间的联系结构,所以Android HAL会被区分成以下2种类型:
1,Binderized HALs,从名字上应该是指Binder化的HAL,对Android 比较熟悉的同学应该对binder这个东西很熟悉,我们是不是可以大胆猜猜下Android 8.0里的HAL是不是都是binder化了?也就是说HAL都被写成了binder service了?Android FW都是binder client?后续我们研究研究再来看看我们的猜测是不是正确的。
2,Passthrough HALs,从google的官方介绍来说,这个是对原先HAL的包装,但是最终的binder service 跟binder client都是活在同一个进程当中。这个应该是对老版本HAL的兼容。
3,Same-Process HALs,由于某些性能的因素,这些HALs必须运行在Android Framework 所在的进程当中。

按照google的要求,新设计生产的Android O设备,必须而且只能支持 Binderized HALs,而老版本的设备升级到Android O可以支持 Passthrough HALs,但是有些HAL也必须修改成 Binderized HALs。
这里写图片描述
以下HAL可以根据是升级设备或者新设备自由选择:
这里写图片描述
以下跟graphic相关的HAL因为涉及到性能问题,只能在同一个进程当中运行:
这里写图片描述

HIDL的相关介绍
HIDL的全称是HAL interface definition language(硬件抽象层接口定义语言),在此之前Android 有AIDL,架构在Android binder 之上,用来定义Android 基于Binder通信的Client 与Service之间的接口。HIDL也是类似的作用,只不过定义的是Android Framework与Android HAL实现之间的接口。

在AIDL机制中Android 会提供一系列工具会将用户定义的*.aidl文件编译生成Client端代码与Service端代码,用户仅仅 需要1)在Service端实现所需要实现的接口。2)在Client端调用相关接口。基于Binder机制,在Clinet端的调用会自动通过 binder驱动跨进程到service进程当中。

而在HIDL里,与AIDL比较类似,底层也是基于binder机制。但是也有稍微不一样的地方。为了支持HIDL,Android 对BInder做了一定程度的修改。

这里写图片描述

这里写图片描述

接下来,我们来研究下HIDL的语法,以及通过一个实际的例子来真实感受下HIDL。

HIDL的基本语法:

1)定义接口:

package android.hardware.tests.foo@1.0; interface ISimpleTest { enum SomeBaseEnum : uint8_t {bar = 66 }; struct Goober {int32_t q; string name; string address;};getCookie() generates (int32_t cookie);customVecInt() generates (vec chain);customVecStr() generates (vec<string> chain);mystr() generates (string str);myhandle() generates (handle str);};

在这里,我们定义一个新的HIDL接口,取名叫做 ISimpleTest, 从语法上看有点像JAVA的语法。interface是关键字,代表要创建一个HIDL的接口。我们把上述接口保存成 IsimpleTest.hal文件存放在hardware/interfaces/tests/foo/1.0/ISimpleTest.hal,其实 我们完全可以新建一个新目录,使用一个新的package名,而不使用android.hardware.tests.foo,

2)定义成员:
如上所示,HIDL当中可以像JAVA/C代码一样,很容易定义出联合体/结构体变量。

3)定义成员函数:
如上所示,定义的都是无参函数,如果需要定义一个带有参数的函数,可以写成doThis(float param);,这就代表是一个有参数,但是无返回值的函数。

而以上定义的 getCookie() generates (int32_t cookie); 其含义为:函数名为 getCookie,无参数传入,函数的返回值为一个int32_t 类型。

HIDL编译
在根目录执行./hardware/interfaces/update-makefiles.sh,我们能够看到会把Android 在hardware/interfaces下的所有package都会更新一遍,我们看下hardware/interfaces/tests/foo /1.0/Android.bp,在Android O当中,貌似使用了 Android.bp来替代Android.mk来作为编译管理工具。至于Android.bp的东西可以后续在研究,这里我们只关注于HIDL。

 
3 filegroup { 4 name: "android.hardware.tests.foo@1.0_hal", 5 srcs: [  6 "types.hal", 7 "IFoo.hal",  8 "IFooCallback.hal",  9 "IMyTypes.hal",  10 "ISimple.hal",  11 "ISimpleTest.hal",  12 "ITheirTypes.hal", 13 ], 14 } 
我们可以看到”ISimpleTest.hal”,已经被加进编译文件列表当中。

而在生成的C++文件:

16 genrule {  17 name: "android.hardware.tests.foo@1.0_genc++",  18 tools: ["hidl-gen"],  19 cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tests.foo@1.0",  20 srcs: [  21 ":android.hardware.tests.foo@1.0_hal", 22 ],  23 out: [ 24 "android/hardware/tests/foo/1.0/types.cpp",  25 "android/hardware/tests/foo/1.0/FooAll.cpp",  26 "android/hardware/tests/foo/1.0/FooCallbackAll.cpp",  27 "android/hardware/tests/foo/1.0/MyTypesAll.cpp",  28 "android/hardware/tests/foo/1.0/SimpleAll.cpp",  29 "android/hardware/tests/foo/1.0/SimpleTestAll.cpp",  30 "android/hardware/tests/foo/1.0/TheirTypesAll.cpp",  31 ],  32 } 我们可以看到这段逻辑是利用 hidl-gen工具来生成.cpp文件。命令是: cmd: “(locationhidl?gen)?o(genDir)-Lc++-sources -randroid.hardware:hardware/interfaces 
-randroid.hidl:system/libhidl/transport android.hardware.tests.foo@1.0”, 

.hal源码是:

20 srcs: [  21 ":android.hardware.tests.foo@1.0_hal",  22 ],

而这部分就是上面所定义的各种.hal文件。最终输出就是各种.cpp文件。我们比较关注的就是 SimpleTestAll.cpp文件。

同时会生成以下一些头文件:

34 genrule {  35 name: "android.hardware.tests.foo@1.0_genc++_headers",  36 tools: ["hidl-gen"],  37 cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tests.foo@1    .0",  38 srcs: [  39 ":android.hardware.tests.foo@1.0_hal",  40 ],  41 out: [……………………….  64 "android/hardware/tests/foo/1.0/ISimpleTest.h",  65 "android/hardware/tests/foo/1.0/IHwSimpleTest.h",  66 "android/hardware/tests/foo/1.0/BnHwSimpleTest.h",  67 "android/hardware/tests/foo/1.0/BpHwSimpleTest.h",  68 "android/hardware/tests/foo/1.0/BsSimpleTest.h",………………………...  74 ], 75 }

从生成的头文件里看,我们看到有 ISimpleTest.h, BnHwSimpleTest.h, BpHwSimpleTest.h,Bnxxxxx与Bpxxxxx这两个东西我们是不是看起来很眼熟?在Binder里, Ixxxxx.h定义了client与service统一的通用接口,而Bnxxxxx.h 派生自 Ixxxxx.h,做为service端实现的头文件,Bpxxxxx.h同样派生自 Ixxxxx.h做为client端的头文件。这样调用Bpxxxxx.h定义的接口,就自动利用binder机制跨进程由service端实现了 Bnxxxxx.h定义函数。

我们大胆的猜测下,HIDL编译生成的这些头文件使用方式应该是与AIDL编译出来的Bnxxxxx/Bpxxxxx作用类似,恭喜你,你的猜测很正确。

这里写图片描述

IFoo.h. Describes the pure IFoo interface in a C++ class; it contains the methods and types defined in the IFoointerface in the IFoo.hal file, translated to C++ types where necessary. Does not contain details related to the RPC mechanism (e.g., HwBinder) used to implement this interface. The class is namespaced with the package and version, e.g. ::android::hardware::samples::IFoo::V1_0. Both clients and servers include this header: Clients for calling methods on it and servers for implementing those methods.
IHwFoo.h. Header file that contains declarations for functions that serialize data types used in the interface. Developers should never include his header directly (it does not contain any classes).
BpFoo.h. A class that inherits from IFoo and describes the HwBinder proxy (client-side) implementation of the interface. Developers should never refer to this class directly.
BnFoo.h. A class that holds a reference to an IFoo implementation and describes the HwBinder stub (server-side) implementation of the interface. Developers should never refer to this class directly.

FooAll.cpp. A class that contains the implementations for both the HwBinder proxy and the HwBinder stub. When a client calls an interface method, the proxy automatically marshals the arguments from the client and sends the transaction to the binder kernel driver, which delivers the transaction to the stub on the other side (which then calls the actual server implementation).

Google的解释还是挺清楚,我就不画蛇添足的翻译成中文了。

.hal最终编译出来的结果是:

cc_library_shared {name: "android.hardware.tests.foo@1.0",defaults: ["hidl-module-defaults"],generated_sources: ["android.hardware.tests.foo@1.0_genc++"],generated_headers: ["android.hardware.tests.foo@1.0_genc++_headers"],export_generated_headers: ["android.hardware.tests.foo@1.0_genc++_headers"],vendor_available: true,shared_libs: [ "libhidlbase", "libhidltransport", "libhwbinder", "liblog", "libutils", "libcutils", "android.hidl.base@1.0",],export_shared_lib_headers: [ "libhidlbase", "libhidltransport", "libhwbinder", "libutils", "android.hidl.base@1.0",],

从上面看得很清楚,.hal文件被编译后会生成一个动态库文件 android.hardware.tests.foo@1.0.so

HIDL的使用
HIDL的使用,其实就是指怎么在service端实现,怎么在client端调用。其实也挺简单,基本流程就是service端往系统里注册,client从系统里拿到service 的proxy,然后调用。跟AIDL的Binder一样一样的。

Client端拿service的proxy:
foo = IFoo::getService(“foo”, mode == PASSTHROUGH /* getStub */);

使用的是Ixxx里自动生成的 getService函数,拿到之后就能使用.hal定义的接口了。

Service端往系统注册:
int main() {
return defaultPassthroughServiceImplementation();
}
而且nfc 模块自己写了一个.rc文件:
service nfc_hal_service /vendor/bin/hw/android.hardware.nfc@1.0-service
class hal
user nfc
group nfc

这样就能让系统的Init进程在开机阶段就把这个service启动起来。

稍微总结下HIDL相关的内容:
1)HIDL是Android O里的Treble计划的核心。目的是通过HIDL语法构建出一个松耦合的系统,最终目的是为了方便Android 升级,解决碎片化的问题。
2)Android为了实现 Binderized HAL有一个比较清晰的road map:
这里写图片描述

不过其实还有些东西还没有涉及到,比如FMQ,后续再来做探讨。下一部分,我们开始来研究下Android 新给出的Vendor NDK.



使用 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 package包里都含有一个名为types.hal的文件,该文件中定义了这个包里所有 interface 共享的用户自定义数据类型,并且一般也会导入需要用到的其它包里的数据类型。
  当前包中新的定义的 interface 可以继承自从其它包里导入的 interface,这样的继承关系可以使用extend关键字实现。比如下面示例中的 1.1 版本包中的 IQuux 接口就继承自 1.0 版本包中的 IQuux 接口:
// types.hal package android.hardware.example@1.1 import android.hardware.example@1.0 // 导入1.0的包// IQuux.hal package android.hardware.example@1.1 interface IQuux extends @1.0::IQuux {  // 继承1.0包中的接口fromBarToFoo(foo.bar b) generates (foo f);  // 直接使用fromBarToFoo方法而不再在当前包中声明 }


这篇关于hidl 摘抄的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/942086

相关文章

《自控力》-- 精华摘抄

我希望,这个旅程并不仅仅是走马观花的一瞥,不仅仅让你惊叹于神奇的科学研究。 实际上,每一项研究都告诉我们很多东西。这些东西关乎我们自己,也关乎我们的意志力挑战。它们让我们意识到,我们天生就有自控的能力,即便有时我们不太会运用这种能力。它们甚至告诉我们,做人意味着什么。比如,我们一次又一次地看到,并不是只有一个自我,人是多个自我的混合体。 人类的天性不仅包括了想即时满足的自我,也包括了目标远大的

深度学习小笔记05-扩展autograd-摘抄自《深度学习框架PyTorch:入门与实践》陈云-附个人书评

为什么摘抄这一段,因为我认为这里是一个非常有用的部分,看完autograd就想去问答区提问: 然后发现没有c币,于是乎暂时作罢,结果发现答案就在下一小节(先看完再想问题,不然浪费了一个好问题),没办法我就是这么热爱思考的一个人,看完立刻就有问题,等不到再看一段书。 — 我是分界线— p94:目前,绝大多数函数都可以使用autograd实现反向求导,但如果需要自己写一个复杂的函数,不支持自动

【Linux】系列入门摘抄笔记-9-软件管理与Yum源配置

背景 Linux和Windows是完全不同的操作系统,软件包的安装和管理也是截然不同的。Linux操作系统中的软件包非常多,而且几乎都是经GPL协议授权的,Linux操作系统中的软件包大致可以分为两类:源码包与二进制包。 1.源码包 源码包里面是一大堆源代码文件,是由程序员按照特定的格式和语法编写出来的代码文件。源码包中的代码文件是无法直接安装到操作系统上的,因为计算机只认识二进制语言,也就

好段落句子摘抄

创新思路:   Encoder-Decoder是个创新游戏大杀器,一方面如上所述,可以搞各种不同的模型组合,另外一方面它的应用场景多得不得了,比如对于机器翻译来说,<X,Y>就是对应不同语言的句子,比如X是英语句子,Y是对应的中文句子翻译。再比如对于文本摘要来说,X就是一篇文章,Y就是对应的摘要;再比如对于对话机器人来说,X就是某人的一句话,Y就是对话机器人的应答;再比如……总之,太多了。哎,那位

Android8.1 Camera2+HAL3之HIDL open()流程(二十)

跟了整整一天代码,总算有点清晰了....  简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言:  人生从来没有捷径,

[Android] 使用 android 自带的 hidl 共享内存接口,Ashmem

Android 提供了 一个共享内存服务 android::hidl::allocator::V1_0::IAllocator / android::hidl::memory::V1_0::IMemory, 通过这个接口可以向 android 直接请求共享内存。使用此方法可以更加方便和安全地在 android 系统中使用共享内存,而不需要使用 posix c 的共享内存模块。 源码: p

Android12之如何查看hidl服务

1.前言 本篇目的:在Android源码中提供了cmd、service、dumpsys来获取Binder服务的工具,但是Android8.0以后推出HIDL服务, 前边三个工具是无法获取到的,下面我们如何获取HIDL服务呢? 注意:Android13开始,Camera将使用AIDL替代HIDL。 2.解决方式 Google为我们提供了一个脚lshal的工具,下面来看下它的用法。 <1>.ls

20240419金融读报:加大绿色债券支持绿色金融货币政策仍有空间人民银行对金融服务实体理解摘抄

1、国家发文支持通过发行绿色债券、绿色资产支持正确等支持绿色金融。但2023年绿色债券发行规模占比1.17%。(是不是可以买一支,乘风起?) 2、4月18日,国新办举行新闻发布会,表明货币政策还有空间,我们将密切观察政策效果及经济恢复、目标实现情况,择机用好储备工具(还会再放松一些信贷呀?) 3、人民银行对金融服务实体理解摘抄:(1)货币信贷总量要稳,不多不少,不急不徐(2)盘活存量、优化信贷结构

《领域驱动的设计》摘抄

主要的的软件设计师认为领域建模和设计是过去二十年来非常重要的话题,但令人惊讶的是,很少有人编写需要做什么,或者应该如何做的文章。虽然这个方法还不明确,但其观点已经在面向对象社区中发展成一种潜流,我称之“领域驱动的设计”在过去的十年里,我关注于开发在不同业务领域和技术领域中的复杂系统。我曾经试验过那些软件设计和开发过程的最佳实践,当他们刚刚从面向对象开发社区的领导者那里形成。我的一部分项目非常成功,

每日一读|经典美文摘抄

1、记不清有多少个夜晚,在我翻阅纸张的指间滑落;记不清有多少支蜡烛,在我的凝视中化为灰烬。逝者如斯,我时时刻刻会听见自己对生命承诺的余音,感到岁月的流转在渐渐稀释我的年少无知,我愿自己是一只上足了发条的时钟,在昼夜不停的流转中留下自己充实的每一刻。 2、如果人类不好好保护我们这个赖以生存的地球,终有一天,风沙的肆虐与垃圾的堆积会吞没我们美丽的家园。我向全世界的人们呼吁:让我们从现在开始,从我做起