A linguagem AIDL é vagamente baseada na linguagem Java. Os arquivos especificam um contrato de interface de usuário e vários tipos de dados e constantes usados neste contrato.
Pacote
Cada arquivo AIDL começa com um pacote opcional que corresponde ao em vários back-ends. Uma declaração de pacote tem esta aparência:
package my.package;
Assim como no 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
Em 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 da AIDL.
Anotações
Várias partes do idioma AIDL oferecem suporte a anotações. Para conferir uma lista de anotações e onde elas podem ser aplicadas, consulte Anotações do AIDL.
Importações
Para usar tipos definidos em outras interfaces, primeiro adicione dependências ao
sistema de build. Nos 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 que usam
aidl_interface
, consulte
aqui.
Uma importação é assim:
import some.package.Foo; // explicit import
Ao importar um tipo no mesmo pacote, o pacote pode ser omitido. No entanto, a omissão do pacote pode levar a erros de importação ambíguos quando os tipos são especificados sem um pacote e colocados em um namespace global (geralmente todos os tipos deve receber namespaces):
import Foo; // same as my.package.Foo
Definir tipos
Os arquivos AIDL geralmente definem tipos que são 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íncrona. Se uma interface for definida como
oneway
(oneway interface ITeleport {...}
), todos os métodos nela serão
implicitamente oneway
. Os métodos de uma via 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 executadas em série (embora potencialmente em diferentes linhas de execução). Para saber
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 de vinculação sejam compartilhados pelo binder
do Google Cloud. As interfaces AIDL frequentemente empregam callbacks como parte de chamadas de método,
como com ITeleportCallback
no exemplo anterior. É possível reutilizar objetos de callback
entre chamadas para o mesmo método ou chamadas para métodos diferentes. Outro
uso comum de tipos de interface é para que subinterfaces ou
objetos de sessão sejam retornados de métodos, como com ITeleportSession
no
exemplo anterior. Esse aninhamento permite que diferentes APIs sejam encapsuladas em
com a API ou com base no estado do ambiente 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 do ponteiro do objeto de vinculação.
Os métodos podem ter zero ou mais argumentos. Os argumentos para os métodos podem ser
in
, out
ou inout
. Para uma discussão sobre como isso afeta tipos de argumentos,
ver
Direcionalidade dos back-ends da AIDL.
Parcelables
Para ver uma descrição de como criar parcelables específicos de back-end, Back-ends AIDL personalizados parcelables.
O Android 10 e versões mais recentes são compatíveis com definições parcelable diretamente na AIDL. Esse tipo de parcelable é chamado de parcelable estruturado. Para mais informações sobre como a AIDL estruturada e estável está relacionada na compilador AIDL e nosso sistema de build, consulte Estruturado versus estável AIDL.
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. Exemplo:
package my.package;
import my.package.FooSettings;
import my.package.BarSettings;
union Settings {
FooSettings fooSettings;
BarSettings barSettings;
@utf8InCpp String str;
int number;
}
Enumerações
O Android 11 e versões mais recentes oferecem suporte a declarações de tipo enumerado. Exemplo:
package my.package;
enum Boo {
A = 1 * 4,
B = 3,
}
Declarações de tipo aninhadas
O Android 13 e versões mais recentes oferecem suporte a declarações de tipo aninhado. 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 uniões também podem conter números inteiros e constantes de string, como:
const @utf8InCpp String HAPPY = ":)";
const String SAD = ":(";
const byte BYTE_ME = 1;
const int ANSWER = 6 * 7;
Expressões constantes
Constantes da AIDL, tamanhos de matrizes e enumeradores podem ser especificados usando valores e expressões. As expressões podem usar parênteses para aninhar operações. Constante valores de expressão podem ser usados com valores integrais ou flutuantes.
Os literais true
e false
representam valores booleanos. Valores com .
, mas
sem um sufixo, como 3.8
, são considerados valores duplos. Os valores
flutuantes têm o sufixo f
, como 2.4f
. Um valor integral com os valores l
ou
O sufixo L
indica um valor 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 interpretados pela primeira vez
como o menor tipo não assinado com preservação de valor entre 32 e 64 bits
e reinterpretados como valores não assinados. Portanto, 0xffffffff
tem o valor int
.
-1
A partir do Android 13, 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. Do menor para o
com maior precedência, os operadores binários
|| && | ^ & == != < > <= >= << >> + - * / %
: Os operadores unários são + - ! ~
.