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 składni Javy:
@AnnotationName(argument1=value, argument2=value) AidlEntity
W tym przypadku AnnotationName
jest nazwą adnotacji, a AidlEntity
jest jednostką AIDL, taką jak interface Foo
, void method()
lub int arg
. Adnotacja jest dołączona do jednostki, która po niej następuje.
Niektóre adnotacje mogą mieć argumenty umieszczone w nawiasach, jak pokazano powyżej. Adnotacje bez 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 działają w innych backendach. Mają różne ograniczenia, do których można je przywiązać.
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 |
JavaOnlyStableParcelable | 11 |
JavaDerive | 12 |
JavaPassthrough | 12 |
FixedSize | 12 |
Descriptor | 12 |
nullable
nullable
deklaruje, że nie można podać wartości jednostki z adnotacjami.
Ta adnotacja może być dołączona tylko do typów zwracanych metod, parametrów metod i pól paczkowanych.
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. Oto błąd.
void method(in @nullable int a); // int is a primitive type
Ta adnotacja jest niedostępna dla backendu Java. Dzieje się tak, ponieważ w Javie wszystkie typy nieprymitywne są przekazywane przez referencję, co może mieć null
.
W zapleczu CPP @nullable T
mapuje na std::unique_ptr<T>
w systemie Android 11 lub nowszym oraz 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 do std::optional<std::vector<std::optional<T>>>
(lub std::unique_ptr<std::vector<std::unique_ptr<T>>>
w przypadku backendu CPP dla systemu Android 11 lub starszego).
Istnieje wyjątek od tego mapowania. Gdy T
jest interfejsem IBinder
lub AIDL, @nullable
oznacza brak operacji. Innymi słowy, zarówno @nullable IBinder
, jak i IBinder
równym stopniu mapują na android::sp<IBinder>
, który już dopuszcza wartość null, ponieważ jest silnym wskaźnikiem (odczyty CPP nadal wymuszają wartość null, ale typ nadal to android::sp<IBinder>
).
Począwszy od Androida 13, @nullable(heap=true)
może być używany dla pól parcelowalnych do modelowania typów rekurencyjnych. @nullable(heap=true)
nie można używać z parametrami metody ani typami zwracanymi. Po opatrzeniu adnotacją pole jest mapowane na przydzieloną stertę referencję std::unique_ptr<T>
w backendach CPP/NDK. @nullable(heap=true)
nie działa w backendzie Java.
utf8InCpp
utf8InCpp
deklaruje, że String
jest reprezentowany w formacie UTF8 dla backendu CPP. Jak sama nazwa wskazuje, adnotacja jest niedostępna dla innych backendów. W szczególności, String
jest zawsze UTF16 w zapleczu Java i UTF8 w zapleczu NDK.
Ta adnotacja może być dołączona wszędzie tam, gdzie może być użyty typ String
, w tym wartości zwracane, parametry, deklaracje stałych i pola parcelable.
W przypadku zaplecza CPP, @utf8InCpp String
w AIDL mapuje na std::string
, podczas gdy String
bez adnotacji mapuje na android::String16
, gdzie używany jest UTF16.
Zauważ, że istnienie adnotacji utf8InCpp
nie zmienia sposobu, w jaki ciągi są przesyłane przez przewód. Ciągi są zawsze przesyłane w sieci jako UTF16. Ciąg z adnotacjami utf8InCpp
jest konwertowany na UTF16 przed przesłaniem. Po odebraniu ciągu jest on konwertowany z UTF16 na UTF8, jeśli został oznaczony jako utf8InCpp
.
VintfStabilność
VintfStability
deklaruje, że typ zdefiniowany przez użytkownika (interfejs, parcelable i enum) może być używany w całym systemie i domenach dostawców. Zobacz AIDL dla warstw HAL, aby uzyskać więcej informacji na temat współdziałania systemu z dostawcą.
Adnotacja nie zmienia sygnatury typu, ale gdy jest ustawiona, wystąpienie typu jest oznaczane jako stabilne, dzięki czemu może podróżować między procesami dostawcy i systemu.
Adnotację można dołączyć tylko 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, również powinien być oznaczony jako taki. W poniższym przykładzie Data
i IBar
powinny być opatrzone adnotacjami 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 adnotacjami VintfStability
mogą być budowane tylko 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
wskazuje, że typ AIDL z adnotacjami jest częścią interfejsu innego niż SDK, który był dostępny dla starszych aplikacji. Zobacz Ograniczenia dotyczące interfejsów innych niż SDK, aby uzyskać więcej informacji o ukrytych interfejsach API.
Adnotacja UnsupportedAppUsage
nie wpływa na zachowanie wygenerowanego kodu. Adnotacja opisuje tylko wygenerowaną klasę Java z adnotacją Java o tej samej nazwie.
// in AIDL
@UnsupportedAppUsage
interface IFoo {...}
// in Java
@android.compat.annotation.UnsupportedAppUsage
public interface IFoo {...}
To jest zakaz dla backendów innych niż Java.
Poparcie
Adnotacja Backing
określa typ magazynu typu wyliczenia AIDL.
@Backing(type="int")
enum Color { RED, BLUE, }
W backendzie CPP powyższe emituje klasę enum C++ typu int32_t
.
enum class Color : int32_t {
RED = 0,
BLUE = 1,
}
Jeśli adnotacja zostanie pominięta, zakłada się, że type
jest byte
, który jest mapowany na int8_t
dla backendu CPP.
Argument type
można ustawić tylko na następujące typy całkowite:
-
byte
(8 bitów szerokości) -
int
(szerokość 32-bitowa) -
long
(szerokość 64-bitowa)
JavaTylko stabilna Parcelable
JavaOnlyStableParcelable
oznacza deklarację parcelable (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 parcelables bycie stabilnym wymaga, aby jego 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 element parcelable był nieustrukturyzowany (lub właśnie zadeklarowany), nie można się do niego odnieść.
parcelable Data; // Data is NOT a structured parcelable
parcelable AnotherData {
Data d; // Error
}
JavaOnlyStableParcelable
umożliwia pominięcie kontroli, gdy element parcelable, do którego się odwołujesz, jest już bezpiecznie dostępny jako część Android SDK.
@JavaOnlyStableParcelable
parcelable Data;
parcelable AnotherData {
Data d; // OK
}
JavaPochodna
JavaDerive
automatycznie generuje metody dla typów paczkowalnych w backendzie 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 pola. Na przykład:Data{number: 42, str: foo}
JavaDefault
JavaDefault
, dodana w systemie Android 13, kontroluje, czy generowana jest domyślna obsługa wersji implementacji (dla setDefaultImpl
). To wsparcie nie jest już generowane domyślnie w celu zaoszczędzenia miejsca.
Przekazywanie Java
JavaPassthrough
umożliwia opisywanie wygenerowanego interfejsu Java API za pomocą dowolnej adnotacji Java.
Następujące 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 wychwycony przez kompilator AIDL, ale przez kompilator Java.
Ta adnotacja może być dołączona do dowolnej jednostki AIDL. Ta adnotacja jest niedozwolona dla backendów innych niż Java.
Naprawiono rozmiar
FixedSize
oznacza ustrukturyzowany działek jako stały rozmiar. Po oznaczeniu działki nie będzie można dodać do niej nowych pól. Wszystkie pola parcelable muszą być również typami o stałym rozmiarze, w tym typami pierwotnymi, wyliczeniami, tablicami o stałym rozmiarze i innymi parcelable oznaczonymi przez FixedSize
.
Nie zapewnia to żadnej gwarancji dla różnych bitów i nie należy na nim polegać w przypadku komunikacji o mieszanym bitwie.
Deskryptor
Descriptor
wymusza określenie deskryptora interfejsu.
package android.foo;
@Descriptor(value="android.bar.IWorld")
interface IHello {...}
Deskryptorem powyższego interfejsu jest android.bar.IWorld
. Jeśli brakuje adnotacji Descriptor
, deskryptorem będzie android.foo.IHello
.
Jest to przydatne do zmiany nazwy już opublikowanego interfejsu. Uczynienie deskryptora interfejsu o zmienionej nazwie takim samym jak deskryptor interfejsu przed zmianą nazwy umożliwi dwóm interfejsom komunikowanie się ze sobą.
@ukryj w komentarzach
Kompilator AIDL rozpoznaje @hide
w komentarzach i przekazuje go do wyjścia Java, aby metalava mogła go pobrać. 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, aby kod klienta był ostrzegany, jeśli odwołuje się do przestarzałych jednostek. Na przykład adnotacja @Deprecated
i tag @deprecated
są dołączone do kodu wygenerowanego w języku Java.