Tipos de datos

Dado un archivo de interfaz HIDL, el backend de Java HIDL genera interfaces de Java, código Stub y Proxy. 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 HIDL compatibles. El backend de Java HIDL NO admite tipos union ni tipos fmq. Android 11 agrega compatibilidad con los tipos memory y handle.

Como el tiempo 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 con signo como si no tuvieran signo.

Enums

Las enumeraciones 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 enumeración. Si la clase enum deriva de alguna otra clase enum, 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 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

String en Java 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.

Handle y memory

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

En el código server generado, los argumentos de memoria y handle recibidos solo son válidos dentro del alcance de la invocación del método. Si la implementación del servidor quiere extender su ciclo de vida, debe duplicarse con sus métodos dup() respectivos. La instancia que se muestra se puede usar más allá de la invocación del método y debe cerrarse correctamente cuando se termine de usar.

En el código client generado, los handles y las instancias de memoria que se envían como argumentos de entrada del método llamado no necesitan duplicarse ni mantenerse válidos después de que el método regrese. Sin embargo, los handles y las instancias de memoria que se reciben como argumentos de salida se duplican automáticamente con el código generado automáticamente y deben cerrarse correctamente cuando se termine de usar. Esto es cierto, ya sea que esos argumentos de devolución aparezcan como valores de devolución del método (en el caso de un solo valor de devolución) o con 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 a arrays de Java y los vectores se traducen a ArrayList<T> donde T es el tipo de objeto adecuado, que posiblemente incluye 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 a 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).