AIDL obsługuje adnotacje, które dostarczają kompilatorowi AIDL dodatkowych informacji o adnotowanym elemencie. Te informacje wpływają też na wygenerowany kod zastępczy.
Składnia jest podobna do składni języka Java:
@AnnotationName(argument1=value, argument2=value) AidlEntity
W tym przykładzie AnnotationName
to nazwa adnotacji, a AidlEntity
to element AIDL, np. interface Foo
, void method()
lub int arg
. Do encji, która następuje po nim, jest dołączona adnotacja.
Niektóre adnotacje mogą mieć argumenty w nawiasach, jak pokazano powyżej. Adnotacje, które nie mają argumentu, nie wymagają nawiasów. Przykład:
@AnnotationName AidlEntity
Te adnotacje różnią się od adnotacji w języku Java, choć wyglądają bardzo podobnie. Użytkownicy nie mogą definiować własnych adnotacji AIDL. Wszystkie adnotacje są zdefiniowane wstępnie. Niektóre adnotacje mają zastosowanie tylko do określonego backendu i nie działają w innych backendach. Mają różne ograniczenia dotyczące tego, do czego mogą być dołączone.
Oto lista wstępnie zdefiniowanych 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 |
nullable
nullable
oznacza, że wartość opatrzonego adnotacją elementu może nie być podana.
Tę adnotację można dołączyć tylko do typów zwracanych przez metodę, parametrów metody i pól możliwych do podzielenia.
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 prymitywnych. 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 w języku Java. Dzieje się tak, ponieważ w języku Java wszystkie typy inne niż prymitywne są przekazywane przez odniesienie, które może być null
.
W backendzie CPP wartość @nullable T
jest mapowana na wartość std::unique_ptr<T>
w Androidzie 11 lub starszym, a na wartość std::optional<T>
w Androidzie 12 lub nowszym.
W backendzie NDK @nullable T
zawsze odpowiada std::optional<T>
.
W backendzie Rust @nullable T
zawsze jest mapowane na Option<T>
.
W przypadku typu L
, np. T[]
lub List<T>
, @nullable L
jest mapowane na std::optional<std::vector<std::optional<T>>>
(lub std::unique_ptr<std::vector<std::unique_ptr<T>>>
w przypadku backendu CPP w Androidzie 11 lub niższym).
Od tego mapowania jest jeden wyjątek. Gdy T
jest IBinder
lub interfejsem AIDL, @nullable
jest bezczynny dla wszystkich backendów z wyjątkiem Rust. Innymi słowy, zarówno @nullable IBinder
, jak i IBinder
mapują się na android::sp<IBinder>
, która jest już typami z możliwością przypisania wartości, ponieważ jest to silny wskaźnik (w przypadku odczytu w C++ nadal jest wymagana możliwość przypisania wartości, ale typ jest nadal android::sp<IBinder>
). W Rust te typy są nullable
tylko wtedy, gdy są opatrzone adnotacją @nullable
. Jeśli są opatrzone adnotacjami, są przypisane do Option<T>
.
Począwszy od Androida 13 możesz używać pola @nullable(heap=true)
do modelowania rekurencyjnych typów za pomocą pól parcelowalnych. @nullable(heap=true)
nie może być używany z parametrami metody ani typami zwracanymi. Gdy jest ono opatrzone adnotacjami, jest mapowane na odwołanie std::unique_ptr<T>
przydzielone na stosie w backendach CPP/NDK. @nullable(heap=true)
nie jest wykonywane w backendzie Java.
utf8InCpp
utf8InCpp
deklaruje, że String
jest reprezentowany w formacie UTF-8 na zapleczu CPP. Jak wskazuje nazwa, adnotacje nie są obsługiwane przez inne backendy.
W szczególności String
jest zawsze w formacie UTF-16 w backendzie Java i w formacie UTF-8 w backendzie NDK.
Tę adnotację można dołączyć wszędzie tam, gdzie można użyć typu String
, w tym w wartościach zwracanych, parametrach, deklaracjach stałych i polach możliwych do podzielenia.
W przypadku backendu w C++ parametr @utf8InCpp String
w pliku AIDL jest mapowany na std::string
, natomiast parametr String
bez adnotacji jest mapowany na android::String16
, gdzie używany jest format UTF-16.
Pamiętaj, że obecność adnotacji utf8InCpp
nie zmienia sposobu przesyłania ciągów znaków przez sieć. Ciągi znaków są zawsze przesyłane w formacie UTF16. Przed przesłaniem ciąg znaków z adnotacjami utf8InCpp
jest konwertowany na UTF16. Gdy otrzymany ciąg znaków został oznaczony jako utf8InCpp
, jest on konwertowany z UTF16 na UTF8.
VintfStability
VintfStability
deklaruje, że typ zdefiniowany przez użytkownika (interface, parcelable, enum) może być używany w domenie systemu i dostawcy. Więcej informacji o interoperacyjności dostawców systemów znajdziesz w AIDL dla HAL-i.
Adnotacja nie zmienia sygnatury typu, ale po jej ustawieniu instancja typu jest oznaczana jako stabilna, aby mogła być przekazywana przez procesy dostawcy i systemu.
Adnotację można dołączyć tylko do deklaracji typu zdefiniowanego przez użytkownika, jak pokazano tutaj:
@VintfStability
interface IFoo {
....
}
@VintfStability
parcelable Data {
....
}
@VintfStability
enum Type {
....
}
Jeśli typ jest opatrzony adnotacją VintfStability
, każdy inny typ, do którego się odwołuje, powinien być również opatrzony adnotacją. W tym przykładzie Data
i IBar
powinny być oznaczone jako 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 opatrzone adnotacjami VintfStability
można budować tylko za pomocą typu modułu Soong aidl_interface
, przy czym właściwość stability
ma wartość "vintf"
.
aidl_interface {
name: "my_interface",
srcs: [...],
stability: "vintf",
}
UnsupportedAppUsage
Adnotacja UnsupportedAppUsage
oznacza, że oznaczony typ AIDL jest częścią interfejsu spoza pakietu SDK, który był dostępny dla starszych aplikacji.
Więcej informacji o ukrytych interfejsach API znajdziesz w artykule Ograniczenia dotyczące interfejsów API innych niż szkielety aplikacji.
Adnotacja UnsupportedAppUsage
nie wpływa na działanie wygenerowanego kodu. Adnotacja dotyczy tylko wygenerowanej klasy Java i ma taką samą nazwę.
// in AIDL
@UnsupportedAppUsage
interface IFoo {...}
// in Java
@android.compat.annotation.UnsupportedAppUsage
public interface IFoo {...}
Ta opcja nie jest dostępna w przypadku backendów innych niż Java.
Podparcie
Adnotacja Backing
określa typ pamięci masowej dla typu enum AIDL.
@Backing(type="int")
enum Color { RED, BLUE, }
W backendzie CPP generuje to klasę typu enum C++ o typie int32_t
.
enum class Color : int32_t {
RED = 0,
BLUE = 1,
}
Jeśli pominiesz adnotację, zostanie domyślnie przyjęta wartość type
, która w systemie backend CPP jest mapowana na wartość int8_t
.byte
Argument type
może przyjmować tylko te typy nieujemne:
byte
(8-bitowa szerokość)int
(32-bitowa szerokość)long
(64-bitowa szerokość)
NdkOnlyStableParcelable
NdkOnlyStableParcelable
oznacza deklarację z możliwością zapakowania (nie definicji) jako stabilną, aby można było się do niej odwoływać z innych stabilnych typów AIDL. Jest to podobne do JavaOnlyStableParcelable
, ale NdkOnlyStableParcelable
oznacza deklarację parcelable jako stabilną dla backendu NDK, a nie dla Javy.
Aby użyć tej funkcji:
- Musisz podać
ndk_header
. - Musisz mieć bibliotekę NDK, która określa obiekt Parcelable, a biblioteka musi być skompilowana w bibliotece. Na przykład w systemie kompilacji rdzenia w module
cc_*
użyj funkcjistatic_libs
lubshared_libs
. W przypadkuaidl_interface
dodaj bibliotekę w sekcjiadditional_shared_libraries
wAndroid.bp
.
JavaOnlyStableParcelable
JavaOnlyStableParcelable
oznacza deklarację z możliwością zapakowania (nie definicji) jako stabilną, aby można było się do niej odwoływać z innych stabilnych typów AIDL.
Stabilny interfejs AIDL wymaga, aby wszystkie typy zdefiniowane przez użytkownika były stabilne. W przypadku obiektów z możliwością zapakowania 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 go odwoływać.
parcelable Data; // Data is NOT a structured parcelable
parcelable AnotherData {
Data d; // Error
}
JavaOnlyStableParcelable
pozwala zastąpić sprawdzanie, gdy referencje do obiektu parcelable są już bezpiecznie dostępne w pakiecie SDK Androida.
@JavaOnlyStableParcelable
parcelable Data;
parcelable AnotherData {
Data d; // OK
}
JavaDerive
JavaDerive
automatycznie generuje metody dla typów parcelable w backendzie Java.
@JavaDerive(equals = true, toString = true)
parcelable Data {
int number;
String str;
}
Aby określić, co ma zostać wygenerowane, adnotacja wymaga dodatkowych parametrów. Obsługiwane parametry:
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 Androidzie 13, określa, czy domyślna obsługa wersji implementacji jest generowana (w przypadku setDefaultImpl
). Domyślnie nie jest już generowana, aby oszczędzać miejsce.
JavaPassthrough
JavaPassthrough
pozwala na adnotację wygenerowanego interfejsu Java API dowolną adnotacją Java.
te adnotacje w pliku 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 Javy, nie zostanie on wykryty przez kompilator AIDL, ale przez kompilator Javy.
Tę adnotację można dołączyć do dowolnej jednostki AIDL. Ta adnotacja jest ignorowana w przypadku backendów innych niż Java.
RustDerive
RustDerive
automatycznie wdraża cechy dla wygenerowanych typów Rust.
Aby określić, co ma zostać wygenerowane, adnotacja wymaga dodatkowych parametrów. Obsługiwane parametry:
Copy=true
Clone=true
Ord=true
PartialOrd=true
Eq=true
PartialEq=true
Hash=true
Wyjaśnienia tych cech znajdziesz na stronie https://doc.rust-lang.org.
FixedSize
FixedSize
oznacza strukturę parcelable jako o stałym rozmiarze. Po oznaczeniu nie będzie można dodawać do niego nowych pól. Wszystkie pola obiektu parcelable muszą być typu o stałym rozmiarze, w tym typów prymitywnych, enumeracji, tablic o stałym rozmiarze i innych obiektów parcelable oznaczonych za pomocą FixedSize
.
Nie zapewnia to żadnej gwarancji w przypadku różnych głębokości bitów i nie należy polegać na tym w przypadku komunikacji z różną głębokością bitów.
Deskryptor
Descriptor
określa interfejs domyślnie.
package android.foo;
@Descriptor(value="android.bar.IWorld")
interface IHello {...}
Deskryptor tego interfejsu to android.bar.IWorld
. Jeśli brak adnotacji Descriptor
, opis będzie wyglądał tak: android.foo.IHello
.
Jest to przydatne, gdy chcesz zmienić nazwę już opublikowanego interfejsu. Ustawienie identycznego deskryptora przemianowanego interfejsu co deskryptora interfejsu przed przemianą umożliwia wzajemną komunikację obu interfejsów.
@hide w komentarzach
Kompilator AIDL rozpoznaje @hide
w komentarzach i przekazuje go do danych wyjściowych w języku Java, aby Metalava mogła je pobrać. Dzięki temu komentarzowi system kompilacji Androida wie, że interfejsy AIDL API nie są interfejsami SDK API.
@deprecated w komentarzach
Kompilator AIDL rozpoznaje @deprecated
w komentarzach jako tag identyfikujący element AIDL, którego nie należy już używać.
interface IFoo {
/** @deprecated use bar() instead */
void foo();
void bar();
}
Każdy backend oznacza wycofane elementy za pomocą adnotacji lub atrybutu specyficznego dla backendu, aby w przypadku odwołania do wycofanego elementu wyświetlić ostrzeżenie w kodzie klienta. Na przykład do wygenerowanego kodu Java dołączone są adnotacje @Deprecated
i tag @deprecated
.