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
Todos os arquivos AIDL começam com um pacote opcional que corresponde aos nomes dos pacotes em vários backends. Uma declaração de pacote se parece com isso:
package my.package;
Semelhante ao Java, os arquivos AIDL devem estar em uma estrutura de pastas que corresponda ao seu pacote. Os arquivos com o pacote my.package
devem estar na pasta my/package/
.
Tipos
Em arquivos AIDL, há muitos lugares onde os tipos podem ser especificados. Para obter uma lista exata de tipos com suporte na linguagem AIDL, consulte Tipos de back-end AIDL.
Anotações
Várias partes da linguagem AIDL suportam anotações. Para obter uma lista de anotações e onde elas podem ser aplicadas, consulte Anotações AIDL .
Importações
Para usar tipos definidos em outras interfaces, você deve primeiro adicionar dependências no sistema de compilação. Nos cc_*
e java_*
Soong, onde os arquivos .aidl
são usados diretamente sob srcs
nas compilações da plataforma Android, você pode adicionar diretórios usando o campo aidl: { include_dirs: ... }
. Para importações usando aidl_interface
, veja aqui .
Uma importação se parece com isso:
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 namespace):
import Foo; // same as my.package.Foo
Definindo Tipos
Os arquivos AIDL geralmente definem tipos que são usados como uma interface.
Interfaces
Aqui está 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 unidirecionais ( oneway
oneway void doFoo()
) ou síncronos. Se uma interface for definida como unidirecional ( oneway
oneway interface ITeleport {...}
), todos os métodos nela serão implicitamente oneway
. Os métodos Oneway são despachados de forma assíncrona e não podem retornar um resultado. Métodos unidirecionais do mesmo encadeamento para o mesmo fichário também têm garantia de execução serial (embora potencialmente em encadeamentos diferentes). Para obter uma discussão sobre como configurar encadeamentos, consulte gerenciamento de encadeamentos de back-ends AIDL .
Os métodos podem ter zero ou mais argumentos. Argumentos para métodos podem ser in
, out
ou inout
. Para obter uma discussão sobre como isso afeta os tipos de argumentos, consulte direcionalidade de back-ends AIDL .
Parceláveis
Para obter uma descrição de como criar parcelables específicos de back-end, AIDL back-ends parcelables personalizados .
O Android 10 e superior suportam declarações parceladas diretamente no AIDL. Por exemplo:
package my.package;
import my.package.Boo;
parcelable Baz {
@utf8InCpp String name = "baz";
Boo boo;
}
Sindicatos
O Android 12 e superior suportam declarações sindicais. Por exemplo:
package my.package;
import my.package.FooSettings;
import my.package.BarSettings;
union Settings {
FooSettings fooSettings;
BarSettings barSettings;
@utf8InCpp String str;
int number;
}
Enums
O Android 11 e superior são compatíveis com declarações de enumeração. Por exemplo:
package my.package;
enum Boo {
A = 1 * 4,
B = 3,
}
Declarações de tipo aninhado
O Android T (AOSP experimental) e superior são compatíveis com 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 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 AIDL, tamanhos de matriz e 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.
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 o sufixo l
ou L
indica um valor longo de 64 bits. Caso contrário, os valores de integrais obtêm o menor tipo com sinal de preservação de valor entre 8 bits (byte), 32 bits (int) e 64 bits (long). Então 256
é considerado um int
, mas 255 + 1
estoura para ser o byte
0
. Os valores hexadecimais, como 0x3
, são interpretados primeiro como o menor tipo sem sinal de preservação de valor entre 32 bits e 64 bits e, em seguida, reinterpretados como valores sem sinal. Portanto, 0xffffffff
tem o valor int
-1
. A partir do Android T (AOSP experimental), o sufixo u8
pode ser adicionado a constantes, como 3u8
, para representar um valor de byte
. Este sufixo é importante para que um cálculo, como 0xffu8 * 3
, seja interpretado como -3
com tipo byte
enquanto 0xff * 3
é 765
com tipo int
.
Os operadores suportados têm semântica C++ e Java. Na ordem da menor para a maior precedência, os operadores binários são || && | ^ & == != < > <= >= << >> + - * / %
. Operadores unários são + - ! ~
.