给定一个 HIDL 接口文件,Java HIDL 后端会生成 Java 接口、Stub 和代理代码。它支持所有标量 HIDL 类型([u
]int
{8,16,32,64}_t、float、double 和
enum
),以及字符串、接口、safe_union 类型、struct 类型以及受支持的 HIDL 类型的数组和向量。Java HIDL 后端不支持联合类型或 fmq 类型。Android 11 添加了对 memory
和 handle
类型的支持。
由于 Java 运行时本身不支持无符号整数的概念,因此所有无符号类型(以及基于这些类型的枚举)都以静默方式视为其有符号等效类型,即 uint32_t
在 Java 接口中变为 int
。不执行任何值转换;Java 端的实现者必须像使用无符号值一样使用有符号值。
枚举
枚举不会生成 Java 枚举类,而是转换为内部类,其中包含每个枚举案例的静态常量定义。如果枚举类派生自其他一些枚举类,则它会继承该类的存储类型。基于无符号整数类型的枚举会重写为其有符号等效类型。由于底层类型是基本类型,因此即使没有零枚举器,枚举字段/变量的默认值也为零。
例如,类型为 uint8_t
的 SomeBaseEnum
enum SomeBaseEnum : uint8_t { foo = 3 }; enum SomeEnum : SomeBaseEnum { quux = 33, goober = 127 };
… 变为
public final class SomeBaseEnum { public static final byte foo = 3; } public final class SomeEnum { public static final byte foo = 3; public static final byte quux = 33; public static final byte goober = 127; }
以及
enum SomeEnum : uint8_t { FIRST_CASE = 10, SECOND_CASE = 192 };
… 重写为
public final class SomeEnum { static public final byte FIRST_CASE = 10; // no change static public final byte SECOND_CASE = -64; }
字符串
Java 中的 String
是 utf-8 或 utf-16,但在传输时会转换为 utf-8 作为常见的 HIDL 类型。此外,传入 HIDL 时,String
不得为 null。
句柄和内存
Android 11 引入了对 handle
和 memory
类型的 Java 支持。它们分别转换为 android.os.NativeHandle
和 android.os.HidlMemory
。null 句柄被视为有效,而 null 内存则无效。
在生成的服务器代码中,接收到的内存和句柄参数仅在方法调用范围内有效。如果服务器实现想要延长其生命周期,则必须使用其各自的 dup()
方法复制它们。返回的实例可以在方法调用之外使用,并且在使用完毕后应正确关闭。
在生成的客户端代码中,作为调用方法的输入参数发送的句柄和内存实例在方法返回后无需复制或保持有效。但是,作为输出参数接收的句柄和内存实例由自动生成的代码自动复制,并且在使用完毕后必须正确关闭。无论这些返回参数是以方法返回值(在单个返回值的情况下)还是使用同步回调样式(在多个返回值的情况下)出现,都是如此。
有关复制和关闭的更多信息,请参阅 Java 类的文档。
数组和向量
数组转换为 Java 数组,向量转换为 ArrayList<T>
,其中 T 是适当的对象类型,可能包装标量类型,例如 vec<int32_t> => ArrayList<Integer>
)。例如
takeAnArray(int32_t[3] array); returnAVector() generates (vec<int32_t> result);
… 变为
void takeAnArray(int[] array); ArrayList<Integer> returnAVector();
结构
结构会转换成具有类似布局的 Java 类。例如
struct Bar { vec<bool> someBools; }; struct Foo { int32_t a; int8_t b; float[10] c; Bar d; };
… 变为
class Bar { public final ArrayList<Boolean> someBools = new ArrayList(); }; class Foo { public int a; public byte b; public final float[] c = new float[10]; public final Bar d = new Bar(); }
声明类型
在 types.hal
中声明的每个顶级类型都会获得自己的 .java 输出文件(Java 的要求)。例如,以下 types.hal
文件会生成两个额外的文件(Foo.java 和 Bar.java)
struct Foo { ... }; struct Bar { ... struct Baz { }; ... };
Baz 的定义位于 Bar 的静态内部类中(在 Bar.java
中)。