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 backends. Uma declaração de pacote se parece com isto:
package my.package;
Semelhante ao Java, os arquivos AIDL devem estar em uma estrutura de pastas correspondente ao seu pacote. Arquivos com pacote my.package
devem estar na pasta my/package/
.
Tipos
Nos arquivos AIDL, há muitos locais onde os tipos podem ser especificados. Para obter uma lista exata de tipos suportados 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 módulos cc_*
e java_*
Soong, onde os arquivos .aidl
são usados diretamente em 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 fica assim:
import some.package.Foo; // explicit import
Ao importar um tipo no mesmo pacote, o pacote pode ser omitido. Porém, 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 devem ter namespace):
import Foo; // same as my.package.Foo
Definindo Tipos
Os arquivos AIDL geralmente definem tipos que são usados como 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 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 despachados de forma assíncrona e não podem retornar um resultado. Métodos unidirecionais do mesmo thread para o mesmo fichário também têm garantia de execução serial (embora potencialmente em threads diferentes). Para uma discussão sobre como configurar threads, consulte Gerenciamento de threads de back-end AIDL .
Os métodos podem ter zero ou mais argumentos. Os argumentos para métodos podem ser in
, out
ou inout
. Para uma discussão sobre como isso afeta os tipos de argumentos, consulte Direcionalidade de backends AIDL .
Parceláveis
Para obter uma descrição de como criar parcelables específicos de back-end, AIDL back-end parcelables personalizados .
O Android 10 e versões superiores suportam definições parceladas diretamente no AIDL. Este tipo de parcelamento é chamado de parcelamento estruturado. Para obter mais informações sobre como AIDL estruturado e estável estão relacionados no compilador AIDL e em nosso sistema de compilação, consulte AIDL estruturado versus estável .
Por exemplo:
package my.package;
import my.package.Boo;
parcelable Baz {
@utf8InCpp String name = "baz";
Boo boo;
}
Sindicatos
O Android 12 e versões superiores oferecem suporte a 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 versões superiores oferecem suporte a declarações de enum. Por exemplo:
package my.package;
enum Boo {
A = 1 * 4,
B = 3,
}
Declarações de tipo aninhadas
O Android 13 e versões posteriores oferecem suporte a declarações de tipo aninhadas. 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 inteiras e de string, 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 array e enumeradores 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 flutuantes.
literais true
e false
representam valores booleanos. Valores com .
mas sem 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 longo de 64 bits. Caso contrário, os valores integrais obtêm o menor tipo de sinal com preservação de valor entre 8 bits (byte), 32 bits (int) e 64 bits (longo). 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 com preservação de valor entre 32 bits e 64 bits e depois reinterpretados como valores não assinados. Então, 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
. 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. Em ordem de precedência mais baixa para a mais alta, os operadores binários são || && | ^ & == != < > <= >= << >> + - * / %
. Os operadores unários são + - ! ~
.