Na podstawie pliku interfejsu HIDL backend Java HIDL generuje interfejsy Java, kod Stub i Proxy. Obsługuje wszystkie skalarne typy HIDL
([u]int{8,16,32,64}_t, float, double, i
enums), a także ciągi znaków, interfejsy, typy safe_union, typy struct
oraz tablice i wektory obsługiwanych typów HIDL. Backend Java HIDL NIE obsługuje typów union ani fmq. Android 11 dodaje obsługę typów memory i handle.
Ponieważ środowisko wykonawcze Java nie obsługuje natywnie koncepcji liczb całkowitych bez znaku,
wszystkie typy bez znaku (i oparte na nich wyliczenia) są cicho traktowane jako ich
odpowiedniki ze znakiem, czyli uint32_t staje się int w
interfejsie Java. Nie jest wykonywana żadna konwersja wartości. Implementator po stronie Java musi używać wartości ze znakiem tak, jakby były bez znaku.
Wartości w polu enum
Wartości w polu enum nie generują klas enum w języku Java, ale są tłumaczone na klasy wewnętrzne zawierające statyczną definicję stałej dla każdego przypadku enum. Jeśli klasa enum dziedziczy po innej klasie enum, dziedziczy typ przechowywania tej klasy. Wyliczenia oparte na typie liczby całkowitej bez znaku są przepisywane na ich odpowiedniki ze znakiem. Ponieważ typ bazowy jest typem pierwotnym, wartość domyślna pól/zmiennych enum to zero, nawet jeśli nie ma enumeratora zero.
Na przykład SomeBaseEnum z typem uint8_t:
enum SomeBaseEnum : uint8_t { foo = 3 }; enum SomeEnum : SomeBaseEnum { quux = 33, goober = 127 };
… staje się:
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; }
A:
enum SomeEnum : uint8_t { FIRST_CASE = 10, SECOND_CASE = 192 };
… jest przepisywane jako:
public final class SomeEnum { static public final byte FIRST_CASE = 10; // no change static public final byte SECOND_CASE = -64; }
Strings
String w języku Java to utf-8 lub utf-16, ale podczas transportu jest konwertowany na utf-8 jako typ HIDL. Ponadto String nie może mieć wartości null, gdy jest przekazywany do HIDL.
Handle and memory
Android 11 wprowadza obsługę typów handle i
memory w języku Java. Są one tłumaczone odpowiednio na android.os.NativeHandle i
android.os.HidlMemory. Uchwyt null jest uważany za prawidłowy, natomiast pamięć null
nie.
W wygenerowanym kodzie serwera otrzymane argumenty pamięci i uchwytu są prawidłowe tylko w zakresie wywołania metody. Jeśli implementacja serwera chce wydłużyć ich czas życia, musi je zduplikować za pomocą odpowiednich metod dup(). Zwróconej
instancji można używać poza wywołaniem metody i należy ją prawidłowo zamknąć, gdy nie jest już potrzebna.
W wygenerowanym kodzie klienta uchwyty i instancje pamięci, które są wysyłane jako argumenty wejściowe wywoływanej metody, nie muszą być duplikowane ani utrzymywane w stanie prawidłowym po powrocie z metody. Uchwyty i instancje pamięci, które są otrzymywane jako argumenty wyjściowe, są jednak automatycznie duplikowane przez autogenerowany kod i muszą zostać prawidłowo zamknięte, gdy nie są już potrzebne. Dotyczy to zarówno argumentów zwracanych jako wartości zwracane przez metodę (w przypadku pojedynczej wartości zwracanej), jak i argumentów zwracanych za pomocą synchronicznego wywołania zwrotnego (w przypadku wielu wartości zwracanych).
Więcej informacji o duplikowaniu i zamykaniu znajdziesz w dokumentacji klas Java.
Arrays and vectors
Tablice są tłumaczone na tablice Java, a wektory na
ArrayList<T> gdzie T jest odpowiednim typem obiektu, ewentualnie
opakowującym typy skalarne, np. vec<int32_t> =>
ArrayList<Integer>). Przykład:
takeAnArray(int32_t[3] array); returnAVector() generates (vec<int32_t> result);
… staje się:
void takeAnArray(int[] array); ArrayList<Integer> returnAVector();
Konstrukcje
Konstrukcje są tłumaczone na klasy Java o podobnym układzie. Przykład:
struct Bar { vec<bool> someBools; }; struct Foo { int32_t a; int8_t b; float[10] c; Bar d; };
… staje się:
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(); }
Declared types
Każdy typ najwyższego poziomu zadeklarowany w types.hal otrzymuje własny plik wyjściowy .java (zgodnie z wymaganiami języka Java). Na przykład poniższy plik types.hal powoduje utworzenie 2 dodatkowych plików (Foo.java i Bar.java):
struct Foo { ... }; struct Bar { ... struct Baz { }; ... };
Definicja Baz znajduje się w statycznej klasie wewnętrznej Bar (w pliku Bar.java).