精选文章 HIDL详解-Android10.0 HwBinder通信原理(二)

HIDL详解-Android10.0 HwBinder通信原理(二)

作者:IngresGe 时间: 2021-02-05 09:43:11
IngresGe 2021-02-05 09:43:11
【摘要】摘要:本节主要来讲解Android10.0 HIDL相关知识 
 
 阅读本文大约需要花费18分钟。 
 文章首发微信公众号:IngresGe 
 专注于Android系统级源码分析,Android的平台设计,欢迎关注我,谢谢! 
 
[Android取经之路] 的源码都基于Android-Q(10.0) 进行分析 
[Android取经之路] 系列文章: 
《系统启动篇》 
Android...

摘要:本节主要来讲解Android10.0 HIDL相关知识

阅读本文大约需要花费18分钟。

文章首发微信公众号:IngresGe

专注于Android系统级源码分析,Android的平台设计,欢迎关注我,谢谢!

[Android取经之路] 的源码都基于Android-Q(10.0) 进行分析

[Android取经之路] 系列文章:

《系统启动篇》

  1. Android系统架构
  2. Android是怎么启动的
  3. Android 10.0系统启动之init进程
  4. Android10.0系统启动之Zygote进程
  5. Android 10.0 系统启动之SystemServer进程
  6. Android 10.0 系统服务之ActivityMnagerService
  7. Android10.0系统启动之Launcher(桌面)启动流程
  8. Android10.0应用进程创建过程以及Zygote的fork流程
  9. Android 10.0 PackageManagerService(一)工作原理及启动流程
  10. Android 10.0 PackageManagerService(二)权限扫描
  11. Android 10.0 PackageManagerService(三)APK扫描
  12. Android 10.0 PackageManagerService(四)APK安装流程

《日志系统篇》

  1. Android10.0 日志系统分析(一)-logd、logcat 指令说明、分类和属性
  2. Android10.0 日志系统分析(二)-logd、logcat架构分析及日志系统初始化
  3. Android10.0 日志系统分析(三)-logd、logcat读写日志源码分析
  4. Android10.0 日志系统分析(四)-selinux、kernel日志在logd中的实现​

《Binder通信原理》

  1. Android10.0 Binder通信原理(一)Binder、HwBinder、VndBinder概要
  2. Android10.0 Binder通信原理(二)-Binder入门篇
  3. Android10.0 Binder通信原理(三)-ServiceManager篇
  4. Android10.0 Binder通信原理(四)-Native-C\C++实例分析
  5. Android10.0 Binder通信原理(五)-Binder驱动分析
  6. Android10.0 Binder通信原理(六)-Binder数据如何完成定向打击
  7. Android10.0 Binder通信原理(七)-Framework binder示例
  8. Android10.0 Binder通信原理(八)-Framework层分析
  9. Android10.0 Binder通信原理(九)-AIDL Binder示例
  10. Android10.0 Binder通信原理(十)-AIDL原理分析-Proxy-Stub设计模式
  11. Android10.0 Binder通信原理(十一)-Binder总结

  《HwBinder通信原理》

  1. HwBinder入门篇-Android10.0 HwBinder通信原理(一)
  2.  HIDL详解-Android10.0 HwBinder通信原理(二)
  3. HIDL示例-C++服务创建Client验证-Android10.0 HwBinder通信原理(三)
  4. HIDL示例-JAVA服务创建-Client验证-Android10.0 HwBinder通信原理(四)
  5. HwServiceManager篇-Android10.0 HwBinder通信原理(五)
  6. Native层HIDL服务的注册原理-Android10.0 HwBinder通信原理(六)
  7. Native层HIDL服务的获取原理-Android10.0 HwBinder通信原理(七)
  8. JAVA层HIDL服务的注册原理-Android10.0 HwBinder通信原理(八)
  9. JAVA层HIDL服务的获取原理-Android10.0 HwBinder通信原理(九)
  10. HwBinder驱动篇-Android10.0 HwBinder通信原理(十)
  11. HwBinder原理总结-Android10.0 HwBinder通信原理(十一)

 

1.概述

在Android 8.0开始,Android引入了Treble的机制,为了方便Android系统的快速移植、升级,提升系统稳定性,Android引入了HAL Binder的机制,把framework和HAL进行隔离,减少了framework和HAL的耦合性,使得framework部分可以直接被覆盖、更新,而不需要重新对HAL进行编译。

在HAL Binder中,采用的接口定义语言为HIDL。

下图展示了Android 有Treble和没有Treble的升级方式:

HIDL详解-Android10.0 HwBinder通信原理(二)1

 

2.HIDL说明

HIDL 全称为HAL interface definition language(发音为“hide-l”),是用于指定 HAL 和其用户之间的接口的一种接口描述语言 (IDL)。

同AIDL类似,我们只需要为hal定义相关接口,然后通过hidl-gen工具即可自动编译生成对应的 C++或者java源代码,定义hal接口的文档命名为xxx.hal,为了编译这些.hal代码,需要编写相应的Android.bp或者Android.mk。

Android.bp文档用于编译C++

Android.mk文档用于编译Java

从Android10.0 开始,hidl编译去除了Android.mk,统一使用Android.bp 来生成C++和JAVA的中间代码。

 

2.1 绑定式(Binderized)、直通式(Passthrough)

在Android8.0之前,HAL的调用方式为Legacy HAL,HAL 都是编译成 so,然后动态链接到各个 frameworks service 中去。

到Android8.0 时,Android为了给厂商一些修改的时间,同时保持Android的向前兼容性,Android另外设计了一套直通式(Passthrough)的HAL,保留动态库的HAL调用方式,binderservice 链接动态库HAL的实现。

到Android8.0之后,Android规定,厂商新增的HAL都需要切换到绑定式HAL。

HAL的发展历程:

HIDL详解-Android10.0 HwBinder通信原理(二)2

Legacy Hal:Android 8.0 之前版本的 HAL 都是编译成 so,然后动态链接到各个 frameworks service 中去。

Passthrough Hal:该模式是为了兼容旧版的 HAL,旧版 HAL 实现仍以动态库的方式提供,只是 binder service 链接了动态库 HAL 实现,即 binder service 通过 hw_get_module 链接了旧版的 hal 实现,而用户端通过与 binder service IPC 通信,间接实现了与旧版 HAL 的交互。

Binderized HAL:HAL 与 用户调用在不同的进程中,HAL 被写成 binder service,而用户接口如 frameworks 作为 binder client 通过 IPC 机制实现跨进程接口调用。

 

直通式(Passthrough Hal):

这个是由hidl 封装的hal,具体是在hidl封装处dlopen传统的hal(目前8.0上Camera是这种形式)大概形如如下面这个。下面右侧三个子部分都是在同一个进程中。封装层dlopen传统的hal,这样就不用更改太多代码。 

HIDL详解-Android10.0 HwBinder通信原理(二)3

绑定式(Binderized HAL):

这个完全由hidl语言描述,由hidl-gen工具自动生成的hal。此模式下framwework和hal通过进程间binder通信。(camera相关的是/dev/hwbinder节点)。 

Android 8.0 或后续版本的设备都必须只支持绑定式 HAL。 

HIDL详解-Android10.0 HwBinder通信原理(二)4

2.1 HIDL 规范

2.1.1 软件包

软件包名称可以具有子级,如 package.subpackage。已发布的 HIDL 软件包的根目录为 hardware/interfaces 或 vendor/vendorName(例如,对于 Pixel 设备,根目录为 vendor/google)。软件包名称在根目录下形成一个或多个子目录;定义同一个软件包的所有文件都位于同一目录下。例如,您可以在 

hardware/interfaces/example/extension/light/2.0 下找到 

package android.hardware.example.extension.light@2.0。

软件包名称必须采用完全限定名称(FQN)格式(称为:PACKAGE-NAME)。格式如下:

PACKAGE.MODULE[.SUBMODULE[.SUBMODULE[…]]]@VERSION

下表列出了软件包前缀和位置:

软件包前缀

位置

接口类型

android.hardware.*

hardware/interfaces/*

HAL

android.frameworks.*

frameworks/hardware/interfaces/*

frameworks/ 相关

android.system.*

system/hardware/interfaces/*

system/ 相关

android.hidl.*

system/libhidl/transport/*

核心

2.1.2 目录结构

HIDL接口定义目录如下:

Root-dir

├─Module

│  └─Version

│ ├─Android.bp

│ ├─IInterface_1.hal

│ ├─IInterface_2.hal

│ ├─…

│ ├─IInterface_n.hal

│ └─types.hal (可选)

  • Root-dir:

hardware/interfaces 核心HIDL软件包

vendor/VENDOR/interfaces 供应商软件包

  • Module:

描述系统的小写字词。如果多个字词,需使用嵌套式SubModule

  • Version:

版本号,格式:major.minor

  • IInterface_x:

接口名称

例如:

vendor/ingres/interfaces //Root-dir

├─demo //Module

│  └─1.0 //Version

│ └─ITestHal.hal //IInterface_x, hal接口

│ └─types.hal

├─update-all.sh //执行hal-gen的shell脚本

├─Android.bp //hidl编译文件

 

2.1.3 接口定义

除了 types.hal 之外,其他每个 .hal 文件均定义一个接口。接口通常定义如下:

interface IBar extends IFoo { // IFoo is another interface // embedded types struct MyStruct {/*...*/}; // interface methods create(int32_t id) generates (MyStruct s); close();
};

不含显式 extends 声明的接口会从 android.hidl.base@1.0::IBase(类似于 Java 中的 java.lang.Object)隐式扩展。隐式导入的 IBase 接口声明了多种不应也不能在用户定义的接口中重新声明或以其他方式使用的预留方法。这些方法包括:

  • ping

  • interfaceChain

  • interfaceDescriptor

  • notifySyspropsChanged

  • linkToDeath

  • unlinkToDeath

  • setHALInstrumentation

  • getDebugInfo

  • debug

  • getHashChain

 

2.1.4 导入

import 语句是用于访问其他软件包中的软件包接口和类型的 HIDL 机制。

格式如下:

  • 完整软件包导入

import PACKAGE-NAME

  • 部分导入

import PACKAGE-NAME::UDT;(或者,如果导入的类型是在同一个软件包中,则为 import UDT;)。

  • 仅类型导入

import PACKAGE-NAME::types;

如果当前软件包types.hal存在,则自动导入。

在软件包声明之后(在导入之前),添加一个空行。每个导入都应占用一行,且不能缩进。按以下顺序对导入进行分组:

  • android.harder 软件包(使用完全限定名称)

  • vendor.VENDOR软件包(使用完全限定名称)

每个供应商应为一组

按字母顺序对供应商进行排序

  • 源自同一个软件包的其他接口导入(使用简单名称)

在组与组之间添加一行空行。每个组内,按照字母顺序对导入进行排序。

 

 

2.2 HIDL语法

2.2.1 语法

根据设计,HIDL 语言与 C 语言类似(但前者不使用 C 预处理器)。下面未描述的所有标点符号(用途明显的 = 和 | 除外)都是语法的一部分。

  • /** */ 表示文档注释。此样式只能应用于类型、方法、字段和枚举值声明。

  • /* */ 表示多行注释。

  • // 表示注释一直持续到行尾。除 // 之外,换行符与任何其他空格一样。

  • 在以下示例语法中,从 // 到行尾的文本不是语法的一部分,而是对语法的注释。

  • [empty] 表示该字词可能为空。

  • ? 跟在文本或字词后,表示它是可选的。

  • ... 表示包含零个或多个项、使用指定的分隔符号分隔的序列。HIDL 中不含可变参数。

  • 逗号用于分隔序列元素。

  • 分号用于终止各个元素,包括最后的元素。

  • 大写字母是非终止符。

  • italics 是一个令牌系列,如 integer 或 identifier(标准 C 解析规则)。

  • constexpr 是 C 样式的常量表达式(例如 1 + 1 和 1L << 3)。

  • import_name 是软件包或接口名称,按 HIDL 版本编号中所述的方式加以限定。

  • 小写 words 是文本令牌。

 

2.2.2 软件包声明

软件包声明应位于文档顶部,在许可通知之后,应占一整行,并且不应缩进。声明软件包时需采用以下格式(有关名称格式,请参阅软件包名称):

package PACKAGE-NAME;

例如:

package android.hardware.fingerprint@2.1;

package vendor.ingres.demo@1.0;

 

2.2.3 函数声明

函数名称、参数、generates 和返回值应在同一行中(如果放得下)。例如:

interface IDemo { /** ... */ getHelloString(string name) generates (string result);
};

如果一行中放不下,则尝试按相同的缩进量放置参数和返回值,并突出 generate,以便读取器快速看到参数和返回值。

例如:

interface IDemo { anEvenLongerMethodThatCannotFitInOneLine(int32_t theFirstLongParameter, int32_t anotherVeryLongParameter) generates (int32_t theFirstReturnValue, int32_t anotherReturnValue);
}

2.2.4 结构体声明

对于结构体声明,遵循如下规则:

  • 如果与其他软件包共用结构体声明,则将声明放在 types.hal 中,而不是嵌入到接口内。

  • 在结构体类型名称后和左大括号前加空格。

  • 对齐字段名称(可选)。例如:

struct MyStruct { vec   data; int32_t someInt;
}

2.2.5 矢量声明

对于矢量声明,遵循如下规则:

  • vec 和左尖括号。

  • 左尖括号和元素类型(例外情况:元素类型也是 vec)。

  • 元素类型和右尖括号(例外情况:元素类型也是 vec)。

例如:

// Good
vec array;
 
// Good
vec> array;
 
// Good
vec< vec > array;
 
// Bad
vec < int32_t > array;
 
// Bad
vec < vec < int32_t > > array;

2.3 接口HASH

接口HASH是一种旨在防止意外更改接口并确保接口更改经过全面审查的机制。这种机制是必需的,因为 HIDL 接口带有版本编号,也就是说,接口一经发布便不得再更改,但不会影响应用二进制接口 (ABI) 的情况(例如更正备注)除外。

 

2.3.1 布局

每个软件包根目录(即映射到 hardware/interfaces 的 android.hardware 或映射到 vendor/ingres/demo/interfaces 的 vendor.demo)都必须包含一个列出所有已发布 HIDL 接口文件的 current.txt 文件。我们可以在编译时,通过shell脚本调用hidl-gen来生成。

命令如下:

hidl-gen -L hash -r android.hardware:hardware/interfaces -r android.hardware:hardware/interfaces -r android.hidl:system/libhidl/transport android.hardware.demo@1.0  >> ./current.txt

 

 

3. hidl-gen的使用

hidl-gen 编译器会将 .hal 文件编译成一组 .h 和 .cpp 文件,这些自动生成的文件用于编译客户端/服务端实现链接到的共享库,同时也可以生成Android.bp编译文件。

 

3.1 生成的文件

HIDL 软件包中自动生成的文件会关联到与该软件包同名的单个共享库(例如 android.hardware.samples@1.0)。该共享库还会导出单个头文件 IFoo.h,它可以包含在客户端和服务器中。在 Binder 化模式下,使用 hidl-gen 编译器以 IFoo.hal 接口文件作为输入会自动生成以下文件:

HIDL详解-Android10.0 HwBinder通信原理(二)5

3.2 编译工具

hidl-gen 源码路径:system/tool/hidl

版本中默认没有hidl-gen,我们需要先编译生成hidl-gen这个工具:

make -j18 hidl-gen

./build.sh xxx  -m hidl-gen

编译之后会在out 下生成

 

3.3 使用方法

方法:

hidl-gen -o output-path -L language (-r interface-root) fqname

例子:

1.生成Android.bp

hidl-gen -L androidbp -r android.hardware:hardware/interfaces -r android.hidl:system/libhidl/transport android.hardware.demo@1.0

2.生成demo源码

hidl-gen -o hardware/interfaces/demo/1.0/default/ -Lc++-impl -r android.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.demo@1.0

3.生成current.txt文件

hidl-gen -L hash -r android.hardware:hardware/interfaces -r android.hardware:hardware/interfaces -r android.hidl:system/libhidl/transport android.hardware.demo@1.0  >> ./current.txt

参数说明:

  • -L:语言类型,包括c++, c++-headers, c++-sources, export-header, c++-impl, java, java-constants, vts, makefile, androidbp, androidbp-impl, hash等。hidl-gen可根据传入的语言类型产生不同的文件。

  • fqname:完全限定名称的输入文件。比如本例中android.hardware.demo@1.0,要求在源码目录下必须有hardware/interfaces/ gunder /1.0/目录。对于单个文件来说,格式如下:package@version::fileName,比如android.hardware.demo@1.0::types.Feature。对于目录来说。格式如下package@version,比如android.hardware.demo@1.0。

  • -r:格式package:path,可选,对fqname对应的文件来说,用来指定包名和文件所在的目录到Android系统源码根目录的路径。如果没有制定,前缀默认是:android.hardware,目录是Android源码的根目录。

  • -o:存放hidl-gen产生的中间文件的路径。

可以使用hidl-gen 查看帮助,如下图所示:

HIDL详解-Android10.0 HwBinder通信原理(二)6

 

我的微信公众号:IngresGe

HIDL详解-Android10.0 HwBinder通信原理(二)7

勿删,copyright占位
分享文章到微博
分享文章到朋友圈

上一篇:如何使数字指定位数,不足补零

下一篇:【好用的工具】word 和Excel 文件那些事

您可能感兴趣

  • Java 基础之详解 Java 反射机制

    Java 反射机制是 Java 的高级特性之一,是很多框架实现的基础,所以 Java 反射机制是 Java 程序员必须要掌握的重点内容之一。 本场 Chat 将从以下几个方面详解 Java 反射机制: 什么是 Java 的反射机制?Java 反射机制常见方法介绍。Java 反射机制常见用法举例。 使用 Java 反射通过一个对象获取某个类的完整包...

  • XGBOOST原理解析

    1.引言最近,因为一些原因,自己需要做一个小范围的XGBoost的实现层面的分享,于是干脆就整理了一下相关的资料,串接出了这份report,也算跟这里的问题相关,算是从一个更偏算法实现的角度,提供一份参考资料吧。这份report从建模原理、单机实现、分布式实现这几个角度展开。在切入到细节之前,特别提一下,对于有过GBDT算法实现经验的同学(与我有过直...

  • ProGuard代码混淆技术详解

    前言        受《APP研发录》启发,里面讲到一名Android程序员,在工作一段时间后,会感觉到迷茫,想进阶的话接下去是看Android系统源码呢,还是每天继续做应用,毕竟每天都是画UI和利用MobileAPI处理Json还是蛮无聊的,做着重复的事情,没有技术的上提升空间的。所以,根据里面提到的Android应用开发人员所需要精通的...

  • iptables配置详解

    如果你的IPTABLES基础知识还不了解,建议先去看看. 开始配置 我们来配置一个filter表的防火墙. (1)查看本机关于IPTABLES的设置情况 [root@tp ~]# iptables -L -n ...

  • CCNA认证的考试步骤详解

    CISCO公司的职业资格证书CCNA在国外一向都有“通往高薪的直通车”的美誉,虽然在国内由于种种原因,CCNA已经不像前几年一样火爆,但其含金量还是为众多用人单位所重视,可以说,只要你手中有一份CCNA的有效证书(它的有效期为三年),那用人单位肯定会重点考察,成功的机率自然也就高出很多,然而更多的人对于CCNA根本不了解,或者只了...

  • VMware Workstation Pro 15 搭建CentOS虚拟机操作步骤详解

    准备条件: 一.安装好的VMware-workstation-full-15:可去网站https://my.vmware.com/cn/web/vmware/info/slug/desktop_end_user_computing/vmware_workstation_pro/15_0 进行下载安装 二.下载好的光盘映像文件(CentOS-7-...

  • TCP三次握手及原理

      TCP/IP是很多的不同的协议组成,实际上是一个协议组,TCP用户数据报表协议(也称作TCP传输控制协议,Transport Control Protocol。可靠的主机到主机层协议。这里要先强调一下,传输控制协议是OSI网络的第四层的叫法,TCP传输控制协议是TCP/IP传输的6个基本协议的一种。两个TCP意思非相同。...

  • CRC循环校验码原理及计算举例

    循环冗余校验码(CRC),简称循环码,是一种常用的、具有检错、纠错能力的校验码,在早期的通信中运用广泛。通过某种数学运算来建立数据位和校验位的约定关系。这种数学运算就是“模2除法”。这种编码基本思想是将要传送的信息M(...

CSDN

CSDN

中国开发者社区CSDN (Chinese Software Developer Network) 创立于1999年,致力为中国开发者提供知识传播、在线学习、职业发展等全生命周期服务。

华为云40多款云服务产品0元试用活动

免费套餐,马上领取!
HIDL详解-Android10.0 HwBinder通信原理(二)介绍:华为云为您免费提供HIDL详解-Android10.0 HwBinder通信原理(二)在博客、论坛、帮助中心等栏目的相关文章,同时还可以通过 站内搜索 查询更多HIDL详解-Android10.0 HwBinder通信原理(二)的相关内容。| 移动地址: HIDL详解-Android10.0 HwBinder通信原理(二) | 写博客