Datentypen

Anhand einer HIDL-Schnittstellendatei generiert das Java HIDL-Back-End Java-Schnittstellen, ‑Stubs und ‑Proxy-Code. Es unterstützt alle skalaren HIDL-Typen ([u]int{8,16,32,64}_t, float, double, und enums), sowie Strings, Schnittstellen, safe_union-Typen, Strukturtypen und Arrays und Vektoren unterstützter HIDL-Typen. Das Java HIDL-Backend unterstützt KEINE Union-Typen oder FMQ-Typen. Mit Android 11 wird Unterstützung für die Typen memory und handle hinzugefügt.

Da die Java-Laufzeit das Konzept von Ganzzahlen ohne Vorzeichen nicht nativ unterstützt, werden alle Ganzzahltypen ohne Vorzeichen (und darauf basierende Enumerationen) automatisch als ihre signierten Äquivalente behandelt. Das bedeutet, dass uint32_t in der Java-Benutzeroberfläche zu int wird. Es erfolgt keine Wertumwandlung. Der Implementierer auf Java-Seite muss die signierten Werte so verwenden, als wären sie nicht signiert.

Aufzählungen

Für Enums werden keine Java-Enumerationsklassen generiert, sondern sie werden in innere Klassen übersetzt, die eine statische Konstantendefinition für jeden Enumerationsfall enthalten. Wenn die Enum-Klasse von einer anderen Enum-Klasse abgeleitet ist, wird der Speichertyp dieser Klasse übernommen. Auf einem Ganzzahltyp ohne Vorzeichen basierende Aufzählungen werden in ihre signierte Entsprechung umgeschrieben. Da der zugrunde liegende Typ ein primitiver Typ ist, ist der Standardwert für enum-Felder/-Variablen null, auch wenn es keinen Nullenumerator gibt.

Beispiel: Ein SomeBaseEnum mit dem Typ uint8_t:

enum SomeBaseEnum : uint8_t { foo = 3 };
enum SomeEnum : SomeBaseEnum {
    quux = 33,
    goober = 127
};

… wird zu:

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

Und:

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

… wird in folgende Form umgewandelt:

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

Strings

String in Java ist utf-8 oder utf-16, wird aber beim Transport in utf-8 als gängigen HIDL-Typ konvertiert. Außerdem darf String nicht null sein, wenn es an HIDL übergeben wird.

Handle und Arbeitsspeicher

In Android 11 wird Java-Unterstützung für die Typen handle und memory eingeführt. Sie werden in android.os.NativeHandle bzw. android.os.HidlMemory übersetzt. Ein Null-Handle gilt als gültig, ein Null-Speicher hingegen nicht.

Im generierten Server-Code sind die empfangenen Speicher- und Handle-Argumente nur im Gültigkeitsbereich der Methode gültig. Wenn die Lebensdauer der Tokens durch die Serverimplementierung verlängert werden soll, müssen sie mit den entsprechenden dup()-Methoden dupliziert werden. Die zurückgegebene Instanz kann auch nach dem Aufruf der Methode verwendet werden und sollte nach Gebrauch ordnungsgemäß geschlossen werden.

Im generierten Client-Code müssen Handles und Speicherinstanzen, die als Eingabeargumente der aufgerufenen Methode gesendet werden, nach der Rückgabe der Methode nicht dupliziert oder gültig gehalten werden. Handles und Speicherinstanzen, die als Ausgabeargumente empfangen werden, werden jedoch automatisch vom automatisch generierten Code dupliziert und müssen nach Gebrauch ordnungsgemäß geschlossen werden. Das gilt unabhängig davon, ob diese Rückgabeargumente als Rückgabewerte der Methode (bei einem einzelnen Rückgabewert) oder mit dem synchronen Rückrufstil (bei mehreren Rückgabewerten) erscheinen.

Weitere Informationen zum Duplizieren und Schließen finden Sie in der Dokumentation der Java-Klassen.

Arrays und Vektoren

Arrays werden in Java-Arrays und Vektoren in ArrayList<T> umgewandelt, wobei T der entsprechende Objekttyp ist, der möglicherweise skalare Typen wie vec<int32_t> => ArrayList<Integer> umschließt. Beispiel:

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

… wird zu:

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

Gebäude

Strukturen werden in Java-Klassen mit einem ähnlichen Layout übersetzt. Beispiel:

struct Bar {
 vec<bool> someBools;
};
struct Foo {
 int32_t a;
 int8_t b;
 float[10] c;
 Bar d;
};

… wird zu:

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

Deklarierte Typen

Jeder in types.hal deklarierte Typ der obersten Ebene erhält eine eigene .java-Ausgabedatei (wie von Java gefordert). Die folgende types.hal-Datei führt beispielsweise dazu, dass zwei zusätzliche Dateien erstellt werden: Foo.java und Bar.java:

struct Foo {
 ...
};

struct Bar {
 ...

 struct Baz {
 };

 ...
};

Die Definition von Baz befindet sich in einer statischen inneren Klasse von Bar (in Bar.java).