Typy danych

Mając plik interfejsu HIDL, backend Java HIDL generuje interfejsy Java, kod pośredniczący i kod 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 struktur oraz tablice i wektory obsługiwanych typy HIDL. Zaplecze Java HIDL NIE obsługuje typów unii ani typów 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ą dyskretnie traktowane jako ich odpowiedniki ze znakiem, tj. 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.

Wyliczenia

Wyliczenia nie generują klas wyliczeniowych Java, lecz są tłumaczone na klasy wewnętrzne zawierające statyczną definicję stałej dla każdego przypadku wyliczenia. Jeśli klasa wyliczeniowa wywodzi się z innej klasy wyliczeniowej, dziedziczy typ przechowywania tej klasy. Wyliczenia oparte na typie całkowitym bez znaku są przepisywane na ich odpowiedniki ze znakiem. Ponieważ typ podstawowy jest pierwotny, domyślną wartością pól/zmiennych wyliczeniowych jest zero, nawet jeśli nie ma zerowego modułu wyliczającego.

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;
}

I:

enum SomeEnum : uint8_t {
    FIRST_CASE = 10,
    SECOND_CASE = 192
};

… zostaje przepisany jako:

public final class SomeEnum {
    static public final byte FIRST_CASE  = 10;  // no change
    static public final byte SECOND_CASE = -64;
}

Smyczki

String w Javie mają format utf-8 lub utf-16, ale podczas transportu są konwertowane na utf-8 jako powszechny typ HIDL. Ponadto String nie może mieć wartości null po przekazaniu do języka HIDL.

Uchwyt i pamięć

W systemie Android 11 wprowadzono obsługę języka Java dla typów handle i memory . Są one tłumaczone odpowiednio na android.os.NativeHandle i android.os.HidlMemory . Uchwyt zerowy jest uważany za prawidłowy, podczas gdy pamięć zerowa 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 przedłużyć ich żywotność, należy je zduplikować przy użyciu odpowiednich metod dup() . Zwróconej instancji można użyć poza wywołaniem metody i po zakończeniu należy ją poprawnie zamknąć.

W wygenerowanym kodzie klienta uchwyty i instancje pamięci wysyłane jako argumenty wejściowe wywoływanej metody nie muszą być duplikowane ani zachowywane jako ważne po zwróceniu metody. Jednakże uchwyty i instancje pamięci odbierane jako argumenty wyjściowe są automatycznie duplikowane przez automatycznie wygenerowany kod i po zakończeniu muszą zostać poprawnie zamknięte. Dzieje się tak niezależnie od tego, czy te zwracane argumenty pojawiają się jako wartości zwracane przez metodę (w przypadku pojedynczej wartości zwracanej), czy też przy użyciu synchronicznego stylu wywołania zwrotnego (używanego w przypadku wielu wartości zwracanych).

Więcej informacji na temat powielania i zamykania można znaleźć w dokumentacji klas Java.

Tablice i wektory

Tablice są tłumaczone na tablice Java, a wektory są tłumaczone na ArrayList<T> , gdzie T jest odpowiednim typem obiektu, ewentualnie zawijającym typy skalarne, takie jak vec<int32_t> => ArrayList<Integer> ). Na przykład:

takeAnArray(int32_t[3] array);
returnAVector() generates (vec<int32_t> result);

… staje się:

void takeAnArray(int[] array);
ArrayList<Integer> returnAVector();

Struktury

Struktury są tłumaczone na klasy Java o podobnym układzie. Na 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();
}

Deklarowane typy

Każdy typ najwyższego poziomu zadeklarowany w types.hal otrzymuje swój własny plik wyjściowy .java (zgodnie z wymaganiami Java). Na przykład następujący plik types.hal powoduje utworzenie dwóch dodatkowych plików (Foo.java i Bar.java):

struct Foo {
 ...
};

struct Bar {
 ...

 struct Baz {
 };

 ...
};

Definicja Baza mieści się w statycznej klasie wewnętrznej Bar (w Bar.java).