À partir d'un fichier d'interface HIDL, le backend Java HIDL génère du code d'interface, de stub et de proxy Java. Il est compatible avec tous les types HIDL scalaires ([u
]int
{8,16,32,64}_t, float, double,
et enum
s), ainsi qu'avec les chaînes, les interfaces, les types safe_union, les types struct, et les tableaux et vecteurs de types HIDL compatibles. Le backend Java HIDL n'est PAS compatible avec les types union ni les types fmq. Android 11 est compatible avec les types memory
et handle
.
Comme l'environnement d'exécution Java n'est pas compatible avec le concept d'entiers non signés de manière native, tous les types non signés (et les énumérations basées sur ceux-ci) sont traités silencieusement comme leurs équivalents signés. Par exemple, uint32_t
devient int
dans l'interface Java. Aucune conversion de valeur n'est effectuée. L'implémenteur côté Java doit utiliser les valeurs signées comme si elles n'étaient pas signées.
Énumérations
Les énumérations ne génèrent pas de classes d'énumération Java, mais sont plutôt traduites en classes internes contenant une définition de constante statique pour chaque cas d'énumération. Si la classe enum dérive d'une autre classe enum, elle hérite du type de stockage de cette classe. Les énumérations basées sur un type entier non signé sont réécrites dans leur équivalent signé. Étant donné que le type sous-jacent est primitif, la valeur par défaut des champs/variables enum est zéro, même en l'absence d'énumérateur zéro.
Par exemple, un SomeBaseEnum
de type uint8_t
:
enum SomeBaseEnum : uint8_t { foo = 3 }; enum SomeEnum : SomeBaseEnum { quux = 33, goober = 127 };
… devient :
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; }
Et :
enum SomeEnum : uint8_t { FIRST_CASE = 10, SECOND_CASE = 192 };
… est réécrit comme suit :
public final class SomeEnum { static public final byte FIRST_CASE = 10; // no change static public final byte SECOND_CASE = -64; }
Strings
String
en Java est utf-8 ou utf-16, mais est converti en utf-8 en tant que type HIDL commun lors du transport. De plus, String
ne doit pas être nul lorsqu'il est transmis à HIDL.
Poignée et mémoire
Android 11 introduit la prise en charge de Java pour les types handle
et memory
. Elles sont traduites par android.os.NativeHandle
et android.os.HidlMemory
, respectivement. Un handle Null est considéré comme valide, contrairement à une mémoire Null.
Dans le code serveur généré, les arguments de mémoire et de gestion reçus ne sont valides que dans le champ d'application de l'appel de méthode. Si l'implémentation du serveur souhaite étendre sa durée de vie, elle doit être dupliquée à l'aide de ses méthodes dup()
respectives. L'instance renvoyée peut être utilisée au-delà de l'appel de méthode et doit être correctement fermée une fois l'opération terminée.
Dans le code client généré, les handles et les instances de mémoire qui sont envoyés en tant qu'arguments d'entrée de la méthode appelée n'ont pas besoin d'être dupliqués ni conservés valides après le retour de la méthode. Toutefois, les handles et les instances de mémoire qui sont reçus en tant qu'arguments de sortie sont automatiquement dupliqués par le code généré automatiquement et doivent être correctement fermés une fois utilisés. Cela est vrai que ces arguments de retour apparaissent comme des valeurs de retour de la méthode (dans le cas d'une seule valeur de retour) ou en utilisant le style de rappel synchrone (utilisé dans le cas de plusieurs valeurs de retour).
Pour en savoir plus sur la duplication et la fermeture, consultez la documentation des classes Java.
Tableaux et vecteurs
Les tableaux sont traduits en tableaux Java et les vecteurs sont traduits en ArrayList<T>
où T est le type d'objet approprié, en enveloppant éventuellement les types scalaires tels que vec<int32_t> =>
ArrayList<Integer>
). Par exemple :
takeAnArray(int32_t[3] array); returnAVector() generates (vec<int32_t> result);
… devient :
void takeAnArray(int[] array); ArrayList<Integer> returnAVector();
Structures
Les structures sont traduites en classes Java avec une mise en page similaire. Exemple :
struct Bar { vec<bool> someBools; }; struct Foo { int32_t a; int8_t b; float[10] c; Bar d; };
… devient :
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(); }
Types déclarés
Chaque type de premier niveau déclaré dans types.hal
obtient son propre fichier de sortie .java (comme l'exige Java). Par exemple, le fichier types.hal
suivant entraîne la création de deux fichiers supplémentaires (Foo.java et Bar.java) :
struct Foo { ... }; struct Bar { ... struct Baz { }; ... };
La définition de Baz se trouve dans une classe interne statique de Bar (dans Bar.java
).