Langue AIDL

Le langage AIDL est vaguement basé sur le langage Java. Les fichiers spécifient un contrat d'interface et divers types de données et constantes utilisés dans ce contrat.

Forfait

Chaque fichier AIDL commence par un package facultatif qui correspond aux noms de package dans différents backends. Une déclaration de package ressemble à ceci :

    package my.package;

Semblable à Java, les fichiers AIDL doivent se trouver dans une structure de dossiers correspondant à leur package. Les fichiers avec le package my.package doivent se trouver dans le dossier my/package/ .

Les types

Dans les fichiers AIDL, il existe de nombreux endroits où les types peuvent être spécifiés. Pour obtenir une liste exacte des types pris en charge dans le langage AIDL, consultez AIDL backends types .

Remarques

Plusieurs parties du langage AIDL prennent en charge les annotations. Pour une liste des annotations et où elles peuvent être appliquées, voir Annotations AIDL .

Importations

Pour utiliser des types définis dans d'autres interfaces, vous devez d'abord ajouter des dépendances dans le système de génération. Dans cc_* et java_* Soong, où les fichiers .aidl sont utilisés directement sous srcs dans les builds de la plate-forme Android, vous pouvez ajouter des répertoires à l'aide du champ aidl: { include_dirs: ... } . Pour les importations utilisant aidl_interface , voir ici .

Une importation ressemble à ceci :

    import some.package.Foo;  // explicit import

Lors de l'importation d'un type dans le même package, le package peut être omis. Cependant, l'omission du package peut entraîner des erreurs d'importation ambiguës lorsque les types sont spécifiés sans package et placés dans l'espace de noms global (généralement, tous les types doivent être dans un espace de noms) :

    import Foo;  // same as my.package.Foo

Définition des types

Les fichiers AIDL définissent généralement des types qui sont utilisés comme interface.

Interfaces

Voici un exemple d'interface AIDL :

    interface ITeleport {
        void teleport(Location baz, float speed);
        String getName();
    }

Une interface définit un objet avec une série de méthodes. Les méthodes peuvent être unidirectionnelles ( oneway oneway void doFoo() ) ou synchrones. Si une interface est définie comme unidirectionnelle ( interface unidirectionnelle oneway oneway interface ITeleport {...} ), alors toutes les méthodes qu'elle contient sont implicitement oneway . Les méthodes unidirectionnelles sont distribuées de manière asynchrone et ne peuvent pas renvoyer de résultat. Les méthodes unidirectionnelles du même thread vers le même classeur sont également garanties pour s'exécuter en série (bien que potentiellement sur des threads différents). Pour une discussion sur la configuration des threads, consultez AIDL backends thread management .

Les méthodes peuvent avoir zéro ou plusieurs arguments. Les arguments des méthodes peuvent être in , out ou inout . Pour une discussion sur la façon dont cela affecte les types d'arguments, voir AIDL backends directionality .

Colisables

Pour une description de la façon de créer des parcelables spécifiques au backend, AIDL backends custom parcelables .

Android 10 et supérieur prennent en charge les déclarations parcelables directement dans AIDL. Par exemple:

    package my.package;

    import my.package.Boo;

    parcelable Baz {
        @utf8InCpp String name = "baz";
        Boo boo;
    }

Les syndicats

Android 12 et versions ultérieures prennent en charge les déclarations syndicales. Par exemple:

    package my.package;

    import my.package.FooSettings;
    import my.package.BarSettings;

    union Settings {
        FooSettings fooSettings;
        BarSettings barSettings;
        @utf8InCpp String str;
        int number;
    }

Énumérations

Android 11 et versions ultérieures prennent en charge les déclarations d'énumération. Par exemple:

    package my.package;

    enum Boo {
        A = 1 * 4,
        B = 3,
    }

Déclarations de type imbriquées

Android 13 et versions ultérieures prennent en charge les déclarations de type imbriquées. Par exemple:

    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

Les interfaces AIDL personnalisées, les parcelables et les unions peuvent également contenir des constantes entières et de chaîne, telles que :

    const @utf8InCpp String HAPPY = ":)";
    const String SAD = ":(";
    const byte BYTE_ME = 1;
    const int ANSWER = 6 * 7;

Expressions constantes

Les constantes AIDL, les tailles de tableau et les énumérateurs peuvent être spécifiés à l'aide d'expressions constantes. Les expressions peuvent utiliser des parenthèses pour imbriquer des opérations. Les valeurs d'expression constante peuvent être utilisées avec des valeurs entières ou flottantes.

les littéraux true et false représentent des valeurs booléennes. Les valeurs avec un . mais sans suffixe, comme 3.8 , sont considérées comme des valeurs doubles. Les valeurs flottantes ont le suffixe f , comme 2.4f . Une valeur intégrale avec le suffixe l ou L indique une valeur longue de 64 bits. Sinon, les valeurs intégrales obtiennent le plus petit type signé préservant la valeur entre 8 bits (octet), 32 bits (int) et 64 bits (long). Donc 256 est considéré comme un int , mais 255 + 1 déborde pour être l' byte 0 . Les valeurs hexadécimales, telles que 0x3 , sont d'abord interprétées comme le plus petit type non signé préservant la valeur entre 32 bits et 64 bits, puis réinterprétées comme des valeurs non signées. Ainsi, 0xffffffff a la valeur int -1 . À partir d'Android 13, le suffixe u8 peut être ajouté à des constantes, telles que 3u8 , pour représenter une valeur byte . Ce suffixe est important pour qu'un calcul, tel que 0xffu8 * 3 , soit interprété comme -3 avec le type byte alors que 0xff * 3 est 765 avec le type int .

Les opérateurs pris en charge ont une sémantique C++ et Java. Dans l'ordre de priorité la plus faible à la plus élevée, les opérateurs binaires sont || && | ^ & == != < > <= >= << >> + - * / % . Les opérateurs unaires sont + - ! ~ .