Idioma AIDL

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 + - ! ~ .