- 对应的官方文档地址:HIDL(General) - 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 是围绕着接口的概念构建的,接口时面向对象语言中用于定义行为的抽象类型,每个接口都是包的一部分。
1. 包
(Package)
Package names can have sublevels such as
package.subpackage
. The root directory for published HIDL packages ishardware/interfaces
orvendor/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, packageandroid.hardware.example.extension.light@2.0
could be found underhardware/interfaces/example/extension/light/2.0
.
包名中可以包含子包名,比如 package.subpackage
。发布 HIDL 包的根目录是 hardware/interfaces
或者 vendor/vendorName
(比如 vendor/google
是谷歌 Pixel 对应的目录)。根据包名,在根目录下会形成一个或多个子目录。定义包的所有文件都在同一目录中。比如说,package android.hardware.example.extension.light@2.0
对应的路径是 hardware/interfaces/example/extension/light/2.0
。
下表列出了一些包名前缀与位置的对应关系:
包前缀 | 位置 |
---|---|
android.hardware.* | hardware/interfaces/* |
android.frameworks.* | frameworks/hardware/interfaces/* |
android.system.* | system/hardware/interfaces/* |
android.hidl.* | system/libhidl/transport/* |
The package directory contains files with extension
.hal
. Every file must contain apackage
statement naming the package and version the file is part of. The filetypes.hal
, if present, does not define an interface but instead defines data types accessible to every interface in the package.
包目录中包含了扩展名为 .hal
的文件。每个文件都必须包含一个 package
声明,用于命名文件的包和对应版本。如果文件 types.hal
存在,在它内部没有定义任何接口,它只定义了包中的每个接口都可以访问的数据类型。
2. 定义接口
(Interface definition)
Aside from types.hal, every other .hal file defines an interface. For example, 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 fromandroid.hidl.base@1.0::IBase
(similar tojava.lang.Objec
t 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:
ping
interfaceChain
interfaceDescriptor
notifySyspropsChanged
linkToDeath
unlinkToDeath
setHALInstrumentation
getDebugInfo
debug
getHashChain
一个没有显式的 externs
定义的接口,将会隐式地 extends android.hidl.base@1.0::IBase
(就像 Java
中的 java.lang.Object
一样)。这个 IBase
接口将会被隐式地 import
进来,并且它定义了一些基本方法,这些方法在用户自定的接口中不应该,也不能被重定义或者使用其它方法。这些方法包括:
ping
interfaceChain
interfaceDescriptor
notifySyspropsChanged
linkToDeath
unlinkToDeath
setHALInstrumentation
getDebugInfo
debug
getHashChain
3. 导入
(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.
import
语句是用于访问另一个包的接口和类型的 HIDL 机制。一个 import
声明语句关注两个实体:
importing
(执行导入)的实体,它可以是任何一个包或者接口。imported
(被导入)的实体,这也可以是任一包或者接口。
The importing entity is determined by the location of the
import
statement. When the statement is inside a package’stypes.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
声明语句的位置决定。当声明语句是在包的 types.hal
中,则被导入的对于整个包都是可见的。这是一个包级别(package-level
)的导入。当声明语句是在一个接口文件中时,则执行导入的实体则是接口本身,这是接口级别的导入。
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.
- If the value is an UDT defined in
types.hal
, then only that UDT is imported into the importing entity (other types intypes.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
之后的值决定的,这个值不能是全限定名(fully-qualified name)。如果一个组件被忽略,它将会自动填充当前包内的信息。对于全限定名,以下几种导入情况是允许的:
- 全包导入(Whole-package imports):若值是包名以及其版本号,则包被导入到执行导入的实体中。
- 局部导入(Partial imports):
- 如果值是一个接口,则接口与包中的
types.hal
都会被导入到执行导入的实体中。 - 如果值是一个在
types.hal
中的UDT
定义,则只有这个UDT
会被导入到执行导入的实体中,而types.hal
中的其它类型不会被导入。
- 如果值是一个接口,则接口与包中的
- 类型导入(Types-only imports):如果值采用了局部导入的语法,但用关键字
types
替代了接口名,则只有在types.hal
中的UDTs
所指定的包会被导入到执行导入的实体中。
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.
执行导入的实体可以访问的是:
- 定义在被导入包的
types.hal
中的共通的UDTs
。 - 包中的所有接口(对于全包导入)或者包中的一些特定接口(局部导入),为了方便调用它们,需要将句柄给它们,并且(或者)继承它们。
The import statement uses the fully-qualified-type-name syntax to provide the name and version of the package or interface being imported:
import
声明语句使用完全限定类型名称语法提供导入的包或接口的名称和版本:
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
4. 接口继承
(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.
一个接口可以是另一个预先定义的接口的扩展。这个扩展可以是以下三种类型之一:
- 一个接口可以向另一个接口添加功能,合并后 API 不变。
- 一个包可以向另一个包添加功能,合并后 API 不变。
- 接口可以从一个包或者一个特定接口导入其类型。
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 packagederivative
is based on (extends) an interfaceIFoo
in version 1.2 of packageoriginal
, and a version 1.3 of packageoriginal
is created,IBar
version 4.1 cannot extend version 1.3 ofIFoo
. Instead,IBar
version 4.1 must extendIBar
version 4.0, which is tied toIFoo
version 1.2.IBar
version 5.0 could extendIFoo
version 1.3, if desired.
一个接口只可以扩展另一个接口(没有多重扩展)。包内每个从版本号不为零的接口都需要扩展自其前一个版本的接口。比如说,4.0
版本的包 derivative
中有一个接口 IBar
,它扩展了 1.2
版本的包 original
中的接口 IFoo
。此时,如果出现了 original
包的升级版 1.3
版本,则 4.1
版本的 IBar
并不能扩展 1.3
版本的 IFoo
,它必须扩展 4.0
版本的 IBar
(与 1.2
版本的 IFoo
关联)。如果有需要使得 IBar
扩展 1.3
版本的 IFoo
,则要在 5.0
版本的 IBar
进行扩展。
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.
接口的扩展,并不意味着生成的代码中会包含对库的依赖或者跨 HAL 的情况:它们只是在 HIDL 级别中对于数据结构与方法定义进行导入,HAL 层的每个方法都需要实现在它对应的 HAL 中。
5. 供应商的扩展
(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 名称和版本下注册。
6. 版本化
(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 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.
包是版本化的,而接口则有对应其包的版本。版本用两个整数表示,即主版本号与从版本号:
- 主版本号:主版本是不向后兼容的,当主版本号增加的时候,从版本号要重置为 0。
- 从版本号:从版本向后兼容。增加从版本号表明新的版本是向后兼容从前的版本的。可以增加新的数据结构与方法,但已有的数据结构与方法签名不能被改变。
For broader compatibility with frameworks, multiple major versions of a HAL can be present on a device simultaneously. While multiple minor versions can also be present on a device, as minor versions are backwards compatible no reason exists to support more than the latest minor version for each major version.
For more details on versioning and vendor extensions, see HIDL Versioning.
为了更广泛地兼容框架部分,一个 HAL 的多个主版本可以同时存在于同一个设备上。虽然多个从版本也可以存在于同一设备上,但是由于其向后兼容,所以不需要对每个主版本都支持其最新的从版本。
关于版本化与供应商扩展的更详细的信息,可以参看 HIDL Versioning。