https://source.android.com/devices/architecture/hidl-java
HIDL Java
Android O 对 Android 操作系统的架构重新进行了设计,以在独立于设备的 Android 平台与特定于设备和供应商的代码之间定义清晰的接口。 Android 已经以 HAL 接口的形式(在 hardware/libhardware
中定义为 C 标头)定义了许多此类接口。HIDL 将这些 HAL 接口替换为稳定的带版本接口,可以采用 Java(如下所述),也可以是采用 C++ 的客户端和服务器端 HIDL 接口。
HIDL 接口主要通过本机代码使用,因此 HIDL 专注于自动生成高效的 C++ 代码。不过,HIDL 接口也必须能够直接通过 Java 使用,因为有些 Android 子系统(如 Telephony)很可能具有 Java HIDL 接口。
本部分介绍了 HIDL 接口的 Java 前端,详细说明了如何创建、注册和使用服务,以及使用 Java 编写的 HAL 和 HAL 客户端如何与 HIDL RPC 系统进行交互。
作为客户端
要访问软件包 android.hardware.foo
版本 1.0 中服务名称注册为 foo-bar
的接口 IFoo,请执行以下操作:
- 添加库:
- 将以下内容添加到 Android.mk 中:
LOCAL_STATIC_JAVA_LIBRARIES += android.hardware.foo-V1.0-java 或
- 将以下内容添加到 Android.bp 中:
static_libs: [ /* … */ "android.hardware.foo-V1.0-java", ],
- 将以下内容添加到 Android.mk 中:
- 将以下内容添加到您的 Java 文件中:
import android.hardware.foo.V1_0.IFoo; ... // retry to wait until the service starts up if it is in the manifest IFoo server = IFoo.getService(true /* retry */); // throws NoSuchElementException if not available IFoo anotherServer = IFoo.getService("second_impl", true /* retry */); server.doSomething(…);
警告:不含参数的 Java
getService
将不会等待服务启动。
提供服务
Java 中的框架代码可能需要提供接口才能接收来自 HAL 的异步回调。
警告:请勿用 Java 实现驱动程序 (HAL)。我们强烈建议您用 C++ 实现驱动程序。
警告:Java 驱动程序必须与其客户端处于不同的进程中(不支持同一进程通信)。
对于 1.0 版软件包 android.hardware.foo
中的接口 IFooCallback
,您可以按照以下步骤用 Java 实现接口。
- 用 HIDL 定义您的接口。
- 打开
/tmp/android/hardware/foo/IFooCallback.java
作为参考。 - 为您的 Java 实现创建一个新模块。
- 检查抽象类
android.hardware.foo.V1_0.IFooCallback.Stub
,然后编写一个新类以对其进行扩展,并实现抽象方法。
查看自动生成的文件
要查看自动生成的文件,请运行以下命令:
hidl-gen -o /tmp -Ljava \ -randroid.hardware:hardware/interfaces \ -randroid.hidl:system/libhidl/transport android.hardware.foo@1.0
这些命令会生成目录 /tmp/android/hardware/foo/1.0
。对于文件 hardware/interfaces/foo/1.0/IFooCallback.hal
,这会生成文件 /tmp/android/hardware/foo/1.0/IFooCallback.java
,其中包含 Java 接口、代理代码和存根(代理和存根均与接口吻合)。
-Lmakefile
会生成在构建时运行此命令的规则,并允许您包含 android.hardware.foo-V1.0-java
并链接到相应的文件。您可以在 hardware/interfaces/update-makefiles.sh
中找到自动为充满接口的项目执行此操作的脚本。 本示例中的路径是相对路径;硬件/接口可能是代码树下的一个临时目录,让您能够先开发 HAL 然后再进行发布。
运行服务
HAL 提供了一个接口 IFoo
,它必须通过接口 IFooCallback
对框架进行异步回调。IFooCallback
接口不按名称注册为可检测到的服务;相反,IFoo
必须包含一个诸如 setFooCallback(IFooCallback x)
的方法。
要通过软件包 android.hardware.foo
版本 1.0 设置 IFooCallback
,请将 android.hardware.foo-V1.0-java
添加到 Android.mk
中。运行服务的代码为:
import android.hardware.foo.V1_0.IFoo; import android.hardware.foo.V1_0.IFooCallback.Stub; .... class FooCallback extends IFooCallback.Stub { // implement methods } .... // Get the service you will be receiving callbacks from. // This also starts the threadpool for your callback service. IFoo server = IFoo.getService(true /* retry */); // throws NoSuchElementException if not available .... // This must be a persistent instance variable, not local, // to avoid premature garbage collection. FooCallback mFooCallback = new FooCallback(); .... // Do this once to create the callback service and tell the "foo-bar" service server.setFooCallback(mFooCallback);
接口扩展
假设指定服务在所有设备上实现了接口 IFoo
,那么该服务在特定设备上可能会提供在接口扩展 IBetterFoo
中实现的附加功能,即:
interface IFoo { ... }; interface IBetterFoo extends IFoo { ... };
感知到扩展接口的调用代码可以使用 castFrom()
Java 方法将基本接口安全地转换为扩展接口:
IFoo baseService = IFoo.getService(true /* retry */); // throws NoSuchElementException if not available IBetterFoo extendedService = IBetterFoo.castFrom(baseService); if (extendedService != null) { // The service implements the extended interface. } else { // The service only implements the base interface. }