Android_Architecture_HIDL(General)--Overview

说明:转载自官方英文+中文版https://source.android.com/devices/architecture/hidl


HIDL

HAL interface definition language or HIDL (pronounced “hide-l”) is an interface description language (IDL) to specify the interface between a HAL and its users. It allows specifying types and method calls, collected into interfaces and packages. More broadly, HIDL is a system for communicating between codebases that may be compiled independently.

HIDL is intended to be used for inter-process communication (IPC). Communication between processes is referred to as Binderized. For libraries that must be linked to a process, a passthrough mode is also available (not supported in Java).

HIDL specifies data structures and method signatures, organized in interfaces (similar to a class) that are collected into packages. The syntax of HIDL will look familiar to C++ and Java programmers, though with a different set of keywords. HIDL also uses Java-style annotations.

HAL 接口定义语言(简称 HIDL,发音为“hide-l”)是用于指定 HAL 和其用户之间的接口的一种接口描述语言 (IDL)。HIDL 允许指定类型和方法调用(会汇集到接口和软件包中)。从更广泛的意义上来说,HIDL 是用于在可以独立编译的代码库之间进行通信的系统。

HIDL 旨在用于进程间通信 (IPC)。进程之间的通信经过 Binder 化。对于必须与进程相关联的代码库,还可以使用直通模式(在 Java 中不受支持)。

HIDL 可指定数据结构和方法签名,这些内容会整理归类到接口(与类相似)中,而接口会汇集到软件包中。尽管 HIDL 具有一系列不同的关键字,但 C++ 和 Java 程序员对 HIDL 的语法并不陌生。此外,HIDL 还使用 Java 样式的注释。

HIDL design(HIDL 设计)


The goal of HIDL is that the framework can be replaced without having to rebuild HALs. HALs will be built by vendors or SOC makers and put in a /vendor partition on the device, enabling the framework, in its own partition, to be replaced with an OTA without recompiling the HALs.

HIDL 的目标是,框架可以在无需重新构建 HAL 的情况下进行替换。HAL 将由供应商或 SOC 制造商构建,放置在设备的 /vendor 分区中,这样一来,框架就可以在其自己的分区中通过 OTA 进行替换,而无需重新编译 HAL。

HIDL design balances the following concerns:

  • Interoperability. Create reliably interoperable interfaces between processes which may be compiled with various architectures, toolchains, and build configurations. HIDL interfaces are versioned and cannot be changed after they are published.

  • Efficiency. HIDL tries to minimize the number of copy operations. HIDL-defined data is delivered to C++ code in C++ standard layout data structures that can be used without unpacking. HIDL also provides shared memory interfaces and, as RPCs are inherently somewhat slow, HIDL supports two ways to transfer data without using an RPC call: shared memory and a Fast Message Queue (FMQ).

  • Intuitive. HIDL avoids thorny issues of memory ownership by using only in parameters for RPC (see Android Interface Definition Language (AIDL); values that cannot be efficiently returned from methods are returned via callback functions. Neither passing data into HIDL for transfer nor receiving data from HIDL changes the ownership of the data—ownership always remains with the calling function. Data needs to persist only for the duration of the called function and may be destroyed immediately after the called function returns.

HIDL 设计在以下方面之间保持了平衡:

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

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

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

Using passthrough mode(使用直通模式)


To update devices running earlier versions of Android to Android O, you can wrap both conventional (and legacy) HALs in a new HIDL interface that serves the HAL in binderized and same-process (passthrough) modes. This wrapping is transparent to both the HAL and the Android framework.

Passthrough mode is available only for C++ clients and implementations. Devices running earlier versions of Android do not have HALs written in Java, so Java HALs are inherently binderized.

要将运行早期版本的 Android 的设备更新为使用 Android O,您可以将惯用的(和旧版)HAL 封装在一个新 HIDL 接口中,该接口将在绑定式模式和同进程(直通)模式提供 HAL。这种封装对于 HAL 和 Android 框架来说都是透明的。

直通模式仅适用于 C++ 客户端和实现。运行早期版本的 Android 的设备没有用 Java 编写的 HAL,因此 Java HAL 自然而然经过 Binder 化。

Passthrough header files(直通式标头文件)

When a .hal file is compiled, hidl-gen produces an extra passthrough header file BsFoo.h in addition to the headers used for binder communication; this header defines functions to be dlopened. As passthrough HALs run in the same process in which they are called, in most cases passthrough methods are invoked by direct function call (same thread). oneway methods run in their own thread as they are not intended to wait for the HAL to process them (this means any HAL that uses oneway methods in passthrough mode must be thread-safe).

Given an IFoo.hal, BsFoo.h wraps the HIDL-generated methods to provide additional features (such as making oneway transactions run in another thread). This file is similar to BpFoo.h, however instead of passing on calls IPC using binder, the desired functions are directly invoked. Future implementations of HALs may provide multiple implementations, such as FooFast HAL and a FooAccurate HAL. In such cases, a file for each additional implementation would be created (e.g., PTFooFast.cpp and PTFooAccurate.cpp).

编译 .hal 文件时,除了用于 Binder 通信的标头之外,hidl-gen 还会生成一个额外的直通标头文件 BsFoo.h;此标头定义了会被执行 dlopen 操作的函数。由于直通式 HAL 在它们被调用的同一进程中运行,因此在大多数情况下,直通方法由直接函数调用(同一线程)来调用。oneway 方法在各自的线程中运行,因为它们不需要等待 HAL 来处理它们(这意味着,在直通模式下使用 oneway 方法的所有 HAL 对于线程必须是安全的)。

如果有一个 IFoo.halBsFoo.h 会封装 HIDL 生成的方法,以提供额外的功能(例如使 oneway 事务在其他线程中运行)。该文件类似于 BpFoo.h,不过,所需函数是直接调用的,并未使用 Binder 传递调用 IPC。未来,HAL 的实现可能提供多种实现结果,例如 FooFast HAL 和 FooAccurate HAL。在这种情况下,系统会针对每个额外的实现结果创建一个文件(例如 PTFooFast.cppPTFooAccurate.cpp)。

Binderizing passthrough HALs(Binder 化直通式 HAL)

You can binderize HAL implementations that support passthrough mode. Given a HAL interface [email protected]::IFoo, two packages are created:

  • [email protected]::IFoo-impl. Contains the implementation of the HAL and exposes function IFoo* HIDL_FETCH_IFoo(const char* name). On legacy devices, this package is dlopened and the implementation is instantiated using HIDL_FETCH_IFoo. You can generate the base code using hidl-gen and -Lc++-impl and -Landroidbp-impl.
  • [email protected]::IFoo-service. Opens the passthrough HAL and registers itself as a binderized service, enabling the same HAL implementation to be used as both passthrough and binderized.


Given the type IFoo, you can call sp<IFoo> IFoo::getService(string name, bool getStub) to get access to an instance of IFoo. If getStub is true, getService attempts to open the HAL only in passthrough mode. If getStub is false, getService attempts to find a binderized service; if that fails, it then tries to find the passthrough service. The getStub parameter should never be used except in defaultPassthroughServiceImplementation. (Devices launching with Android O are fully binderized devices, so opening a service in passthrough mode is disallowed.)

您可以将支持直通模式的 HAL 实现 Binder 化。如果有一个 HAL 接口 [email protected]::IFoo,系统会创建两个软件包:

  • [email protected]::IFoo-impl。包含 HAL 的实现,并暴露函数 IFoo* HIDL_FETCH_IFoo(const char* name)。在旧版设备上,此软件包经过 dlopen 处理,且实现使用 HIDL_FETCH_IFoo 进行了实例化。您可以使用 hidl-gen-Lc++-impl 以及 -Landroidbp-impl 来生成基础代码。
  • [email protected]::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 grammar(HIDL 语法)


By design, the HIDL language is similar to C (but does not use the C preprocessor). All punctuation not described below (aside from the obvious use of = and |) is part of the grammar.

Note: For details on HIDL code style, see the Code Style Guide.

  • /** */ indicates a documentation comment. These can be applied only to type, method, field, and enum value declarations.
  • /* */ indicates a multiline comment.
  • // indicates a comment to end of line. Aside from //, newlines are the same as any other whitespace.
  • In the example grammar below, text from // to the end of the line is not part of the grammar but is instead a comment on the grammar.
  • [empty] means that the term may be empty.
  • ? following a literal or term means it is optional.
  • ... indicates sequence containing zero or more items with separating punctuation as indicated. There are no variadic arguments in HIDL.
  • Commas separate sequence elements.
  • Semicolons terminate each element, including the last element.
  • UPPERCASE is a nonterminal.
  • italics is a token family such as integer or identifier (standard C parsing rules).
  • constexpr is a C style constant expression (such as 1 + 1 and 1L << 3).
  • import_name is a package or interface name, qualified as described in HIDL Versioning.
  • Lowercase words are literal tokens.

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

注意:有关 HIDL 代码样式的详细信息,请参阅代码样式指南

  • /** */ 表示文档注释。此样式只能应用于类型、方法、字段和枚举值声明。
  • /* */ 表示多行注释。
  • // 表示注释一直持续到行结束。除了 //,换行符与任何其他空白一样。
  • 在以下示例语法中,从 // 到行结束的文本不是语法的一部分,而是对语法的注释。
  • [empty] 表示该字词可能为空。
  • ? 跟在文本或字词后,表示它是可选的。
  • ... 表示包含零个或多个项、用指定的分隔符号分隔的序列。HIDL 中不含可变参数
  • 逗号用于分隔序列元素。
  • 分号用于终止各个元素,包括最后的元素。
  • 大写字母是非终止符。
  • italics 是一个令牌系列,如 integeridentifier(标准 C 解析规则)。
  • constexpr 是 C 样式的常量表达式(例如 1 + 11L << 3)。
  • import_name 是软件包或接口名称,按 HIDL 版本编号中所述的方式加以限定。
  • 小写 words 是文本令牌。

Example:

ROOT =
    PACKAGE IMPORTS PREAMBLE { ITEM ITEM ... }  // not for types.hal
  | PACKAGE IMPORTS ITEM ITEM...  // only for types.hal; no method definitions

ITEM =
    ANNOTATIONS? oneway? identifier(FIELD, FIELD ...) GENERATES?;
  |  safe_union identifier { UFIELD; UFIELD; ...};
  |  struct identifier { SFIELD; SFIELD; ...};  // Note - no forward declarations
  |  union identifier { UFIELD; UFIELD; ...};
  |  enum identifier: TYPE { ENUM_ENTRY, ENUM_ENTRY ... }; // TYPE = enum or scalar
  |  typedef TYPE identifier;

VERSION = integer.integer;

PACKAGE = package android.hardware.identifier[.identifier[...]]@VERSION;

PREAMBLE = interface identifier EXTENDS

EXTENDS = <empty> | extends import_name  // must be interface, not package

GENERATES = generates (FIELD, FIELD ...)

// allows the Binder interface to be used as a type
// (similar to typedef'ing the final identifier)
IMPORTS =
   [empty]
  |  IMPORTS import import_name;

TYPE =
  uint8_t | int8_t | uint16_t | int16_t | uint32_t | int32_t | uint64_t | int64_t |
 float | double | bool | string
|  identifier  // must be defined as a typedef, struct, union, enum or import
               // including those defined later in the file
|  memory
|  pointer
|  vec<TYPE>
|  bitfield<TYPE>  // TYPE is user-defined enum
|  fmq_sync<TYPE>
|  fmq_unsync<TYPE>
|  TYPE[SIZE]

FIELD =
   TYPE identifier

UFIELD =
   TYPE identifier
  |  safe_union identifier { FIELD; FIELD; ...} identifier;
  |  struct identifier { FIELD; FIELD; ...} identifier;
  |  union identifier { FIELD; FIELD; ...} identifier;

SFIELD =
   TYPE identifier
  |  safe_union identifier { FIELD; FIELD; ...};
  |  struct identifier { FIELD; FIELD; ...};
  |  union identifier { FIELD; FIELD; ...};
  |  safe_union identifier { FIELD; FIELD; ...} identifier;
  |  struct identifier { FIELD; FIELD; ...} identifier;
  |  union identifier { FIELD; FIELD; ...} identifier;

SIZE =  // Must be greater than zero
     constexpr

ANNOTATIONS =
     [empty]
  |  ANNOTATIONS ANNOTATION

ANNOTATION =
  |  @identifier
  |  @identifier(VALUE)
  |  @identifier(ANNO_ENTRY, ANNO_ENTRY  ...)

ANNO_ENTRY =
     identifier=VALUE

VALUE =
     "any text including \" and other escapes"
  |  constexpr
  |  {VALUE, VALUE ...}  // only in annotations

ENUM_ENTRY =
     identifier
  |  identifier = constexpr

Terminology(术语)


This section uses the following HIDL-related terms:

binderized Binder 化 Indicates HIDL is being used for remote procedure calls between processes, implemented over a Binder-like mechanism. See also passthrough.  表示 HIDL 用于进程之间的远程过程调用,并通过类似 Binder 的机制来实现。另请参阅“直通式”。
callback, asynchronous 异步回调 Interface served by a HAL user, passed to the HAL (via a HIDL method), and called by the HAL to return data at any time.  由 HAL 用户提供、传递给 HAL(通过 HIDL 方法)并由 HAL 调用以随时返回数据的接口。
callback, synchronous 同步回调 Returns data from a server’s HIDL method implementation to the client. Unused for methods that return void or a single primitive value.  将数据从服务器的 HIDL 方法实现返回到客户端。不用于返回无效值或单个原始值的方法。
client 客户端 Process that calls methods of a particular interface. A HAL or framework process may be a client of one interface and a server of another. See also passthrough.  调用特定接口的方法的进程。HAL 进程或框架进程可以是一个接口的客户端和另一个接口的服务器。另请参阅“直通式”。
extends 扩展 Indicates an interface that adds methods and/or types to another interface. An interface can extend only one other interface. Can be used for a minor version increment in the same package name or for a new package (e.g. a vendor extension) to build on an older package.  表示向另一接口添加方法和/或类型的接口。一个接口只能扩展另一个接口。可用于具有相同软件包名称的 Minor 版本递增,也可用于在旧软件包的基础上构建的新软件包(例如,供应商扩展)。
generates 生成 Indicates an interface method that returns values to the client. To return one non-primitive value, or more than one value, a synchronous callback function is generated.  表示将值返回给客户端的接口方法。要返回一个非原始值或多个值,则会生成同步回调函数。
interface 接口 Collection of methods and types. Translated into a class in C++ or Java. All methods in an interface are called in the same direction: a client process invokes methods implemented by a server process.  方法和类型的集合。会转换为 C++ 或 Java 中的类。接口中的所有方法均按同一方向调用:客户端进程会调用由服务器进程实现的方法。
oneway 单向 When applied to a HIDL method, indicates the method returns no values and does not block.  应用到 HIDL 方法时,表示该方法既不返回任何值也不会造成阻塞。
package 软件包 Collection of interfaces and data types sharing a version.  共用一个版本的接口和数据类型的集合。
passthrough 直通式 Mode of HIDL in which the server is a shared library, dlopened by the client. In passthrough mode, client and server are the same process but separate codebases. Used only to bring legacy codebases into the HIDL model. See also Binderized.  HIDL 的一种模式,使用这种模式时,服务器是共享库,由客户端进行 dlopen 处理。在直通模式下,客户端和服务器是相同的进程,但代码库不同。此模式仅用于将旧版代码库并入 HIDL 模型。另请参阅“Binder 化”。
server 服务器 Process that implements methods of an interface. See also passthrough.  实现接口的方法的进程。另请参阅“直通式”。
transport 传输 HIDL infrastructure that moves data between the server and client.  在服务器和客户端之间移动数据的 HIDL 基础架构。
version 版本 Version of a package. Consists of two integers, major and minor. Minor version increments may add (but not change) types and methods.  软件包的版本。由两个整数组成:Major 版本和 Minor 版本。Minor 版本递增可以添加(但不会更改)类型和方法。
发布了60 篇原创文章 · 获赞 27 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/xiaosaerjt/article/details/104540578
今日推荐