Types de données

À partir d'un fichier d'interface HIDL, le backend HIDL Java génère des interfaces Java, des bouchons et du code proxy. Il est compatible avec tous les types HIDL scalaires ([u]int{8,16,32,64}_t, float, double, et enums), ainsi que les chaînes, les interfaces, les types safe_union, les types struct, ainsi que les tableaux et les vecteurs de types HIDL compatibles. Le backend HIDL Java n'est PAS compatible avec les types d'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 qui s'y basent) sont traités de manière silencieuse comme leurs équivalents signés, c'est-à-dire que uint32_t devient int dans l'interface Java. Aucune conversion de valeur n'est effectuée. L'implémentateur 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 traduites en classes internes contenant une définition de constante statique pour chaque cas d'énumération. Si la classe d'énumération dérive d'une autre classe d'énumération, elle hérite du type de stockage de cette classe. Les énumérations basées sur un type d'entier non signé sont réécrites en leur équivalent signé. Étant donné que le type sous-jacent est une primitive, la valeur par défaut des champs/variables d'énumération est zéro, même en l'absence d'énumérateur de 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 dans HIDL.

Gestion des poignées et de la mémoire

Android 11 introduit la prise en charge de Java pour les types handle et memory. Ils sont traduits en android.os.NativeHandle et android.os.HidlMemory, respectivement. Un gestionnaire nul est considéré comme valide, tandis qu'une mémoire nulle ne l'est pas.

Dans le code serveur généré, les arguments de mémoire et de poignée reçus ne sont valides que dans le champ d'application de l'appel de méthode. Si l'implémentation du serveur souhaite prolonger leur durée de vie, elles doivent être dupliquées à l'aide de leurs 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 terminée.

Dans le code client généré, les poignées et les instances de mémoire qui sont envoyées en tant qu'arguments d'entrée de la méthode appelée n'ont pas besoin d'être dupliquées ni conservées valides après le retour de la méthode. Toutefois, les poignées et les instances de mémoire reçues en tant qu'arguments de sortie sont automatiquement dupliquées par le code généré automatiquement et doivent être correctement fermées une fois que vous n'en avez plus besoin. Cela est vrai que ces arguments de retour apparaissent comme valeurs de retour de la méthode (dans le cas d'une seule valeur de retour) ou à l'aide du 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 en ArrayList<T>, où T est le type d'objet approprié, éventuellement encapsulant des 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 reçoit son propre fichier de sortie .java (comme l'exige Java). Par exemple, le fichier types.hal suivant génère 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).