Com um arquivo de interface HIDL, o back-end Java HIDL gera interfaces Java,
stubs e código proxy. Ele oferece suporte a todos os tipos de HIDL escalar
([u
]int
{8,16,32,64}_t, float, double,
e
enum
s), além de strings, interfaces, tipos safe_union, tipos
de struct, matrizes e vetores de tipos de HIDL aceitos. O back-end Java HIDL
NÃO oferece suporte a tipos de união ou fmq. O Android
11 adiciona suporte aos tipos memory
e
handle
.
Como o ambiente de execução do Java não oferece suporte ao conceito de números inteiros não sinalizados de forma nativa,
todos os tipos não sinalizados (e enumerações com base neles) são tratados silenciosamente como
equivalentes sinalizados, ou seja, uint32_t
se torna int
na
interface Java. Nenhuma conversão de valor é realizada. O implementador no
lado Java precisa usar os valores assinados como se não tivessem assinatura.
Enumerações
Os tipos enumerados não geram classes de tipo enumerado Java, mas são convertidos em classes internas que contêm uma definição de constante estática para cada caso de tipo enumerado. Se a classe de tipo enumerado for derivada de outra, ela herda o tipo de armazenamento dessa classe. As enumerações baseadas em um tipo de número inteiro não assinado são reescritas no equivalente assinado. Como o tipo subjacente é primitivo, o valor padrão para campos/variáveis de enumeração é zero, mesmo quando não há um enumerador zero.
Por exemplo, um SomeBaseEnum
com um tipo de
uint8_t
:
enum SomeBaseEnum : uint8_t { foo = 3 }; enum SomeEnum : SomeBaseEnum { quux = 33, goober = 127 };
… se torna:
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; }
E:
enum SomeEnum : uint8_t { FIRST_CASE = 10, SECOND_CASE = 192 };
… é reescrito como:
public final class SomeEnum { static public final byte FIRST_CASE = 10; // no change static public final byte SECOND_CASE = -64; }
Strings
String
em Java é utf-8 ou utf-16, mas é convertido em utf-8
como o tipo HIDL comum ao ser transportado. Além disso, String
não pode ser nulo quando transmitido para o HIDL.
Gerenciador e memória
O Android 11 introduz suporte a Java para os tipos handle
e
memory
. Elas são traduzidas para android.os.NativeHandle
e
android.os.HidlMemory
, respectivamente. Um identificador nulo é considerado válido, enquanto uma memória
nula não é.
No código do servidor gerado, os argumentos de memória e de manipulação recebidos são válidos
apenas no escopo da invocação do método. Se a implementação do servidor quiser estender a
duração, ela precisará ser duplicada usando os métodos dup()
correspondentes. A
instância retornada pode ser usada além da invocação do método e precisa ser fechada corretamente
quando terminar.
No código cliente gerado, os identificadores e as instâncias de memória que são enviados como argumentos de entrada do método chamado não precisam ser duplicados nem mantidos válidos após o retorno do método. No entanto, os identificadores e as instâncias de memória que são recebidos como argumentos de saída são automaticamente duplicados pelo código gerado automaticamente e precisam ser fechados corretamente quando terminarem. Isso é verdadeiro se esses argumentos forem exibidos como valores de retorno do método (no caso de um único valor de retorno) ou usando o estilo de callback síncrono (usado no caso de vários valores de retorno).
Para mais informações sobre duplicação e fechamento, consulte a documentação das classes Java.
Matrizes e vetores
As matrizes são traduzidas em matrizes Java, e os vetores são traduzidos em
ArrayList<T>
, em que T é o tipo de objeto apropriado, possivelmente
envolvendo tipos escalares, como vec<int32_t> =>
ArrayList<Integer>
. Por exemplo:
takeAnArray(int32_t[3] array); returnAVector() generates (vec<int32_t> result);
… se torna:
void takeAnArray(int[] array); ArrayList<Integer> returnAVector();
Estruturas
As estruturas são traduzidas em classes Java com um layout semelhante. Por exemplo:
struct Bar { vec<bool> someBools; }; struct Foo { int32_t a; int8_t b; float[10] c; Bar d; };
… se torna:
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 nível superior declarado em types.hal
recebe o próprio arquivo de saída .java (conforme exigido pelo Java). Por exemplo, o arquivo types.hal
abaixo resulta na criação de dois arquivos extras (Foo.java
e Bar.java):
struct Foo { ... }; struct Bar { ... struct Baz { }; ... };
A definição de Baz fica em uma classe interna estática de Bar (em Bar.java
).