AIDL supporta le annotazioni che forniscono al compilatore AIDL informazioni aggiuntive sull'elemento annotato, il che influisce anche sul codice stub generato.
La sintassi è simile a quella di Java:
@AnnotationName(argument1=value, argument2=value) AidlEntity
Qui, AnnotationName
è il nome dell'annotazione e AidlEntity
è
un'entità AIDL come interface Foo
, void method()
o int arg
. Un'annotazione
è allegata all'entità che la segue.
Alcune annotazioni possono avere argomenti impostati tra parentesi, come mostrato sopra. Le annotazioni che non hanno un argomento non richiedono le parentesi. Ad esempio:
@AnnotationName AidlEntity
Queste annotazioni non sono le stesse delle annotazioni Java, anche se hanno un aspetto molto simile. Gli utenti non possono definire annotazioni AIDL personalizzate; le annotazioni sono tutte predefinite. Alcune annotazioni interessano solo un determinato backend e non hanno effetto in altri backend. Hanno restrizioni diverse per quanto riguarda i contenuti a cui possono essere allegati.
Di seguito è riportato l'elenco delle annotazioni AIDL predefinite:
Annotazioni | Aggiunta nella versione di Android |
---|---|
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
dichiara che il valore dell'entità annotata non può essere fornito.
Questa annotazione può essere associata solo a tipi restituiti di metodi, parametri di metodi e campi serializzabili.
interface IFoo {
// method return types
@nullable Data method();
// method parameters
void method2(in @nullable Data d);
}
parcelable Data {
// parcelable fields
@nullable Data d;
}
Le annotazioni non possono essere associate a tipi primitivi. Di seguito è riportato un errore.
void method(in @nullable int a); // int is a primitive type
Questa annotazione è no-op per il backend Java. Questo perché, in Java, tutti i tipi non primitivi vengono passati per riferimento, il che potrebbe essere null
.
Nel backend CPP, @nullable T
corrisponde a std::unique_ptr<T>
in Android
11 o versioni precedenti e a std::optional<T>
in Android
12 o versioni successive.
Nel backend NDK, @nullable T
viene sempre mappato a std::optional<T>
.
Nel backend Rust, @nullable T
viene sempre mappato a Option<T>
.
Per un tipo di elenco L
come T[]
o List<T>
, @nullable L
viene mappato a
std::optional<std::vector<std::optional<T>>>
(o
std::unique_ptr<std::vector<std::unique_ptr<T>>>
nel caso del backend CPP
per Android 11 o versioni precedenti).
Esiste un'eccezione a questa mappatura. Quando T
è IBinder
o un'interfaccia AIDL, @nullable
è un'operazione no-op per tutti i backend, ad eccezione di Rust. In altre parole, sia
@nullable IBinder
che IBinder
vengono mappati in modo equivalente a android::sp<IBinder>
, che
è già annullabile perché è un puntatore forte (le letture CPP
applicano ancora l'annullabilità, ma il tipo è ancora android::sp<IBinder>
). In Rust,
questi tipi sono nullable
solo se annotati con @nullable
. Vengono mappati su
Option<T>
se annotati.
A partire da Android 13, @nullable(heap=true)
può essere utilizzato per
i campi parcelable per modellare i tipi ricorsivi. @nullable(heap=true)
non può essere utilizzato
con i parametri del metodo o i tipi restituiti. Quando viene annotato con questo valore, il campo viene mappato a un riferimento allocato nell'heap std::unique_ptr<T>
nei backend CPP/NDK. @nullable(heap=true)
è un'operazione no-op nel backend Java.
utf8InCpp
utf8InCpp
dichiara che un String
è rappresentato in formato UTF8 per il backend CPP. Come indica il nome, l'annotazione è un'operazione no-op per altri backend.
Nello specifico, String
è sempre UTF16 nel backend Java e UTF8 nel backend NDK.
Questa annotazione può essere allegata ovunque sia possibile utilizzare il tipo String
,
inclusi valori restituiti, parametri, dichiarazioni di costanti e campi
parcelable.
Per il backend CPP, @utf8InCpp String
in AIDL viene mappato a std::string
, mentre
String
senza l'annotazione viene mappato a android::String16
dove viene utilizzato UTF16.
Tieni presente che l'esistenza dell'annotazione utf8InCpp
non modifica il modo in cui
le stringhe vengono trasmesse via cavo. Le stringhe vengono sempre trasmesse come UTF16
via cavo. Una stringa annotata utf8InCpp
viene convertita in UTF16 prima di essere
trasmessa. Quando viene ricevuta una stringa, questa viene convertita da UTF16 a UTF8 se
è stata annotata come utf8InCpp
.
VintfStability
VintfStability
dichiara che un tipo definito dall'utente (interfaccia, parcelable e enum) può essere utilizzato nei domini di sistema e del fornitore. Per saperne di più sull'interoperabilità tra sistema e fornitore, consulta
AIDL per HAL.
L'annotazione non modifica la firma del tipo, ma quando viene impostata, l'istanza del tipo viene contrassegnata come stabile in modo che possa essere trasferita tra i processi del fornitore e del sistema.
L'annotazione può essere allegata solo alle dichiarazioni di tipo definite dall'utente come mostrato qui:
@VintfStability
interface IFoo {
....
}
@VintfStability
parcelable Data {
....
}
@VintfStability
enum Type {
....
}
Quando un tipo è annotato con VintfStability
, anche qualsiasi altro tipo a cui viene fatto riferimento nel tipo deve essere annotato come tale. Nel seguente
esempio, Data
e IBar
devono essere entrambi annotati con 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 {...}
Inoltre, i file AIDL che definiscono i tipi annotati con VintfStability
possono essere creati solo utilizzando il tipo di modulo Soong aidl_interface
, con la
proprietà stability
impostata su "vintf"
.
aidl_interface {
name: "my_interface",
srcs: [...],
stability: &
quot;vintf",
}
UnsupportedAppUsage
L'annotazione UnsupportedAppUsage
indica che il tipo AIDL annotato fa parte dell'interfaccia non SDK accessibile per le app legacy.
Per ulteriori informazioni sulle API nascoste, consulta la sezione Limitazioni relative alle interfacce non SDK.
L'annotazione UnsupportedAppUsage
non influisce sul comportamento del codice generato. L'annotazione annota solo la classe Java generata con l'annotazione Java con lo stesso nome.
// in AIDL
@UnsupportedAppUsage
interface IFoo {...}
// in Java
@android.compat.annotation.UnsupportedAppUsage
public interface IFoo {...}
Questa operazione non ha effetto sui backend non Java.
Supporto
L'annotazione Backing
specifica il tipo di archiviazione di un tipo di enumerazione AIDL.
@Backing(type="int")
enum Color { RED
, BLUE, }
Nel backend C++, viene emessa una classe enum C++ di tipo int32_t
.
enum class Color : int32_t {
RED = 0,
BLUE = 1,
}
Se l'annotazione viene omessa, si presuppone che type
sia byte
, che corrisponde
a int8_t
per il backend CPP.
L'argomento type
può essere impostato solo sui seguenti tipi integrali:
byte
(8 bit di larghezza)int
(32 bit di larghezza)long
(64 bit)
NdkOnlyStableParcelable
NdkOnlyStableParcelable
contrassegna una dichiarazione (non una definizione) di parcelable
come stabile, in modo che possa essere referenziata da altri tipi di AIDL stabili. Questo
è simile a JavaOnlyStableParcelable
, ma
NdkOnlyStableParcelable
contrassegna una dichiarazione parcelable come stabile per il backend NDK
anziché per Java.
Per utilizzare questo parcelable:
- Devi specificare
ndk_header
. - Devi disporre di una libreria NDK che specifichi l'oggetto Parcelable e la libreria deve
essere compilata nella libreria. Ad esempio, nel sistema di build principale di un modulo
cc_*
, utilizzastatic_libs
oshared_libs
. Peraidl_interface
, aggiungi la libreria inadditional_shared_libraries
inAndroid.bp
.
JavaOnlyStableParcelable
JavaOnlyStableParcelable
contrassegna una dichiarazione (non una definizione) di parcelable
come stabile, in modo che possa essere referenziata da altri tipi di AIDL stabili.
AIDL stabile richiede che tutti i tipi definiti dall'utente siano stabili. Per i parcelable, la stabilità richiede che i relativi campi siano descritti in modo esplicito nel file sorgente 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
}
Se il parcelable non era strutturato (o era solo dichiarato), non può essere referenziato.
parcelable Data; // Data is NOT a structured parcelable
parcelable AnotherData {
Data d; // Error
}
JavaOnlyStableParcelable
consente di ignorare il controllo quando il parcelable
a cui fai riferimento è già disponibile in modo sicuro nell'ambito dell'SDK Android.
@JavaOnlyStableParcelable
parcelable Data;
parcelable AnotherData {
Data d; // OK
}
JavaDerive
JavaDerive
genera automaticamente metodi per i tipi parcelable nel
backend Java.
@JavaDerive(equals = true, toString = true)
parcelable Data {
int number;
String str;
}
L'annotazione richiede parametri aggiuntivi per controllare cosa generare. I parametri supportati sono:
equals=true
genera i metodiequals
ehashCode
.toString=true
genera il metodotoString
che stampa il nome del tipo e dei campi. Ad esempio:Data{number: 42, str: foo}
JavaDefault
JavaDefault
, aggiunto in Android 13, controlla se
viene generato il supporto del controllo delle versioni dell'implementazione predefinita (per
setDefaultImpl
). Questo supporto non viene più generato per impostazione predefinita per
risparmiare spazio.
JavaPassthrough
JavaPassthrough
consente di annotare l'API Java generata con un'annotazione Java arbitraria.
Le seguenti annotazioni in AIDL
@JavaPassthrough(annotation="@android.annotation.Alice")
@JavaPassthrough(annotation="@com.android.Alice(arg=com.android.Al
ice.Value.A)")
diventare
@android.annotation.Alice
@com.android.Alice(arg=com.android.Alice.Value.A)
nel codice Java generato.
Il valore del parametro annotation
viene emesso direttamente. Il compilatore AIDL
non esamina il valore del parametro. Se è presente un errore di sintassi a livello di Java, non verrà rilevato dal compilatore AIDL, ma dal compilatore Java.
Questa annotazione può essere allegata a qualsiasi entità AIDL. Questa annotazione è un'operazione no-op per i backend non Java.
RustDerive
RustDerive
implementa automaticamente i tratti per i tipi Rust generati.
L'annotazione richiede parametri aggiuntivi per controllare cosa generare. I parametri supportati sono:
Copy=true
Clone=true
Ord=true
PartialOrd=true
Eq=true
PartialEq=true
Hash=true
Per le spiegazioni di queste caratteristiche, visita la pagina https://doc.rust-lang.org.
FixedSize
FixedSize
contrassegna un pacco strutturato come di dimensioni fisse. Una volta contrassegnato, non sarà consentito aggiungere nuovi campi al parcelable. Tutti i campi del
parcelable devono essere anche tipi di dimensioni fisse, inclusi tipi primitivi,
enum, array di dimensioni fisse e altri parcelable contrassegnati con FixedSize
.
Questa opzione non fornisce alcuna garanzia per bitness diverse e non deve essere utilizzata per la comunicazione con bitness miste.
Descrittore
Descriptor
specifica forzatamente il descrittore dell'interfaccia di un'interfaccia.
package android.foo;
@Descriptor(value="android.bar.IWorld")
interface IHe
llo {...}
Il descrittore di questa interfaccia è android.bar.IWorld
. Se l'annotazione
Descriptor
non è presente, il descrittore sarà
android.foo.IHello
.
Questa operazione è utile per rinominare un'interfaccia già pubblicata. Se il descrittore dell'interfaccia rinominata è uguale a quello dell'interfaccia prima della ridenominazione, le due interfacce possono comunicare tra loro.
@hide in comments
Il compilatore AIDL riconosce @hide
nei commenti e lo passa
all'output Java per il recupero da parte di metalava. Questo commento garantisce che il sistema di build di Android sappia che le API AIDL non sono API SDK.
@deprecated nei commenti
Il compilatore AIDL riconosce @deprecated
nei commenti come tag per identificare un'entità AIDL che non deve più essere utilizzata.
interface IFoo {
/** @deprecated use bar() instead */
void foo();
void bar();
}
Ogni backend contrassegna le entità ritirate con un'annotazione o un attributo specifico del backend in modo che il codice client venga avvisato se fa riferimento alle entità ritirate. Ad esempio, l'annotazione @Deprecated
e il tag @deprecated
sono allegati al codice Java generato.