Na podstawie pliku interfejsu HIDL backend HIDL w języku Java generuje interfejsy Java, kod Stub i Proxy. Obsługuje wszystkie skalarne typy HIDL ([u
]int
{8,16,32,64}_t, float, double,
i enum
s), a także ciągi znaków, interfejsy, typy safe_union, typy struct oraz tablice i wektory obsługiwanych typów HIDL. Backend HIDL w Javie nie obsługuje typów union ani typów fmq. Android 11 dodaje obsługę typów memory
i handle
.
Środowisko wykonawcze Java nie obsługuje natywnie koncepcji liczb całkowitych bez znaku, dlatego wszystkie typy bez znaku (i wyliczenia na nich oparte) są cicho traktowane jako ich odpowiedniki ze znakiem, tzn. uint32_t
staje się int
w interfejsie Java. Nie jest wykonywana konwersja wartości. Osoba wdrażająca po stronie Javy musi używać wartości ze znakiem tak, jakby były bez znaku.
Wykazy
Wyliczenia nie generują klas wyliczeniowych Java, ale są tłumaczone na klasy wewnętrzne zawierające statyczną definicję stałej dla każdego przypadku wyliczenia. Jeśli klasa wyliczeniowa dziedziczy po innej klasie wyliczeniowej, dziedziczy też jej typ pamięci. Wyliczenia oparte na typie liczby całkowitej bez znaku są przekształcane w odpowiedniki ze znakiem. Ponieważ typ bazowy jest typem prostym, domyślna wartość pól/zmiennych wyliczeniowych to zero, nawet jeśli nie ma wyliczenia o wartości zero.
Na przykład SomeBaseEnum
o typie uint8_t
:
enum SomeBaseEnum : uint8_t { foo = 3 }; enum SomeEnum : SomeBaseEnum { quux = 33, goober = 127 };
… zmienia się w:
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; }
Oraz:
enum SomeEnum : uint8_t { FIRST_CASE = 10, SECOND_CASE = 192 };
… można zapisać ponownie w tej postaci:
public final class SomeEnum { static public final byte FIRST_CASE = 10; // no change static public final byte SECOND_CASE = -64; }
Strings
String
w Javie to utf-8 lub utf-16, ale podczas przesyłania jest konwertowany na utf-8 jako wspólny typ HIDL. Poza tym w przypadku przekazywania do HIDL wartość String
nie może być wartością null.
Uchwyt i pamięć
Android 11 wprowadza obsługę języka Java w przypadku typów handle
i memory
. Są one tłumaczone odpowiednio na język android.os.NativeHandle
i android.os.HidlMemory
. Pusty uchwyt jest uważany za prawidłowy, a pamięć o wartości null nie.
W wygenerowanym kodzie serwera argumenty dotyczące otrzymanej pamięci i uchwytu są ważne tylko w zakresie wywołania metody. Jeśli implementacja serwera ma przedłużyć okres istnienia, musi zostać zduplikowana za pomocą odpowiednich metod dup()
. Zwróconej instancji można używać poza wywołaniem metody i należy ją prawidłowo zamknąć po zakończeniu pracy.
W wygenerowanym kodzie klienta uchwyty i instancje pamięci, które są przesyłane jako argumenty wejściowe wywoływanej metody, nie muszą być duplikowane ani utrzymywane w stanie ważności po zwróceniu przez metodę wartości. Jednak uchwyty i instancje pamięci, które są otrzymywane jako argumenty wyjściowe, są automatycznie duplikowane przez autogenerowany kod i muszą być prawidłowo zamykane po zakończeniu pracy. Dotyczy to zarówno argumentów zwracanych jako wartości metody (w przypadku pojedynczej wartości zwracanej), jak i argumentów zwracanych w stylu wywołania zwrotnego synchronicznego (w przypadku wielu wartości zwracanych).
Więcej informacji o duplikowaniu i zamykaniu znajdziesz w dokumentacji klas Java.
Tablice i wektory
Tablice są tłumaczone na tablice Java, a wektory na ArrayList<T>
, gdzie T jest odpowiednim typem obiektu (może obejmować typy skalarne, takie jak vec<int32_t> =>
ArrayList<Integer>
). Przykład:
takeAnArray(int32_t[3] array); returnAVector() generates (vec<int32_t> result);
… zmienia się w:
void takeAnArray(int[] array); ArrayList<Integer> returnAVector();
Konstrukcje
Struktury 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; };
… zmienia się w:
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(); }
Zadeklarowane typy
Każdy typ najwyższego poziomu zadeklarowany w types.hal
ma własny plik wyjściowy .java (zgodnie z wymaganiami języka Java). Na przykład ten pliktypes.hal
powoduje utworzenie 2 dodatkowych plików (Foo.java i Bar.java):
struct Foo { ... }; struct Bar { ... struct Baz { }; ... };
Definicja klasy Baz znajduje się w statycznej klasie wewnętrznej klasy Bar (w Bar.java
).