A linguagem AIDL é baseada na linguagem Java. Os arquivos especificam um contrato de interface e vários tipos de dados e constantes usados nele.
Pacote
Todos os arquivos AIDL começam com um pacote opcional que corresponde aos nomes de pacotes em vários back-ends. Uma declaração de pacote tem esta aparência:
package my.package;
Assim como em Java, os arquivos AIDL precisam estar em uma estrutura de pastas que corresponda ao
pacote. Os arquivos com o pacote my.package precisam estar na pasta my/package/.
Tipos
Nos arquivos AIDL, há muitos lugares em que os tipos podem ser especificados. Para uma lista exata dos tipos compatíveis com a linguagem AIDL, consulte Tipos de back-ends AIDL.
Anotações
Várias partes da linguagem AIDL aceitam anotações. Para uma lista de anotações e onde elas podem ser aplicadas, consulte Anotações AIDL.
Importações
Para usar tipos definidos em outras interfaces, primeiro adicione dependências no
sistema de build. Em módulos cc_* e java_* do Soong, em que os arquivos .aidl são usados
diretamente em srcs em builds da plataforma Android, é possível adicionar diretórios
usando o campo aidl: { include_dirs: ... }. Para importações usando
aidl_interface, consulte
esta página.
Uma importação tem esta aparência:
import some.package.Foo; // explicit import
Ao importar um tipo no mesmo pacote, o pacote pode ser omitido. No entanto, omitir o pacote pode levar a erros de importação ambíguos quando os tipos são especificados sem um pacote e colocados no namespace global. Geralmente, todos os tipos devem ter namespaces.
import Foo; // same as my.package.Foo
Definir tipos
Os arquivos AIDL geralmente definem tipos usados como uma interface.
Interfaces
Confira um exemplo de interface AIDL:
interface ITeleport {
// Location defined elsewhere
void teleport(Location baz, float speed);
String getName();
// ITeleportCallback defined elsewhere
void methodWithCallback(ITeleportCallback callback);
// ITeleportSession defined elsewhere
ITeleportSession getASubInterface();
}
Uma interface define um objeto com uma série de métodos. Os métodos podem ser
oneway (oneway void doFoo()) ou síncronos. Se uma interface for definida como
oneway (oneway interface ITeleport {...}), todos os métodos nela serão
implicitamente oneway. Os métodos unidirecionais são enviados de forma assíncrona e não podem
retornar um resultado. Métodos unidirecionais da mesma linha de execução para o mesmo binder também
são executados em série (embora potencialmente em linhas de execução diferentes). Para uma discussão sobre como configurar linhas de execução, consulte Gerenciamento de linhas de execução de back-ends AIDL.
O Binder permite que muitas interfaces e objetos Binder sejam compartilhados por interfaces
Binder. As interfaces AIDL geralmente usam callbacks como parte das chamadas de método,
como com ITeleportCallback no exemplo anterior. É possível reutilizar objetos de callback entre chamadas para o mesmo método ou para métodos diferentes. Outro uso comum de tipos de interface é para subinterfaces ou objetos de sessão retornados de métodos como ITeleportSession no exemplo anterior. Esse aninhamento permite que diferentes APIs sejam encapsuladas na API ou com base no estado de execução. Por exemplo, uma sessão pode representar
a propriedade de um recurso específico. Quando as interfaces são transmitidas várias vezes ou retornadas ao cliente ou servidor de origem, elas sempre preservam a igualdade de ponteiro do objeto binder subjacente.
Os métodos podem ter zero ou mais argumentos. Os argumentos para métodos podem ser
in, out ou inout. Para saber como isso afeta os tipos de argumentos, consulte
Direcionalidade dos back-ends do AIDL.
Parcelables
Para uma descrição de como criar parcelables específicos do back-end, consulte Parcelables personalizados de back-ends da AIDL.
O Android 10 e versões mais recentes oferecem suporte a definições de parcelable diretamente em AIDL. Esse tipo de parcelable é chamado de parcelable estruturado. Para mais informações sobre como a AIDL estruturada e a estável se relacionam no compilador AIDL e no nosso sistema de build, consulte AIDL estruturada comparada à estável.
Exemplo:
package my.package;
import my.package.Boo;
parcelable Baz {
@utf8InCpp String name = "baz";
Boo boo;
}
União
O Android 12 e versões mais recentes oferecem suporte a declarações de união com tag. Exemplo:
package my.package;
import my.package.FooSettings;
import my.package.BarSettings;
union Settings {
FooSettings fooSettings;
BarSettings barSettings;
@utf8InCpp String str;
int number;
}
Consulte União de back-ends AIDL para detalhes específicos do back-end.
Enumerações
O Android 11 e versões mais recentes oferecem suporte a declarações de enumeração. Exemplo:
package my.package;
enum Boo {
A = 1 * 4,
B = 3,
}
Declarações de tipo aninhadas
O Android 13 e versões mais recentes são compatíveis com declarações de tipo aninhadas. Exemplo:
package my.package;
import my.package.Baz;
interface IFoo {
void doFoo(Baz.Nested nested); // defined in my/package/Baz.aidl
void doBar(Bar bar); // defined below
parcelable Bar { ... } // nested type definition
}
Constantes
Interfaces AIDL personalizadas, parcelables e unions também podem conter constantes de números inteiros e strings, como:
const @utf8InCpp String HAPPY = ":)";
const String SAD = ":(";
const byte BYTE_ME = 1;
const int ANSWER = 6 * 7;
Expressões constantes
Constantes, tamanhos de matrizes e enumeradores da AIDL podem ser especificados usando expressões constantes. As expressões podem usar parênteses para aninhar operações. Valores de expressão constante podem ser usados com valores integrais ou de ponto flutuante.
Os literais true e false representam valores booleanos. Valores com um ., mas sem um sufixo, como 3.8, são considerados valores duplos. Os valores de ponto flutuante têm o sufixo f, como 2.4f. Um valor inteiro com o sufixo l ou L indica um valor longo de 64 bits. Caso contrário, os valores integrais recebem o menor tipo assinado que preserva o valor entre 8 bits (byte), 32 bits (int) e 64 bits (long). Portanto, 256 é considerado um int, mas 255 + 1
transborda para ser o byte 0. Valores hexadecimais, como 0x3, são primeiro interpretados como o menor tipo não assinado que preserva o valor entre 32 e 64 bits e, em seguida, reinterpretados como valores não assinados. Portanto, 0xffffffff tem o valor int
-1. No Android 13 e versões mais recentes, o sufixo u8 pode ser
adicionado a constantes, como 3u8, para representar um valor byte. Esse sufixo é importante para que um cálculo, como 0xffu8 * 3, seja interpretado como -3 com o tipo byte, enquanto 0xff * 3 é 765 com o tipo int.
Os operadores compatíveis têm semântica C++ e Java. Em ordem da precedência mais baixa para a mais alta, os operadores binários são || && | ^ & == != < > <= >= << >> + - * / %. Os operadores unários são + - ! ~.