Język AIDL

Język AIDL jest luźno oparty na języku Java. Pliki określają umowę interfejsu oraz różne typy danych i stałe używane w tej umowie.

Przesyłka

Każdy plik AIDL rozpoczyna się od opcjonalnego pakietu, który odpowiada nazwom pakietów w różnych backendach. Deklaracja pakietu wygląda tak:

    package my.package;

Podobnie jak w przypadku Javy, pliki AIDL muszą mieć strukturę folderów pasującą do swojego pakietu. Pliki z pakietem my.package muszą znajdować się w folderze my/package/.

Rodzaje

W plikach AIDL można określić wiele typów. Dokładną listę typów backendów obsługiwanych w języku AIDL znajdziesz w artykule Typy backendów AIDL.

Adnotacje

Niektóre fragmenty języka AIDL obsługują adnotacje. Listę adnotacji wraz z miejscami, w których można je stosować, znajdziesz w artykule Adnotacje AIDL.

Importy

Aby używać typów zdefiniowanych w innych interfejsach, musisz najpierw dodać zależności w systemie kompilacji. W modułach cc_* i java_* Soong, w których pliki .aidl są używane bezpośrednio w srcs w kompilacjach platformy Androida, możesz dodawać katalogi, korzystając z pola aidl: { include_dirs: ... }. Informacje o importowaniu za pomocą aidl_interface znajdziesz tutaj.

Proces importu wygląda tak:

    import some.package.Foo;  // explicit import

Podczas importowania typu do tego samego pakietu pakiet można pominąć. Mimo że pominięcie pakietu może prowadzić do niejednoznacznych błędów importu, gdy typy są określone bez pakietu i umieszczane w globalnej przestrzeni nazw (zwykle wszystkie typy powinny znajdować się w przestrzeni nazw):

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

Zdefiniuj typy

Pliki AIDL zasadniczo definiują typy używane jako interfejsy.

Interfejsy

Oto przykładowy interfejs AIDL:

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

Interfejs definiuje obiekt za pomocą serii metod. Metody mogą być oneway (oneway void doFoo()) lub synchroniczne. Jeśli interfejs jest zdefiniowany jako oneway (oneway interface ITeleport {...}), wszystkie zawarte w nim metody domyślnie mają ustawienie oneway. Metody jednokierunkowe są wysyłane asynchronicznie i nie mogą zwrócić wyniku. Jednokierunkowe metody z tego samego wątku do tego samego powiązania również są wykonywane po kolei (choć potencjalnie w różnych wątkach). Instrukcje konfigurowania wątków znajdziesz w artykule Zarządzanie wątkami backendu AIDL.

Metody mogą mieć zero lub więcej argumentów. Argumenty metod to in, out lub inout. Aby dowiedzieć się, jak wpływa to na typy argumentów, zapoznaj się z informacjami o kierunkach backendów AIDL.

Parcelables

Opis tworzenia pakietów SDK specyficznych dla backendu zawiera artykuł backendy AIDL.

Android 10 i nowsze wersje obsługują parlamentarne definicje bezpośrednio w AIDL. Ten typ przesyłki nazywanej paczkomatem strukturalnym. Więcej informacji o tym, jak uporządkowane i stabilne AIDL są ze sobą powiązane w kompilatorze AIDL i naszym systemie kompilacji, znajdziesz w sekcji Uporządkowane i stabilne AIDL.

Na przykład:

    package my.package;

    import my.package.Boo;

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

Związki

deklaracje dotyczące wsparcia dla Androida 12 i nowszych wersji. Na przykład:

    package my.package;

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

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

Wykazy

Android 11 i nowsze wersje obsługują deklaracje typu enum. Na przykład:

    package my.package;

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

Deklaracje typu zagnieżdżonego

Android 13 i nowsze wersje obsługują deklaracje typu zagnieżdżone. Na przykład:

    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
    }

Stałe

Niestandardowe interfejsy AIDL, obiekty parcelable i sumy mogą też zawierać stałe liczby całkowite i ciągi znaków, takie jak:

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

Wyrażenia stałe

Stałe AIDL, rozmiary tablic i elementy wyliczające można określić za pomocą wyrażeń stałych. W wyrażeniach możesz używać nawiasów do zagnieżdżania operacji. Wartości wyrażeń stałych można używać z wartościami całkowitymi lub zmiennoprzecinkowymi.

Literale true i false reprezentują wartości logiczne. Wartości z ., ale bez sufiksu, np. 3.8, są uznawane za wartości podwójne. Wartości zmiennoprzecinkowe mają sufiks f, np. 2.4f. Wartość całkowita z sufiksem l lub L oznacza wartość 64-bitową. W przeciwnym razie wartości całkowite korzystają z najmniejszego z zachowaniem wartości typu ze znakiem między 8-bitowym (bajtowym), 32-bitowym (int) i 64-bitowym (długim). 256 jest uznawany za int, ale 255 + 1 wykracza poza byte 0. Wartości szesnastkowe, takie jak 0x3, są najpierw interpretowane jako najmniej zachowywany bez znaku, zachowujący wartość z kodu 32-bitowego do 64-bitowego, a następnie interpretowany jako wartości bez znaku. Zatem 0xffffffff ma wartość int -1. Od Androida 13 do stałych, np. 3u8, można dodawać sufiks u8, który reprezentuje wartość byte. Ten sufiks jest ważny, ponieważ obliczenia, takie jak 0xffu8 * 3, są interpretowane jako -3 z typem byte, a 0xff * 3 to 765 z typem int.

Obsługiwane operatory mają semantykę w językach C++ i Java. Operatory binarne są w kolejności od najniższego do najwyższego. Operatory binarne są: || && | ^ & == != < > <= >= << >> + - * / %. Jednoargumentowe operatory to + - ! ~.