HIDL 原理及使用详解

目录

1.  HIDL 概念

1.1. Hidl 的简单介绍

1.2. Hidl 的设计目的

1.3. Hidl 与 Aidl 的对比

2 . HIDL 类型 

2.1 Passthrough

2.2 Binderized

3. HIDL 服务的实现

3.1 hidl_gen 工具路径

3.2 update-makefiles.sh 

3.3 update-files.sh 

3.4 HIDL 生成的文件 

3.5 service 和 impl 关系

3.6 添加 rc 文件 

3.7 启动 service 

 3.8 实现 client 端

4 . 新旧软件架构对比

4.1 Android 8.0 之前架构图

 4.2 binder 驱动通讯的实现

4.3 使用 HIDL 设计软件架构


1.  HIDL 概念

1.1. Hidl 的简单介绍

        HIDL的全称是HAL interface definition language(硬件抽象层接口定义语言),是Android
Framework 与Android HAL之间的接口。HIDL 旨在用于进程间通信 (IPC),进程之间的通信
采用 Binder 机制。

1.2. Hidl 的设计目的

        HIDL 的目标是,可以在无需重新构建 HAL 的情况下替换框架。HAL 将由供应商或 SOC
制造商构建,并放置在设备的 /vendor 分区中,这样一来,就可以在框架自己的分区中通过
OTA 替换框架,而无需重新编译 HAL。
HIDL 设计在以下方面之间保持了平衡:

•  互操作性。在可以使用各种架构、工具链和编译配置来编译的进程之间创建可互操作的
可靠接口。HIDL 接口是分版本的,发布后不得再进行更改。


•  效率。HIDL 会尝试尽可能减少复制操作的次数。HIDL 定义的数据以 C++ 标准布局数
据结构传递至 C++ 代码,无需解压,可直接使用。此外,HIDL 还提供共享内存接
口;由于 RPC 本身有点慢,因此 HIDL 支持两种无需使用 RPC 调用的数据传输方
法:共享内存和快速消息队列 (FMQ)。


•  直观。通过仅针对 RPC 使用 in 参数,HIDL 避开了内存所有权这一棘手问题:无法通
过相应方法高效返回的值将通过回调函数返回。无论是将数据传递到 HIDL 中以进行传
输,还是从 HIDL 接收数据,都不会改变数据的所有权,也就是说,数据所有权始终属
于调用函数。数据仅需要在函数被调用期间保留,可在被调用的函数返回数据后立即清
除。

1.3. Hidl 与 Aidl 的对比

2 . HIDL 类型 

2.1 Passthrough

        兼容之前的 HAL 使用方式(在同一个进程)。要将运行早期版本的 Android 的设备更新为
使用 Android O,您可以将惯用的(和旧版)HAL 封装在一个新 HIDL 接口中,该接口将在绑
定式模式和同进程(直通)模式提供 HAL。这种封装对于 HAL 和 Android 框架来说都是透明
的。
        直通模式仅适用于 C++ 客户端和实现。运行早期版本的 Android 的设备没有用 Java 编
写的 HAL,因此 Java HAL 自然而然经过 Binder 化。

2.2 Binderized

        使用 Binder 方式进行 IPC(在不同进程)。在使用 HIDL 的时候需要有两个软件包,一个
是 FQName-impl,一个是 FQName-service。FQName-impl 一般是 HAL 实现的部分或者是链接
HAL 的部分,FQName-service 就是 service 端。

3. HIDL 服务的实现

3.1 hidl_gen 工具路径

代码目录:system/tools/hidl

在使用的时候可以直接使用 out/host/linux-x86/bin/hidl-gen 或者使用:
source build/envsetup.sh
lunch m7332-userdebug
lunch 之后可以直接使用 hidl-gen,因为这个时候已经将 bin 的目录添加到了环境变量中了
可以使用 hidl-gen -h 查看

3.2 update-makefiles.sh 

通过/hardware/interfaces/update-makefiles.sh 可以创建编译 HIDL 文件的 Android.bp
假设我们创建一个 helloworld 的模块,在 hardware/interfaces 下创建 helloworld/1.0/IHelloWorld.hal:

通过 update-makefiles.sh 就可以在对应 package 的目录下创建 Android.bp:
chenzhaohao@ubuntu:~/9632-1/public-mtk9632/hardware/interfaces$ ./update-makefiles.sh
…….
Updating android.hardware.helloworld@1.0
…….

name:FQName 的全名
root:定义好的 package root name
interfaces:编译过程中依赖的接口名称,如 c 中的 shared library
gen_java:是否编译为 Java 使用的接口
当然,还有其他的参数,例如 gen_java_constants 设为 true 的时候会生成为 Java 使用的 Constants 类。
可以根据实际情况修改该 Android.bp

3.3 update-files.sh 

IHelloWorld.hal 和对应的 Android.bp 创建好后,就可以根据需要实现 FQName-impl 和 FQName-service 所
需要的文件,而这些文件也是通过 hidl-gen 创建的,就是下面这个脚本。

update-files.sh 文件路径 移动到源码根目录下
执行
chenzhaohao@ubuntu:~/9632-1/public-mtk9632/$ ./update-files.sh

执行完之后自动生成了 default 目录

创建后的 Android.bp 如下:

        可以根据特殊的需要进行修改,例如,vendor 需要设为 true,这样编译出来的 so 位于 vendor 下面,而不是 system。也可以使用同样的方式为 FQName-service 创建对应的规则。 

 

3.4 HIDL 生成的文件 

在编译 HIDL 文件,会在 out/soong/.interfaces/PACKAGE/MOUDLE/VERSION/下生成对应的文件。例如helloworld 是在 hardware/interfaces 下创建,所以生成的文件路径为:
out/soong/.intermediates/hardware/interfaces/helloworld/1.0

 

其中:
android.hardware.helloworld@1.0 就是模块对应的库文件;
android.hardware.helloworld@1.0_genc++ 为生成对应的 C++临时文件,在使用的时候都是链接到这里;
android.hardware.helloworld@1.0_genc++/gen/android/hardware/helloworld/1.0/HelloWorldAll.cpp
android.hardware.helloworld@1.0_genc++_headers 为生成的 C++ 所需的头文件;

android.hardware.helloworld-V1.0-java 为 java 代码所使用的 java 库文件;
android.hardware.helloworld-V1.0-java_gen_java 为 java 代码所使用的 java 文件

3.5 service 和 impl 关系

当 IHelloworld.hal 创建完成就可以创建对应的 HIDL 实现代码(impl 和 service),而 hidl-gen 也提供了默认提供了生成的方式。
Impl:

service.端的 service.cpp 需要手动去编写,可以拷贝系统已存在的过来进行修改,比较简单

3.6 添加 rc 文件 

在实现了 serivce 和 impl 代码后需要添加 rc 文件,文件名为 android.hardware.helloworld@1.0-
service.rc:

3.7 启动 service 

 在 xml 中配置完成之后就直接 start;另外需要设置 selinux 中添加 te 文件,设置 domain 信息。对于selinux 配置,这里暂不分析

 3.8 实现 client 端

客户端的文件直接使用 java 文件引用编译生成的 java 静态库 android.hardware.helloworld-V1.0-java然后 IHelloWorld.getService(true); 来获取 HIDL 服务。这样就直接跳过 java – jni ---c++

接着可以直接在 HelloWorld.cpp 中引用 hal 层编译生成的 so 文件来操作硬件外设。

4 . 新旧软件架构对比

4.1 Android 8.0 之前架构图


以 Android 原生自带的 Led 硬件访问服务为例子

        这里的难度是在 binder 通讯那块,如果使用的是 Android 原生的就 不需要重新写。但是想要开发自己的中间件,就必须实现要去实现自己的 binder 驱动通讯。

 4.2 binder 驱动通讯的实现

        采用旧架构进行中间件的设计和开发架构图如下,这里忽略 app 到中间件的的调用流程,这个流程和HIDL 的一样。流程直接从 native 开始往下走。

从上面的架构流程图可以看出,使用老技术开发操作硬件外设是非常的复杂和繁琐。涉及到的文件和知识点众多,无论是前期开发或者是后期的维护难度是非常大。因此,在 Android 8.0 之后的版本,采用了 HIDL进行软件架构重构,弃用之前的方法。HIDL 加快了相应速度,提高访问效率,而且代码简洁,接口逻辑清晰,开发和维护起来方便。

4.3 使用 HIDL 设计软件架构

有了前面 3 章节介绍 Hidl 的知识点之后,我们就可以设计出基于 HIDL 的软件架构。

通过新软件架构图和传统的软件架构图可以知道 HIDL 那层代替了原来的 

  • 17
    点赞
  • 119
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
机器视觉是指计算机系统利用摄像机等图像采集装置获取外部信息,并通过图像处理和分析技术实现感知、理解和解释图像的能力。机器视觉的主要原理是通过图像信号的采集、预处理、特征提取和分类等步骤,将图像转化为计算机可以理解和处理的数据,然后利用算法和模型对图像进行分析和识别。 机器视觉的应用案例种类繁多。举例来说,智能安防领域常用的人脸识别技术就是机器视觉的一个应用案例。通过采集人脸图像,利用机器学习算法提取人脸的特征,并将其与已有的人脸数据库进行匹配,实现对人脸的自动识别。这种技术可以应用于人脸门禁、人脸支付、人脸搜索等场景,提高了安全性和便利性。 另一个应用案例是机器视觉在工业生产中的应用。例如,智能机器人可以利用视觉系统检测和识别产品的形状、颜色和缺陷等信息,并根据识别结果进行处理和控制,实现自动化生产。这种技术可以提高生产效率和产品质量,并减少人力成本。 此外,机器视觉还可以应用于医学影像分析、无人驾驶、农业等领域。例如,在医学影像领域,机器视觉可以帮助医生对X射线、CT、MRI等影像进行自动分析和诊断,提高疾病的早期发现率和诊断准确性。 综上所述,机器视觉通过图像采集、处理和分析等步骤,实现对图像的感知、理解和解释。其应用案例涵盖了智能安防、工业生产、医学影像等多个领域,为实现自动化和智能化提供了重要的技术支持。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奔跑吧撸码兄弟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值