A linguagem AIDL é vagamente baseada na linguagem Java. Os arquivos especificam um contrato de interface e vários tipos de dados e constantes usados neste contrato.
Pacote
Cada arquivo AIDL começa com um pacote opcional que corresponde aos nomes dos pacotes em vários back-ends. Uma declaração de pacote tem esta aparência:
package my.package;
Semelhante ao 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 da linguagem AIDL oferecem suporte a anotações. Para conferir 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 é necessário adicionar dependências no
sistema de build. Nos módulos Soong cc_*
e java_*
, em que os arquivos .aidl
são usados
diretamente em srcs
nos builds da plataforma Android, você pode adicionar diretórios
usando o campo aidl: { include_dirs: ... }
. Para importações que usam
aidl_interface
, consulte
este link.
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 no namespace global. Geralmente, todos os tipos precisam receber namespace:
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 {
void teleport(Location baz, float speed);
String getName();
}
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 dela serão
implicitamente oneway
. Os métodos só de ida 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
ver uma discussão sobre como configurar linhas de execução, consulte Gerenciamento de linhas de execução de
back-ends da AIDL.
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 os tipos de argumentos,
consulte
Direcionalidade dos back-ends da AIDL.
Parcelables
Para uma descrição de como criar parcelables específicos do back-end, back-ends da AIDL personalizados.
O Android 10 e versões mais recentes oferecem suporte a 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 no compilador AIDL e no nosso sistema de build, consulte AIDL estruturada e estável.
Por 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. Por 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 enumeração. Por 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. Por 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 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
As constantes AIDL, os tamanhos de matriz e os enumeradores podem ser especificados usando expressões constantes. As expressões podem usar parênteses para aninhar operações. Os valores de expressão constante podem ser usados com valores integrais ou flutuantes.
Os literais true
e false
representam valores booleanos. Valores com um .
, mas
sem um sufixo, como 3.8
, são considerados valores duplos. Valores
flutuantes têm o sufixo f
, como 2.4f
. Um valor integral com o sufixo l
ou
L
indica um valor de 64 bits. Caso contrário, os valores integrais recebem o menor tipo assinado de preservação de valor entre 8 bits (byte), 32 bits (int) e 64 bits (longos). 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 de preservação de valor entre 32 e 64 bits
e, em seguida, reinterpretados como valores não assinados. Portanto, 0xffffffff
tem o valor de int
-1
. No Android 13 e versões mais recentes, o sufixo u8
pode ser
adicionado a constantes, como 3u8
, para representar um valor de 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ânticas C++ e Java. Para a precedência mais baixa para a mais alta, os operadores binários são || && | ^ & == != < > <= >= << >> + - * / %
. Os operadores unários são + - ! ~
.