Dado un archivo de interfaz HIDL, el backend de HIDL de Java genera interfaces, Stub y código de proxy de Java. Admite todos los tipos de HIDL escalares ([u
]int
{8,16,32,64}_t, float, double,
y enum
s), así como cadenas, interfaces, tipos de safe_union, tipos de struct, y matrices y vectores de tipos de HIDL compatibles. 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 de forma nativa el concepto de números enteros sin firmar, todos los tipos sin firmar (y las enums basadas en ellos) se tratan de forma silenciosa como sus equivalentes firmados, es decir, uint32_t
se convierte en int
en la interfaz de Java. No se realiza ninguna conversión de valor. El implementador del lado de Java debe usar los valores firmados como si no estuvieran firmados.
Enums
Los enums no generan clases de enum de Java, sino que se traducen a clases internas que contienen una definición de constante estática para cada caso de enum. Si la clase de enumeración deriva de alguna otra clase de enumeración, hereda el tipo de almacenamiento de esa clase. Las enumeraciones basadas en un tipo de número entero sin firmar se vuelven a escribir en su equivalente firmado. 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:
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; }
Además:
enum SomeEnum : uint8_t { FIRST_CASE = 10, SECOND_CASE = 192 };
… se vuelve a escribir 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 de HIDL común cuando se transporta. Además, String
no debe ser nulo cuando se pasa a HIDL.
Control y memoria
Android 11 incluye 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 del servidor generado, la memoria recibida y los argumentos de control solo son válidos dentro del alcance de la invocación del método. Si la implementación del servidor desea extender su tiempo de vida, se deben duplicar con sus respectivos métodos dup()
. La instancia que se muestra 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, los controladores 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 se muestra el método. Sin embargo, el código generado automáticamente duplica automáticamente los controladores y las instancias de memoria que se reciben como argumentos de salida y deben cerrarse correctamente cuando se termine de usarlos. Esto es cierto 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) 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 en arrays de Java y los vectores se traducen en ArrayList<T>
, donde T es el tipo de objeto adecuado, posiblemente un wrapper de tipos escalares, como vec<int32_t> =>
ArrayList<Integer>
. Por ejemplo:
takeAnArray(int32_t[3] array); returnAVector() generates (vec<int32_t> result);
… se convierte en:
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:
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 (como 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 reside en una clase interna estática de Bar (en Bar.java
).