AIDL obsługuje adnotacje, które dostarczają kompilatorowi AIDL dodatkowych informacji o elementach z adnotacjami. Ma to też wpływ na wygenerowany kod stub.
Składnia jest podobna do składni Javy:
@AnnotationName(argument1=value, argument2=value) AidlEntity
W tym przypadku AnnotationName
to nazwa adnotacji, a AidlEntity
to jednostka AIDL, np. interface Foo
, void method()
lub int arg
. Adnotacja jest dołączona do podmiotu, który po niej następuje.
Niektóre adnotacje mogą mieć argumenty ustawione w nawiasach, jak pokazano powyżej. Adnotacje, które nie mają argumentu, nie wymagają nawiasów. Na przykład:
@AnnotationName AidlEntity
Te adnotacje nie są takie same jak adnotacje Java, chociaż wyglądają bardzo podobnie. Użytkownicy nie mogą definiować niestandardowych adnotacji AIDL. Wszystkie adnotacje są wstępnie zdefiniowane. Niektóre adnotacje wpływają tylko na określony backend i nie mają żadnego działania w innych backendach. Mają one różne ograniczenia dotyczące tego, do czego można je dołączyć.
Oto lista wstępnie zdefiniowanych adnotacji AIDL:
Adnotacje | Dodano w wersji Androida |
---|---|
nullable |
7 |
utf8InCpp |
7 |
VintfStability |
11 |
UnsupportedAppUsage |
10 |
Hide |
11 |
Backing |
11 |
NdkOnlyStableParcelable |
14 |
JavaOnlyStableParcelable |
11 |
JavaDerive |
12 |
JavaPassthrough |
12 |
FixedSize |
12 |
Descriptor |
12 |
dopuszczająca wartość null
nullable
oznacza, że wartość adnotowanego elementu może nie być podana.
Tę adnotację można dołączyć tylko do typów zwracanych przez metody, parametrów metod i pól z możliwością przekazywania.
interface IFoo {
// method return types
@nullable Data method();
// method parameters
void method2(in @nullable Data d);
}
parcelable Data {
// parcelable fields
@nullable Data d;
}
Adnotacji nie można dołączać do typów prostych. Wystąpił błąd.
void method(in @nullable int a); // int is a primitive type
W przypadku systemu zaplecza Java ta adnotacja nie ma żadnego efektu. Dzieje się tak, ponieważ w języku Java wszystkie typy inne niż proste są przekazywane przez odwołanie, co może być null
.
W backendzie CPP @nullable T
jest mapowane na std::unique_ptr<T>
na Androidzie 11 lub starszym oraz na std::optional<T>
na Androidzie 12 lub nowszym.
W NDK @nullable T
zawsze odpowiada std::optional<T>
.
W backendzie Rusta znak @nullable T
zawsze jest mapowany na znak Option<T>
.
W przypadku typu listy L
, np. T[]
lub List<T>
, @nullable L
jest mapowany na std::optional<std::vector<std::optional<T>>>
(lub std::unique_ptr<std::vector<std::unique_ptr<T>>>
w przypadku backendu CPP na Androidzie 11 lub starszym).
Od tego mapowania jest wyjątek. Gdy T
jest IBinder
lub interfejsem AIDL, @nullable
nie ma wpływu na wszystkie backendy z wyjątkiem Rusta. Innymi słowy, zarówno @nullable IBinder
, jak i IBinder
są mapowane na android::sp<IBinder>
, które jest już dopuszczalne, ponieważ jest silnym wskaźnikiem (odczyty w C++ nadal wymuszają dopuszczalność, ale typ to nadal android::sp<IBinder>
). W Rust te typy to nullable
tylko wtedy, gdy są oznaczone adnotacją @nullable
. Jeśli są oznaczone, są przypisane do Option<T>
.
Od Androida 13 można używać adnotacji @nullable(heap=true)
w polach z możliwością przekazywania w pakietach do modelowania typów rekurencyjnych. @nullable(heap=true)
nie można używać z parametrami metod ani typami zwracanymi. Jeśli pole jest oznaczone tym adnotacją, jest ono mapowane na referencję przydzieloną na stercie std::unique_ptr<T>
w backendach CPP/NDK. W backendzie Java funkcja @nullable(heap=true)
nie wykonuje żadnych działań.
utf8InCpp
utf8InCpp
deklaruje, że String
jest reprezentowany w formacie UTF8 na potrzeby backendu CPP. Jak sama nazwa wskazuje, ta adnotacja nie ma wpływu na inne systemy backendowe.
W szczególności String
jest zawsze kodowany w formacie UTF16 w przypadku backendu Java i UTF8 w przypadku backendu NDK.
Tę adnotację można dołączyć w dowolnym miejscu, w którym można użyć typu String
, w tym w przypadku wartości zwracanych, parametrów, deklaracji stałych i pól z możliwością przekazywania.
W przypadku backendu CPP @utf8InCpp String
w AIDL jest mapowane na std::string
, a String
bez adnotacji jest mapowane na android::String16
, gdzie używane jest kodowanie UTF16.
Pamiętaj, że obecność adnotacji utf8InCpp
nie zmienia sposobu przesyłania ciągów znaków. Ciągi znaków są zawsze przesyłane jako UTF16. Przed przesłaniem utf8InCpp
adnotowany ciąg znaków jest konwertowany na format UTF16. Gdy ciąg znaków zostanie odebrany, jest konwertowany z UTF16 na UTF8, jeśli został oznaczony jako utf8InCpp
.
VintfStability
VintfStability
deklaruje, że zdefiniowany przez użytkownika typ (interfejs, obiekt do serializacji, i wyliczenie) może być używany w domenach systemowych i dostawcy. Więcej informacji o współdziałaniu systemu z dostawcą znajdziesz w artykule AIDL dla HAL-i.
Adnotacja nie zmienia sygnatury typu, ale gdy jest ustawiona, instancja typu jest oznaczana jako stabilna, dzięki czemu może być przekazywana między procesami dostawcy i systemu.
Adnotację można dołączyć tylko do deklaracji typów zdefiniowanych przez użytkownika, jak pokazano tutaj:
@VintfStability
interface IFoo {
....
}
@VintfStability
parcelable Data {
....
}
@VintfStability
enum Type {
....
}
Jeśli typ jest oznaczony adnotacją VintfStability
, każdy inny typ, do którego odwołuje się ten typ, powinien być również oznaczony w ten sposób. W poniższym przykładzie oba elementy Data
i IBar
powinny być oznaczone adnotacją VintfStability
.
@VintfStability
interface IFoo {
void doSomething(in IBar b); // references IBar
void doAnother(in Data d); // references Data
}
@VintfStability // required
interface IBar {...}
@VintfStability // required
parcelable Data {...}
Dodatkowo pliki AIDL definiujące typy oznaczone adnotacją VintfStability
można tworzyć tylko za pomocą typu modułu Soong aidl_interface
, z właściwością stability
ustawioną na "vintf"
.
aidl_interface {
name: "my_interface",
srcs: [...],
stability: "vintf",
}
UnsupportedAppUsage
Adnotacja UnsupportedAppUsage
oznacza, że typ AIDL z adnotacją jest częścią interfejsu innego niż SDK, który był dostępny dla starszych aplikacji.
Więcej informacji o ukrytych interfejsach API znajdziesz w sekcji Ograniczenia dotyczące interfejsów innych niż SDK.
Adnotacja UnsupportedAppUsage
nie wpływa na działanie wygenerowanego kodu. Adnotacja dodaje do wygenerowanej klasy Java tylko adnotację Java o tej samej nazwie.
// in AIDL
@UnsupportedAppUsage
interface IFoo {...}
// in Java
@android.compat.annotation.UnsupportedAppUsage
public interface IFoo {...}
W przypadku backendów innych niż Java ta operacja nie ma żadnego efektu.
Podkład
Adnotacja Backing
określa typ pamięci masowej typu wyliczeniowego AIDL.
@Backing(type="int")
enum Color { RED, BLUE, }
W backendzie CPP generuje to klasę wyliczeniową C++ typu int32_t
.
enum class Color : int32_t {
RED = 0,
BLUE = 1,
}
Jeśli adnotacja zostanie pominięta, przyjmuje się, że type
ma wartość byte
, która jest mapowana na int8_t
w przypadku backendu CPP.
Argument type
można ustawić tylko na te typy całkowite:
byte
(8-bitowa)int
(32-bitowa)long
(64-bitowa)
NdkOnlyStableParcelable
NdkOnlyStableParcelable
oznacza deklarację (nie definicję) typu parcelable jako stabilną, dzięki czemu można się do niej odwoływać z innych stabilnych typów AIDL. Działa to podobnie jak JavaOnlyStableParcelable
, ale NdkOnlyStableParcelable
oznacza deklarację z możliwością przekazywania jako stabilną w przypadku backendu NDK, a nie Javy.
Aby użyć tego obiektu Parcelable:
- Musisz podać wartość
ndk_header
. - Musisz mieć bibliotekę NDK określającą obiekt Parcelable, a biblioteka musi być skompilowana w bibliotece. Na przykład w podstawowym systemie kompilacji w module
cc_*
użyjstatic_libs
lubshared_libs
. W przypadku elementuaidl_interface
dodaj bibliotekę w sekcjiadditional_shared_libraries
w elemencieAndroid.bp
.
JavaOnlyStableParcelable
JavaOnlyStableParcelable
oznacza deklarację (nie definicję) typu parcelable jako stabilną, dzięki czemu można się do niej odwoływać z innych stabilnych typów AIDL.
Stabilny AIDL wymaga, aby wszystkie typy zdefiniowane przez użytkownika były stabilne. W przypadku obiektów Parcelable stabilność wymaga, aby ich pola były wyraźnie opisane w pliku źródłowym AIDL.
parcelable Data { // Data is a structured parcelable.
int x;
int y;
}
parcelable AnotherData { // AnotherData is also a structured parcelable
Data d; // OK, because Data is a structured parcelable
}
Jeśli obiekt Parcelable był nieustrukturyzowany (lub tylko zadeklarowany), nie można się do niego odwołać.
parcelable Data; // Data is NOT a structured parcelable
parcelable AnotherData {
Data d; // Error
}
JavaOnlyStableParcelable
pozwala zastąpić sprawdzanie, gdy odwoływany obiekt Parcelable jest już bezpiecznie dostępny w ramach pakietu SDK Androida.
@JavaOnlyStableParcelable
parcelable Data;
parcelable AnotherData {
Data d; // OK
}
JavaDerive
JavaDerive
automatycznie generuje metody dla typów możliwych do przekazania w pakiecie w backendzie Java.
@JavaDerive(equals = true, toString = true)
parcelable Data {
int number;
String str;
}
Adnotacja wymaga dodatkowych parametrów, aby określić, co ma być generowane. Obsługiwane parametry:
equals=true
generuje metodyequals
ihashCode
.toString=true
generuje metodętoString
, która wyświetla nazwę typu i pola. Na przykład:Data{number: 42, str: foo}
JavaDefault
JavaDefault
, dodany w Androidzie 13, określa, czy ma być generowana obsługa wersji domyślnej implementacji (w przypadku setDefaultImpl
). Aby zaoszczędzić miejsce, ta obsługa nie jest już generowana domyślnie.
JavaPassthrough
JavaPassthrough
umożliwia dodanie do wygenerowanego interfejsu Java API dowolnej adnotacji Java.
Adnotacje w AIDL
@JavaPassthrough(annotation="@android.annotation.Alice")
@JavaPassthrough(annotation="@com.android.Alice(arg=com.android.Alice.Value.A)")
stać się
@android.annotation.Alice
@com.android.Alice(arg=com.android.Alice.Value.A)
w wygenerowanym kodzie Java.
Wartość parametru annotation
jest emitowana bezpośrednio. Kompilator AIDL nie sprawdza wartości parametru. Jeśli wystąpi błąd składni na poziomie języka Java, nie zostanie on wykryty przez kompilator AIDL, ale przez kompilator języka Java.
Tę adnotację można dołączyć do dowolnej jednostki AIDL. W przypadku backendów innych niż Java ta adnotacja nie ma żadnego efektu.
RustDerive
RustDerive
automatycznie implementuje cechy dla wygenerowanych typów Rusta.
Adnotacja wymaga dodatkowych parametrów, aby określić, co ma być generowane. Obsługiwane parametry:
Copy=true
Clone=true
Ord=true
PartialOrd=true
Eq=true
PartialEq=true
Hash=true
Wyjaśnienie tych cech znajdziesz na stronie https://doc.rust-lang.org.
FixedSize
FixedSize
oznacza strukturalny obiekt Parcelable jako o stałym rozmiarze. Po oznaczeniu do obiektu
parcelable nie będzie można dodawać nowych pól. Wszystkie pola obiektu Parcelable muszą być też typami o stałym rozmiarze, w tym typami prostymi, wyliczeniowymi, tablicami o stałym rozmiarze i innymi obiektami Parcelable oznaczonymi adnotacją FixedSize
.
Nie daje to żadnej gwarancji w przypadku różnych szerokości bitowych i nie należy na nim polegać w przypadku komunikacji z użyciem różnych szerokości bitowych.
Deskryptor
Descriptor
wymusza określenie deskryptora interfejsu.
package android.foo;
@Descriptor(value="android.bar.IWorld")
interface IHello {...}
Deskryptor tego interfejsu to android.bar.IWorld
. Jeśli brakuje adnotacji Descriptor
, opis będzie wyglądać tak: android.foo.IHello
.
Jest to przydatne w przypadku zmiany nazwy opublikowanego już interfejsu. Ustawienie deskryptora zmienionego interfejsu na taki sam jak deskryptor interfejsu przed zmianą nazwy umożliwia komunikację między tymi dwoma interfejsami.
@hide w komentarzach
Kompilator AIDL rozpoznaje symbol @hide
w komentarzach i przekazuje go do danych wyjściowych w języku Java, aby mógł go odczytać program Metalava. Ten komentarz zapewnia, że system kompilacji Androida wie, że interfejsy API AIDL nie są interfejsami API pakietu SDK.
@deprecated w komentarzach
Kompilator AIDL rozpoznaje znak @deprecated
w komentarzach jako tag identyfikujący jednostkę AIDL, która nie powinna być już używana.
interface IFoo {
/** @deprecated use bar() instead */
void foo();
void bar();
}
Każdy backend oznacza wycofane jednostki za pomocą adnotacji lub atrybutu specyficznego dla backendu, aby ostrzegać kod klienta, jeśli odwołuje się on do wycofanych jednostek. Na przykład adnotacja @Deprecated
i tag @deprecated
są dołączane do wygenerowanego kodu Java.