Typy danych

Na podstawie pliku interfejsu HIDL backend Java HIDL generuje interfejsy Java, stub i kod proxy. Obsługuje wszystkie skalarne typy HIDL ([u]int{8,16,32,64}_t, float, double,enums), a także ciągi znaków, interfejsy, typy safe_union, typy struct, tablice i wektory obsługiwanych typów HIDL. Java HIDL backend nie obsługuje typów union ani fmq. Android 11 obsługuje typy memoryhandle.

Ponieważ środowisko uruchomieniowe Java nie obsługuje natywnej koncepcji liczb bez znaku, wszystkie typy bez znaku (i enumeracje na ich podstawie) są po cichu 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 podpisanych tak, jakby były niepodpisane.

Wykazy

Typy wyliczeniowe nie generują klas wyliczeniowych Java, ale są tłumaczone na klasy wewnętrzne zawierające statyczne definicje stałych dla każdego przypadku wyliczenia. Jeśli klasa enum pochodzi z innej klasy enum, dziedziczy typ magazynu tej klasy. Wyliczenia oparte na typie bezznakowego typu całkowitego są przepisywane na ich odpowiedniki ze znakiem. Ponieważ typ bazowy jest prymitywny, wartość domyślna pól/zmiennych enumeracji to 0, nawet jeśli nie ma żadnego enumeratora zerowego.

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

I:

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

… jest zastępowane przez:

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 jest w formacie utf-8 lub utf-16, ale podczas przenoszenia jest konwertowane na utf-8, ponieważ jest to typowy typ HIDL. Dodatkowo wartość String nie może być null, gdy jest przekazywana do HIDL.

Uchwyt i pamięć

Android 11 wprowadza obsługę Javy dla typów handlememory. Są one tłumaczone odpowiednio na android.os.NativeHandle i android.os.HidlMemory. uchwyt null jest uważany za prawidłowy, a pamięć null nie jest prawidłowa.

W wygenerowanym kodzie serwera argumenty received memory i handle są ważne tylko w zakresie wywołania metody. Jeśli implementacja serwera chce wydłużyć czas życia tych obiektów, musi je powielać za pomocą odpowiednich metod dup(). Zwrócona instancja może być używana poza wywołaniem metody i powinna zostać prawidłowo zamknięta po zakończeniu.

W wygenerowanym kodzie klienta uchwyty i wykazy pamięci, które są wysyłane jako argumenty wejściowe wywoływanej metody, nie muszą być powielane ani zachowywane po jej zakończeniu. Jednak uchwyty i wystąpienia pamięci, które są otrzymywane jako argumenty wyjściowe, są automatycznie powielane przez automatycznie generowany kod i muszą zostać prawidłowo zamknięte po zakończeniu. Dotyczy to zarówno sytuacji, gdy te argumenty zwracania występują jako wartości zwracane metody (w przypadku pojedynczej wartości zwracanej), jak i gdy są używane w stylu wywołania asynchronicznego (w przypadku wielu wartości zwracanych).

Więcej informacji o duplikowaniu i zamykaniu znajdziesz w dokumentacji klas Javy.

Tablice i wektory

Tablice są tłumaczone na tablice Java, a wektory na ArrayList<T>, gdzie T to odpowiedni typ obiektu, prawdopodobnie obejmujący typy skalarne, takie jak vec<int32_t> => ArrayList<Integer>. Na przykład:

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

… zmienia się w:

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

Struktury

Struktury są tłumaczone na klasy Java o podobnej strukturze. 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 swój 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 Bar.java).