Учитывая файл интерфейса HIDL, серверная часть Java HIDL генерирует интерфейсы Java, код заглушки и прокси. Он поддерживает все скалярные типы HIDL ([ u
] int
{ 8,16,32,64}_t, float, double,
и enum
s), а также строки, интерфейсы, типы Safe_union, типы структур, а также массивы и векторы поддерживаемых HIDL-типы. Серверная часть Java HIDL НЕ поддерживает типы объединения или типы fmq . В Android 11 добавлена поддержка типов memory
и handle
.
Поскольку среда выполнения Java изначально не поддерживает концепцию беззнаковых целых чисел, все беззнаковые типы (и перечисления на их основе) автоматически обрабатываются как их знаковые эквиваленты, т. е. uint32_t
становится int
в интерфейсе Java. Преобразование значений не выполняется; разработчик на стороне Java должен использовать подписанные значения, как если бы они были беззнаковыми.
Перечисления
Перечисления не генерируют классы перечислений Java, а вместо этого преобразуются во внутренние классы, содержащие определение статической константы для каждого случая перечисления. Если класс перечисления является производным от какого-либо другого класса перечисления, он наследует тип хранения этого класса. Перечисления, основанные на беззнаковом целочисленном типе, перезаписываются в их знаковый эквивалент. Поскольку базовый тип является примитивным, значение по умолчанию для полей/переменных перечисления равно нулю, даже если нулевой перечислитель отсутствует.
Например, SomeBaseEnum
с типом uint8_t
:
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; }
Струны
String
в Java имеет формат utf-8 или utf-16, но при транспортировке преобразуется в utf-8 как общий тип HIDL. Кроме того, String
не должна быть нулевой при передаче в HIDL.
Ручка и память
В Android 11 представлена поддержка Java для типов handle
и memory
. Они переводятся в android.os.NativeHandle
и android.os.HidlMemory
соответственно. Нулевой дескриптор считается допустимым, а нулевая память — нет.
В сгенерированном серверном коде полученные аргументы памяти и дескриптора действительны только в пределах области вызова метода. Если реализация сервера хочет продлить их срок службы, их необходимо продублировать, используя соответствующие методы 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
).