Przegląd AIDL

Język definicji interfejsu Androida (AIDL) to narzędzie, które pozwala użytkownikom abstrahować od IPC. Mając interfejs (określony w pliku .aidl ), różne systemy kompilacji używają pliku binarnego aidl do konstruowania powiązań C++ lub Java, dzięki czemu ten interfejs może być używany w różnych procesach, niezależnie od środowiska wykonawczego lub bitowości.

AIDL może być używany między dowolnym procesem w systemie Android: między komponentami platformy lub między aplikacjami. Jednak nigdy nie jest używany jako interfejs API dla aplikacji. AIDL może być używany na przykład do implementacji interfejsu API SDK na platformie, ale powierzchnia interfejsu API SDK nigdy nie zawiera bezpośrednio interfejsów API AIDL. Aby uzyskać dokumentację dotyczącą bezpośredniego używania AIDL między aplikacjami, zapoznaj się z odpowiednią dokumentacją dla programistów Androida . Gdy AIDL jest używany między składnikami platformy, które są aktualizowane osobno, takimi jak APEX (od systemu Android 10) lub warstwy HAL (od systemu Android 11), należy użyć systemu kontroli wersji znanego jako stabilny AIDL .

Przykład

Oto przykładowy interfejs AIDL:

    package my.package;

    import my.package.Baz; // defined elsewhere

    interface IFoo {
        void doFoo(Baz baz); // synchronous method
        oneway void doFoo(int a); // async method
    }

Android 10 i nowsze obsługują deklaracje parcelable. Na przykład:

    package my.package;

    import my.package.Boo;

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

Android 11 i nowsze obsługują deklaracje wyliczenia. Na przykład:

    package my.package;

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

Android 12 i nowsze obsługują deklaracje związkowe. 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;
    }

Android T (eksperymentalny AOSP) i nowsze obsługują deklaracje typu zagnieżdżonego. 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
    }

Proces serwera rejestruje interfejs i obsługuje do niego wywołania, a proces klienta wykonuje wywołania tych interfejsów. W wielu przypadkach proces działa zarówno jako klient, jak i serwer, ponieważ może odwoływać się do wielu interfejsów. Aby uzyskać więcej informacji na temat różnych środowisk wykonawczych dostępnych do korzystania z tych interfejsów, zobacz Backendy AIDL . Te deklaracje typu są dokładnie takie jak deklaracje klasy w danym języku, ale działają w różnych procesach.

Jak to działa

AIDL używa sterownika jądra bindera do wykonywania wywołań. Po wykonaniu wywołania identyfikator metody i wszystkie obiekty są pakowane do bufora i kopiowane do zdalnego procesu, w którym wątek wiążący czeka na odczytanie danych. Gdy wątek spinacza otrzyma dane dla transakcji, wyszukuje natywny obiekt pośredniczący w procesie lokalnym, a ta klasa rozpakowuje dane i wywołuje obiekt interfejsu lokalnego. Ten lokalny obiekt interfejsu jest tym, który proces serwera tworzy i rejestruje. Gdy wywołania są wykonywane w tym samym procesie i tym samym zapleczu, nie istnieją żadne obiekty proxy, a zatem wywołania są bezpośrednie, bez pakowania lub rozpakowywania.

Interakcja z usługami na urządzeniu

Android zawiera kilka poleceń umożliwiających interakcję z usługami na urządzeniu. Próbować:

    adb shell dumpsys --help # listing and dumping services
    adb shell service --help # sending commands to services for testing