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