Android_Architecture_HIDL(General)--Interfaces & Packages(接口和软件包)

丘飞
2023-12-01

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


Interfaces & Packages(接口和软件包)

HIDL is built around interfaces, an abstract type used in object-oriented languages to define behaviors. Each interface is part of a package.

HIDL 是围绕接口进行编译的,接口是面向对象的语言使用的一种用来定义行为的抽象类型。每个接口都是软件包的一部分。

Packages(软件包)


Package names can have sublevels such as package.subpackage. The root directory for published HIDL packages is hardware/interfaces or vendor/vendorName (e.g. vendor/google for Pixel devices). The package name forms one or more subdirectories under the root directory; all files defining a package are in the same directory. For example, package android.hardware.example.extension.light@2.0 could be found under hardware/interfaces/example/extension/light/2.0.

The following table lists package prefixes and locations:

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

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

Package PrefixLocationInterface Types
android.hardware.*hardware/interfaces/*HAL
android.frameworks.*frameworks/hardware/interfaces/*frameworks/ related
android.system.*system/hardware/interfaces/*system/ related
android.hidl.*system/libhidl/transport/*core

The package directory contains files with extension .hal. Every file must contain a package statement naming the package and version the file is part of. The file types.hal, if present, does not define an interface but instead defines data types accessible to every interface in the package.

软件包目录中包含扩展名为 .hal 的文件。每个文件均必须包含一个指定文件所属的软件包和版本的 package 语句。文件 types.hal(如果存在)并不定义接口,而是定义软件包中每个接口可以访问的数据类型。

Interface definition(接口定义)


Aside from types.hal, every other .hal file defines an interface. An interface is typically defined as follows:

除了 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();
};

An interface without an explicit extends declaration implicitly extends from android.hidl.base@1.0::IBase (similar to java.lang.Object in Java.) The IBase interface, implicitly imported, declares several reserved methods that should not and cannot be redeclared in user-defined interfaces or used otherwise. These methods include:

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

  • ping
  • interfaceChain
  • interfaceDescriptor
  • notifySyspropsChanged
  • linkToDeath
  • unlinkToDeath
  • setHALInstrumentation
  • getDebugInfo
  • debug
  • getHashChain

Importing(导入)


The import statement is HIDL mechanism to access package interfaces and types in another package. An import statement concerns itself with two entities:

  • The importing entity, which can be either a package or an interface; and
  • The imported entity, which too can be either a package or an interface.


The importing entity is determined by the location of the import statement. When the statement is inside a package’s types.hal, what is being imported is visible by the entire package; this is a package-level import. When the statement is inside an interface file, the importing entity is the interface itself; this is an interface-level import.

import 语句是用于访问其他软件包中的软件包接口和类型的 HIDL 机制。import 语句本身涉及两个实体:

  • 导入实体:可以是软件包或接口;以及
  • 被导入实体:也可以是软件包或接口。

导入实体由 import 语句的位置决定。当该语句位于软件包的 types.hal 中时,导入的内容对整个软件包是可见的;这是软件包级导入。当该语句位于接口文件中时,导入实体是接口本身;这是接口级导入。

The imported entity is determined by the value after the import keyword. The value need not be a fully-qualified name; if a component is omitted, it is automatically filled with information from the current package. For fully-qualified values, the following import cases are supported:

  • Whole-package imports. If the value is a package name and a version (syntax described below), then the entire package is imported into the importing entity.
  • Partial imports. If the value is:
    - An interface, the package’s types.hal and that interface are imported into the importing entity.
    - A UDT defined in types.hal, then only that UDT is imported into the importing entity (other types in types.hal are not imported).
  • Types-only imports. If the value uses the syntax of a partial import described above, but with the keyword types instead of an Interface name, only the UDTs in types.hal of the designated package are imported.

被导入实体由 import 关键字后面的值决定。该值不必是完全限定名称;如果某个组成部分被删除了,系统会自动使用当前软件包中的信息填充该组成部分。 对于完全限定值,支持的导入情形有以下几种:

  • 完整软件包导入。如果该值是一个软件包名称和版本(语法见下文),则系统会将整个软件包导入至导入实体中。
  • 部分导入。如果值为:
      1) 一个接口,则系统会将该软件包的 types.hal 和该接口导入至导入实体中。
      2) 在 types.hal 中定义的 UDT,则系统仅会将该 UDT 导入至导入实体中(不导入 types.hal 中的其他类型)。
  • 仅类型导入。如果该值将上文所述的“部分导入”的语法与关键字 types 而不是接口名称配合使用,则系统仅会导入指定软件包的 types.hal 中的 UDT。

The importing entity gets access to a combination of:

  • The imported package’s common UDTs defined in types.hal;
  • The imported package’s interfaces (for a whole-package import) or specified interface (for a partial import) for the purposes of invoking them, passing handles to them and/or inheriting from them.

The import statement uses the fully-qualified-type-name syntax to provide the name and version of the package or interface being imported:

导入实体可以访问以下各项的组合:

  • types.hal 中定义的被导入软件包的常见 UDT;
  • 被导入的软件包的接口(完整软件包导入)或指定接口(部分导入),以便调用它们、向其传递句柄和/或从其继承句柄。

导入语句使用完全限定类型名称语法来提供被导入的软件包或接口的名称和版本:

import android.hardware.nfc@1.0;            // import a whole package
import android.hardware.example@1.0::IQuux; // import an interface and types.hal
import android.hardware.example@1.0::types; // import just types.hal

Interface inheritance(接口继承)


An interface can be an extension of a previously-defined interface. Extensions can be one of the following three types:

  • Interface can add functionality to another one, incorporating its API unchanged.
  • Package can add functionality to another one, incorporating its API unchanged.
  • Interface can import types from a package or from a specific interface.


An interface can extend only one other interface (no multiple inheritance). Each interface in a package with a non-zero minor version number must extend an interface in the previous version of the package. For example, if an interface IBar in version 4.0 of package derivative is based on (extends) an interface IFoo in version 1.2 of package original, and a version 1.3 of package original is created, IBar version 4.1 cannot extend version 1.3 of IFoo. Instead, IBar version 4.1 must extend IBar version 4.0, which is tied to IFoo version 1.2. IBarversion 5.0 could extend IFoo version 1.3, if desired.

Interface extensions do not imply library dependence or cross-HAL inclusion in the generated code—they simply import the data structure and method definitions at the HIDL level. Every method in a HAL must be implemented in that HAL.

接口可以是之前定义的接口的扩展。扩展可以是以下三种类型中的一种:

  • 接口可以向其他接口添加功能,并按原样纳入其 API。
  • 软件包可以向其他软件包添加功能,并按原样纳入其 API。
  • 接口可以从软件包或特定接口导入类型。

接口只能扩展一个其他接口(不支持多重继承)。具有非零 Minor 版本号的软件包中的每个接口必须扩展一个以前版本的软件包中的接口。例如,如果 4.0 版本的软件包 derivative 中的接口 IBar 是基于(扩展了)1.2 版本的软件包 original 中的接口 IFoo,并且您又创建了 1.3 版本的软件包 original,则 4.1 版本的 IBar 不能扩展 1.3 版本的 IFoo。相反,4.1 版本的 IBar 必须扩展 4.0 版本的 IBar,因为后者是与 1.2 版本的 IFoo 绑定的。 如果需要,5.0 版本的 IBar 可以扩展 1.3 版本的 IFoo

接口扩展并不意味着生成的代码中存在代码库依赖关系或跨 HAL 包含关系,接口扩展只是在 HIDL 级别导入数据结构和方法定义。HAL 中的每个方法必须在相应 HAL 中实现。

Vendor extensions(供应商扩展)


In some cases, vendor extensions will be implemented as a subclass of the base object that represents the core interface they extend. The same object will be registered under the base HAL name and version, and under the extension’s (vendor) HAL name and version.

在某些情况下,供应商扩展会作为以下基础对象的子类予以实现:代表其扩展的核心接口的基础对象。同一对象会同时在基础 HAL 名称和版本下,以及扩展的(供应商)HAL 名称和版本下注册。

Versioning(版本编号)


Packages are versioned, and interfaces have the version of their package. Versions are expressed in two integers, major.minor.

  • Major versions are not backwards compatible. Incrementing the major version number resets the minor version number to 0.
  • Minor versions are backwards compatible. Incrementing the minor number indicates the newer version is fully backward compatible with the previous version. New data structures and methods can be added, but no existing data structures or method signatures may be changed.


Multiple major or minor versions of a HAL can be present on a device simultaneously. However, a minor version should be preferred over a major version because client code that works with a previous minor version interface will also work with later minor versions of that same interface. For more details on versioning and vendor extensions, see HIDL Versioning.

软件包分版本,且接口的版本和其软件包的版本相同。版本用两个整数表示:major.minor。

  • Major 版本不向后兼容。递增 Major 版本号将会使 Minor 版本号重置为 0。
  • Minor 版本向后兼容。如果递增 Minor 版本号,则意味着较新版本完全向后兼容之前的版本。您可以添加新的数据结构和方法,但不能更改现有的数据结构或方法签名。

可同时在一台设备上提供 HAL 的多个 Major 或 Minor 版本。不过,Minor 版本应优先于 Major 版本,因为与之前的 Minor 版本接口一起使用的客户端代码也适用于同一接口的后续 Minor 版本。有关版本控制和供应商扩展的更多详细信息,请参阅 HIDL 版本控制

Interface layout summary(接口布局总结)


This section summarizes how to manage a HIDL interface package (such as hardware/interfaces) and consolidates information presented throughout the HIDL section. Before reading, ensure you are familiar with HIDL Versioning, the hashing concepts in Hashing with hidl-gen, the details of working with HIDL in general, and the following definitions:

TermDefinition
Application Binary Interface (ABI)Application programming interface + any binary linkages required.
Fully-qualified name (fqName)Name to distinguish a hidl type. Example: android.hardware.foo@1.0::IFoo.
PackagePackage containing a HIDL interface and types. Example: android.hardware.foo@1.0.
Package rootRoot package that contains the HIDL interfaces. Example: the HIDL interface android.hardware is in the package root android.hardware.foo@1.0.
Package root pathLocation in the Android source tree where a package root maps to.


For more definitions, see HIDL Terminology.

本部分总结了如何管理 HIDL 接口软件包(如 hardware/interfaces)并整合了整个 HIDL 部分提供的信息。在阅读之前,请务必先熟悉 HIDL 版本控制使用 hidl-gen 添加哈希中的哈希概念、关于在一般情况下使用 HIDL 的详细信息以及以下定义:

术语定义
应用二进制接口 (ABI)应用编程接口 + 所需的任何二进制链接。
完全限定名称用于区分 hidl 类型的名称。例如:android.hardware.foo@1.0::IFoo
软件包包含 HIDL 接口和类型的软件包。例如:android.hardware.foo@1.0
软件包根目录包含 HIDL 接口的根目录软件包。例如:HIDL 接口 android.hardware 在软件包根目录 android.hardware.foo@1.0 中。
软件包根目录路径软件包根目录映射到的 Android 源代码树中的位置。

有关更多定义,请参阅 HIDL 术语

  • Every file can be found from the package root mapping and its fully-qualified name


Package roots are specified to hidl-gen as the argument -r android.hardware:hardware/interfaces. For example, if the package is vendor.awesome.foo@1.0::IFoo and hidl-gen is sent -r vendor.awesome:some/device/independent/path/interfaces, then the interface file should be located in $ANDROID_BUILD_TOP/some/device/independent/path/interfaces/foo/1.0/IFoo.hal.


In practice, it is recommended for a vendor or OEM named awesome to put their standard interfaces in vendor.awesome. After a package path has been selected, it must not be changed as this is baked into the ABI of the interface.

每个文件都可以通过软件包根目录映射及其完全限定名称找到

软件包根目录以参数 -r android.hardware:hardware/interfaces 的形式指定给 hidl-gen。例如,如果软件包为 vendor.awesome.foo@1.0::IFoo 并且向 hidl-gen 发送了 -r vendor.awesome:some/device/independent/path/interfaces,那么接口文件应该位于 $ANDROID_BUILD_TOP/some/device/independent/path/interfaces/foo/1.0/IFoo.hal

在实践中,建议称为 awesome 的供应商或原始设备制造商 (OEM) 将其标准接口放在 vendor.awesome 中。在选择了软件包路径之后,不能再更改该路径,因为它已写入接口的 ABI。

  • Package path mapping should be unique


For example, if you have -rsome.package:$PATH_A and -rsome.package:$PATH_B, $PATH_A must be equal to $PATH_B for a consistent interface directory (this also makes versioning interfaces much easier).

  • Package root must have a versioning file


If you create a package path such as -r vendor.awesome:vendor/awesome/interfaces, you should also create the file $ANDROID_BUILD_TOP/vendor/awesome/interfaces/current.txt, which should contain hashes of interfaces made using the -Lhash option in hidl-gen (this is discussed extensively in Hashing with hidl-gen).


Caution: Manage all changes carefully! The Vendor Test Suite (VTS) will fail if an interface is not frozen, and ABI-incompatible changes to an interface will cause framework-only OTAs to fail.

  • Interfaces go in device-independent locations


In practice, it is recommended to share interfaces between branches. This allows for maximum code re-usage and maximum testing of code across different devices and use cases.

软件包路径映射不得重复

例如,如果您有 -rsome.package:$PATH_A-rsome.package:$PATH_B,则 $PATH_A 必须等于 $PATH_B 才能实现一致的接口目录(这也能让接口版本控制起来更简单)。

软件包根目录必须有版本控制文件

如果您创建一个软件包路径(如 -r vendor.awesome:vendor/awesome/interfaces),则还应创建文件 $ANDROID_BUILD_TOP/vendor/awesome/interfaces/current.txt,该文件应包含使用 hidl-gen(在使用 hidl-gen 添加哈希中广泛进行了讨论)中的 -Lhash 选项所创建接口的哈希。

注意:请谨慎管理所有更改!如果接口未冻结,则供应商测试套件 (VTS) 将失败,并且对接口进行的与 ABI 不兼容的更改将导致仅限框架的 OTA 失败。

接口位于设备无关的位置

在实践中,建议在分支之间共享接口。这样可以最大限度地重复使用代码,并在不同的设备和用例中对代码进行最大程度的测试。

 类似资料: