Tipos de datos

Dado un archivo de interfaz HIDL, el backend de HIDL en Java genera interfaces, código de Stub y Proxy en Java. Admite todos los tipos de HIDL escalares ([u]int{8,16,32,64}_t, float, double, y enums), así como cadenas, interfaces, tipos safe_union, tipos struct y arrays y vectores de tipos de HIDL admitidos. El backend de HIDL de Java NO admite tipos de unión ni tipos de fmq. Android 11 agrega compatibilidad con los tipos memory y handle.

Como el entorno de ejecución de Java no admite el concepto de números enteros sin signo de forma nativa, todos los tipos sin signo (y las enumeraciones basadas en ellos) se tratan de forma silenciosa como sus equivalentes con signo, es decir, uint32_t se convierte en un int en la interfaz de Java. No se realiza ninguna conversión de valores; el implementador del lado de Java debe usar los valores firmados como si no estuvieran firmados.

Enums

Los enums no generan clases enum de Java, sino que se traducen en clases internas que contienen una definición de constante estática para cada caso de enum. Si la clase de enumeración deriva de otra clase de enumeración, hereda el tipo de almacenamiento de esa clase. Las enumeraciones basadas en un tipo de número entero sin signo se reescriben en su equivalente con signo. Dado que el tipo subyacente es primitivo, el valor predeterminado para los campos o las variables de enumeración es cero, incluso cuando no hay un enumerador cero.

Por ejemplo, un SomeBaseEnum con un tipo de uint8_t:

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

… se convierte en lo siguiente:

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

Y:

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

… se reescribe de la siguiente manera:

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

Strings

En Java, String es utf-8 o utf-16, pero se convierte a utf-8 como el tipo HIDL común cuando se transporta. Además, String no debe ser nulo cuando se pasa a HIDL.

Manija y memoria

Android 11 introduce compatibilidad con Java para los tipos handle y memory. Se traducen a android.os.NativeHandle y android.os.HidlMemory, respectivamente. Un identificador nulo se considera válido, mientras que una memoria nula no lo es.

En el código server generado, los argumentos de memoria y de identificador recibidos solo son válidos dentro del alcance de la invocación del método. Si la implementación del servidor desea extender su vida útil, se deben duplicar con sus respectivos métodos dup(). La instancia devuelta se puede usar más allá de la invocación del método y se debe cerrar correctamente cuando se termine de usar.

En el código cliente generado, no es necesario duplicar ni mantener válidas las instancias de memoria y los identificadores que se envían como argumentos de entrada del método llamado después de que este muestre un valor. Sin embargo, el código generado automáticamente duplica automáticamente los identificadores y las instancias de memoria que se reciben como argumentos de salida, y se deben cerrar correctamente cuando se termine de usarlos. Esto es así tanto si esos argumentos de devolución aparecen como valores de devolución del método (en el caso de un solo valor de devolución) como si se usa el estilo de devolución de llamada síncrona (que se usa en el caso de varios valores de devolución).

Para obtener más información sobre la duplicación y el cierre, consulta la documentación de las clases de Java.

Arrays y vectores

Los arrays se traducen en arrays de Java y los vectores se traducen en ArrayList<T>, donde T es el tipo de objeto adecuado, que posiblemente encapsula tipos escalares como vec<int32_t> => ArrayList<Integer>. Por ejemplo:

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

… se convierte en lo siguiente:

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

Estructuras

Las estructuras se traducen en clases de Java con un diseño similar. Por ejemplo:

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

… se convierte en lo siguiente:

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

Tipos declarados

Cada tipo de nivel superior declarado en types.hal obtiene su propio archivo de salida .java (según lo requiere Java). Por ejemplo, el siguiente archivo types.hal genera la creación de dos archivos adicionales (Foo.java y Bar.java):

struct Foo {
 ...
};

struct Bar {
 ...

 struct Baz {
 };

 ...
};

La definición de Baz se encuentra en una clase interna estática de Bar (en Bar.java).