AIDL obsługuje adnotacje, które dają kompilatorowi AIDL dodatkowe informacje o elemencie z adnotacjami, co ma również wpływ na wygenerowany kod pośredniczący.
Składnia jest podobna do tej w Javie:
@AnnotationName(argument1=value, argument2=value) AidlEntity
Tutaj AnnotationName
jest nazwą adnotacji, a AidlEntity
jest jednostką AIDL, taką jak interface Foo
, void method()
lub int arg
. Adnotacja jest dołączona do encji, która po niej następuje.
Niektóre adnotacje mogą mieć argumenty umieszczone w nawiasach, jak pokazano powyżej. Adnotacje, które nie zawierają argumentu, nie wymagają nawiasów. Na przykład:
@AnnotationName AidlEntity
Te adnotacje nie są takie same, jak adnotacje w Javie, 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 działają w innych backendach. Mają różne ograniczenia, do których można je podłączyć.
Poniżej znajduje się lista predefiniowanych adnotacji AIDL:
Adnotacje | Dodano w wersji na 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ący wartość null
nullable
deklaruje, że nie można podać wartości jednostki z adnotacją.
Adnotację tę można dołączyć wyłącznie do typów zwracanych metod, parametrów metod i pól, które można dzielić.
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 pierwotnych. Poniżej znajduje się błąd.
void method(in @nullable int a); // int is a primitive type
Ta adnotacja nie ma zastosowania w przypadku zaplecza Java. Dzieje się tak, ponieważ w Javie wszystkie typy inne niż pierwotne są przekazywane przez referencję, która może mieć null
.
W zapleczu CPP @nullable T
mapuje na std::unique_ptr<T>
w systemie Android 11 lub starszym oraz na std::optional<T>
w systemie Android 12 lub nowszym.
W zapleczu NDK @nullable T
zawsze mapuje na std::optional<T>
.
W przypadku typu listowego L
, takiego jak T[]
lub List<T>
, @nullable L
mapuje na std::optional<std::vector<std::optional<T>>>
(lub std::unique_ptr<std::vector<std::unique_ptr<T>>>
w przypadku backendu CPP dla Androida 11 lub starszego).
Istnieje wyjątek od tego mapowania. Gdy T
jest interfejsem IBinder
lub AIDL, @nullable
nie działa. Innymi słowy, zarówno @nullable IBinder
jak i IBinder
w równym stopniu odwzorowują na android::sp<IBinder>
, który już dopuszcza wartość null, ponieważ jest silnym wskaźnikiem (odczyty CPP nadal wymuszają dopuszczalność wartości null, ale typ nadal to android::sp<IBinder>
).
Począwszy od Androida 13, @nullable(heap=true)
może być używane w polach, które można dzielić w celu modelowania typów rekurencyjnych. Nie można używać @nullable(heap=true)
z parametrami metod ani typami zwracanymi. Po dodaniu adnotacji pole jest mapowane na odwołanie przydzielone do sterty std::unique_ptr<T>
w backendach CPP/NDK. @nullable(heap=true)
nie działa w zapleczu Java.
utf8InCpp
utf8InCpp
deklaruje, że String
jest reprezentowany w formacie UTF8 dla zaplecza CPP. Jak sama nazwa wskazuje, adnotacja nie ma zastosowania w przypadku innych backendów. W szczególności String
ma zawsze wartość UTF16 w zapleczu Java i UTF8 w zapleczu NDK.
Tę adnotację można dołączyć wszędzie tam, gdzie można zastosować typ String
, włączając w to wartości zwracane, parametry, deklaracje stałych i pola, które można dzielić.
W przypadku backendu CPP @utf8InCpp String
w AIDL odwzorowuje na std::string
, podczas gdy String
bez adnotacji odwzorowuje na android::String16
, gdzie używany jest UTF16.
Należy zauważyć, że istnienie adnotacji utf8InCpp
nie zmienia sposobu przesyłania łańcuchów przez kabel. Ciągi znaków są zawsze przesyłane przewodowo w formacie UTF16. Ciąg z adnotacjami utf8InCpp
jest konwertowany na UTF16 przed przesłaniem. Po odebraniu ciągu znaków jest on konwertowany z UTF16 na UTF8, jeśli został oznaczony jako utf8InCpp
.
VintfStabilność
VintfStability
deklaruje, że typ zdefiniowany przez użytkownika (interfejs, pakietowanie i wyliczenie) może być używany w całym systemie i domenach dostawców. Zobacz AIDL dla HAL, aby uzyskać więcej informacji na temat współdziałania systemów z dostawcami.
Adnotacja nie zmienia sygnatury typu, ale gdy jest ustawiona, instancja typu jest oznaczana jako stabilna, dzięki czemu może przechodzić przez procesy dostawcy i systemu.
Adnotację można dołączyć wyłącznie do deklaracji typu zdefiniowanego przez użytkownika, jak pokazano poniżej:
@VintfStability
interface IFoo {
....
}
@VintfStability
parcelable Data {
....
}
@VintfStability
enum Type {
....
}
Gdy typ jest opatrzony adnotacją VintfStability
, każdy inny typ, do którego odwołuje się typ, powinien również zostać oznaczony jako taki. W poniższym przykładzie Data
i IBar
powinny być opatrzone 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 {...}
Ponadto pliki AIDL definiujące typy z adnotacją VintfStability
można budować wyłącznie przy użyciu typu modułu aidl_interface
Soong, z właściwością stability
ustawioną na "vintf"
.
aidl_interface {
name: "my_interface",
srcs: [...],
stability: "vintf",
}
Nieobsługiwane użycie aplikacji
Adnotacja UnsupportedAppUsage
oznacza, że typ AIDL z adnotacją jest częścią interfejsu innego niż SDK, który był dostępny dla starszych aplikacji. Aby uzyskać więcej informacji na temat ukrytych interfejsów API, zobacz Ograniczenia dotyczące interfejsów innych niż SDK .
Adnotacja UnsupportedAppUsage
nie ma wpływu na zachowanie wygenerowanego kodu. Adnotacja zawiera wyłącznie adnotację wygenerowanej klasy Java z adnotacją Java o tej samej nazwie.
// in AIDL
@UnsupportedAppUsage
interface IFoo {...}
// in Java
@android.compat.annotation.UnsupportedAppUsage
public interface IFoo {...}
Nie jest to możliwe w przypadku backendów innych niż Java.
Poparcie
Adnotacja Backing
określa typ przechowywania typu wyliczeniowego AIDL.
@Backing(type="int")
enum Color { RED, BLUE, }
W zapleczu CPP powyższe emituje 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
jest byte
, który jest mapowany na int8_t
dla zaplecza CPP.
Argument type
można ustawić tylko na następujące typy całkowite:
-
byte
(szerokość 8 bitów) -
int
(szerokość 32-bitowa) -
long
(szerokość 64-bitowa)
NdkOnlyStableParcelable
NdkOnlyStableParcelable
oznacza deklarację umożliwiającą pakowanie (nie definicję) jako stabilną, dzięki czemu można się do niej odwoływać z innych stabilnych typów AIDL. Działa to podobnie do JavaOnlyStableParcelable
, ale NdkOnlyStableParcelable
oznacza deklarację umożliwiającą pakowanie jako stabilną dla zaplecza NDK, a nie dla Java.
Aby użyć tej opcji parcelowania: * Musisz określić ndk_header
. * Musisz mieć bibliotekę NDK określającą możliwość podzielenia na paczki, a biblioteka musi zostać wkompilowana do biblioteki. Na przykład w podstawowym systemie kompilacji modułu cc_*
użyj static_libs
lub shared_libs
. W przypadku aidl_interface
dodaj bibliotekę w obszarze additional_shared_libraries
w Android.bp
.
JavaOnlyStableParcelable
JavaOnlyStableParcelable
oznacza deklarację umożliwiającą pakowanie (nie definicję) 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 pakietów, aby były stabilne, ich pola są 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 element nadający się do parcelowania był nieustrukturyzowany (lub właśnie zadeklarowany), nie można się do niego odwołać.
parcelable Data; // Data is NOT a structured parcelable
parcelable AnotherData {
Data d; // Error
}
JavaOnlyStableParcelable
umożliwia pominięcie sprawdzenia, gdy pakiet, do którego się odwołujesz, jest już bezpiecznie dostępny w ramach zestawu SDK systemu Android.
@JavaOnlyStableParcelable
parcelable Data;
parcelable AnotherData {
Data d; // OK
}
Wyprowadzenie Java
JavaDerive
automatycznie generuje metody dla typów parcelowanych w backendie Java.
@JavaDerive(equals = true, toString = true)
parcelable Data {
int number;
String str;
}
Adnotacja wymaga dodatkowych parametrów, aby kontrolować, co ma zostać wygenerowane. Obsługiwane parametry to:
-
equals=true
generuje metodyequals
ihashCode
. -
toString=true
generuje metodętoString
, która wypisuje nazwę typu i pól. Na przykład:Data{number: 42, str: foo}
Domyślna Java
JavaDefault
dodany w systemie Android 13 kontroluje, czy generowana jest domyślna obsługa wersjonowania implementacji (dla setDefaultImpl
). Ta podpora nie jest już generowana domyślnie w celu zaoszczędzenia miejsca.
Przejście Java
JavaPassthrough
umożliwia opatrzenie wygenerowanego interfejsu API Java dowolną adnotacją Java.
Poniższe 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 jakikolwiek błąd składni na poziomie Java, nie zostanie on wykryty przez kompilator AIDL, ale przez kompilator Java.
Adnotację tę można dołączyć do dowolnej jednostki AIDL. Ta adnotacja nie jest dostępna w przypadku backendów innych niż Java.
Stały rozmiar
FixedSize
oznacza ustrukturyzowaną paczkę o stałym rozmiarze. Po zaznaczeniu do przesyłki nie będzie można dodawać nowych pól. Wszystkie pola elementu parcelable muszą być również typami o stałym rozmiarze, w tym typami pierwotnymi, wyliczeniami, tablicami o stałym rozmiarze i innymi elementami parcelable oznaczonymi za pomocą FixedSize
.
Nie zapewnia to żadnej gwarancji w przypadku różnych bitowości i nie należy na tym polegać w przypadku komunikacji o mieszanej bitowości.
Deskryptor
Descriptor
wymusza określenie deskryptora interfejsu.
package android.foo;
@Descriptor(value="android.bar.IWorld")
interface IHello {...}
Deskryptor powyższego interfejsu to android.bar.IWorld
. Jeśli brakuje adnotacji Descriptor
, deskryptor będzie miał android.foo.IHello
.
Jest to przydatne do zmiany nazwy już opublikowanego interfejsu. Ujednolicenie deskryptora interfejsu o zmienionej nazwie z deskryptorem interfejsu przed zmianą nazwy umożliwia komunikację między dwoma interfejsami.
@ukryj w komentarzach
Kompilator AIDL rozpoznaje @hide
w komentarzach i przekazuje je do wyjścia Java, aby metalava mogła je przechwycić. Ten komentarz zapewnia, że system kompilacji systemu Android wie, że interfejsy API AIDL nie są interfejsami API zestawu SDK.
@przestarzałe w komentarzach
Kompilator AIDL rozpoznaje @deprecated
w komentarzach jako znacznik 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 przestarzałe jednostki adnotacją/atrybutem specyficznym dla backendu, dzięki czemu kod klienta jest ostrzegany, jeśli odwołuje się do przestarzałych jednostek. Na przykład adnotacja @Deprecated
i znacznik @deprecated
są dołączone do kodu wygenerowanego w języku Java.