AIDL prend en charge les annotations qui fournissent au compilateur AIDL des informations supplémentaires sur l'élément annoté, ce qui affecte également le code de bouchon généré.
La syntaxe est semblable à celle de Java:
@AnnotationName(argument1=value, argument2=value) AidlEntity
Ici, AnnotationName
est le nom de l'annotation, et AidlEntity
est une entité AIDL telle que interface Foo
, void method()
ou int arg
. Une annotation est associée à l'entité qui la suit.
Pour certaines annotations, des arguments peuvent être définis entre parenthèses, comme illustré ci-dessus. Les annotations sans argument n'ont pas besoin de parenthèses. Exemple :
@AnnotationName AidlEntity
Ces annotations ne sont pas les mêmes que les annotations Java, bien qu'elles semblent très similaires. Les utilisateurs ne peuvent pas définir d'annotations AIDL personnalisées. Les annotations sont toutes prédéfinies. Certaines annotations ne concernent qu'un backend spécifique et n'ont aucun effet sur les autres. Ils sont soumis à des restrictions différentes concernant les éléments auxquels ils peuvent être associés.
Voici la liste des annotations AIDL prédéfinies:
Annotations | Ajouté à la version 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 |
pouvant avoir une valeur nulle
nullable
déclare que la valeur de l'entité annotée ne peut pas être fournie.
Cette annotation ne peut être associée qu'aux types de retour de méthode, aux paramètres de méthode et aux champs parcelables.
interface IFoo {
// method return types
@nullable Data method();
// method parameters
void method2(in @nullable Data d);
}
parcelable Data {
// parcelable fields
@nullable Data d;
}
Les annotations ne peuvent pas être associées à des types primitifs. Voici une erreur.
void method(in @nullable int a); // int is a primitive type
Cette annotation est no-op pour le backend Java. En effet, en Java, tous les types non primitifs sont transmis par référence, qui peut être null
.
Dans le backend CPP, @nullable T
correspond à std::unique_ptr<T>
sous Android 11 ou version antérieure, et à std::optional<T>
sous Android 12 ou version ultérieure.
Dans le backend du NDK, @nullable T
est toujours mappé sur std::optional<T>
.
Dans le backend Rust, @nullable T
est toujours mappé sur Option<T>
.
Pour un type L
semblable à une liste, tel que T[]
ou List<T>
, @nullable L
est mappé sur std::optional<std::vector<std::optional<T>>>
(ou std::unique_ptr<std::vector<std::unique_ptr<T>>>
dans le cas du backend CPP pour Android 11 ou version antérieure).
Il existe une exception à ce mappage. Lorsque T
est IBinder
ou une interface AIDL, @nullable
est une opération sans effet pour tous les backends, sauf pour Rust. En d'autres termes, @nullable IBinder
et IBinder
sont mappés de manière égale sur android::sp<IBinder>
, qui est déjà nullable, car il s'agit d'un pointeur fort (les lectures CPP appliquent toujours la nullabilité, mais le type reste android::sp<IBinder>
). En Rust, ces types ne sont nullable
que s'ils sont annotés avec @nullable
. Ils sont mappés sur Option<T>
s'ils sont annotés.
À partir d'Android 13, @nullable(heap=true)
peut être utilisé pour les champs parcellables afin de modéliser des types récursifs. @nullable(heap=true)
ne peut pas être utilisé avec les paramètres de méthode ni les types de retour. Lorsqu'il est annoté avec cette annotation, le champ est mappé sur une référence std::unique_ptr<T>
allouée dans la pile dans les backend CPP/NDK. @nullable(heap=true)
n'est pas une opération dans le backend Java.
utf8InCpp
utf8InCpp
déclare qu'un String
est représenté au format UTF8 pour le backend CPP. Comme son nom l'indique, l'annotation n'a aucun effet sur les autres backends.
Plus précisément, String
est toujours UTF16 dans le backend Java et UTF8 dans le backend NDK.
Cette annotation peut être associée partout où le type String
peut être utilisé, y compris les valeurs de retour, les paramètres, les déclarations de constantes et les champs parcelables.
Pour le backend CPP, @utf8InCpp String
dans AIDL est mappé sur std::string
, tandis que String
sans l'annotation est mappé sur android::String16
, où UTF16 est utilisé.
Notez que l'existence de l'annotation utf8InCpp
ne modifie pas la manière dont les chaînes sont transmises sur le fil. Les chaînes sont toujours transmises au format UTF-16 sur le fil. Une chaîne annotée utf8InCpp
est convertie en UTF-16 avant d'être transmise. Lorsqu'une chaîne est reçue, elle est convertie d'UTF16 en UTF8 si elle a été annotée comme utf8InCpp
.
VintfStability
VintfStability
déclare qu'un type défini par l'utilisateur (interface, parcelable et enum) peut être utilisé dans les domaines du système et du fournisseur. Pour en savoir plus sur l'interopérabilité entre le système et le fournisseur, consultez la section AIDL pour les HAL.
L'annotation ne modifie pas la signature du type, mais lorsqu'elle est définie, l'instance du type est marquée comme stable afin qu'elle puisse se déplacer entre les processus du fournisseur et du système.
L'annotation ne peut être associée qu'aux déclarations de type définies par l'utilisateur, comme indiqué ci-dessous:
@VintfStability
interface IFoo {
....
}
@VintfStability
parcelable Data {
....
}
@VintfStability
enum Type {
....
}
Lorsqu'un type est annoté avec VintfStability
, tout autre type référencé dans le type doit également être annoté en tant que tel. Dans l'exemple suivant, Data
et IBar
doivent tous deux être annotés avec 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 {...}
En outre, les fichiers AIDL définissant des types annotés avec VintfStability
ne peuvent être compilés qu'à l'aide du type de module Soong aidl_interface
, avec la propriété stability
définie sur "vintf"
.
aidl_interface {
name: "my_interface",
srcs: [...],
stability: "vintf",
}
UnsupportedAppUsage
L'annotation UnsupportedAppUsage
indique que le type AIDL annoté fait partie de l'interface non SDK accessible aux anciennes applications.
Pour en savoir plus sur les API masquées, consultez la section Restrictions concernant les interfaces non SDK.
L'annotation UnsupportedAppUsage
n'a aucune incidence sur le comportement du code généré. L'annotation n'annote que la classe Java générée avec l'annotation Java du même nom.
// in AIDL
@UnsupportedAppUsage
interface IFoo {...}
// in Java
@android.compat.annotation.UnsupportedAppUsage
public interface IFoo {...}
Il s'agit d'une opération no-op pour les backends non Java.
Support
L'annotation Backing
spécifie le type de stockage d'un type d'énumération AIDL.
@Backing(type="int")
enum Color { RED, BLUE, }
Dans le backend CPP, cela émet une classe d'énumération C++ de type int32_t
.
enum class Color : int32_t {
RED = 0,
BLUE = 1,
}
Si l'annotation est omise, type
est supposé être byte
, qui se mappe sur int8_t
pour le backend CPP.
L'argument type
ne peut être défini que sur les types entiers suivants:
byte
(8 bits de large)int
(32 bits de large)long
(64 bits de large)
NdkOnlyStableParcelable (NdkOnlyStableParcelable)
NdkOnlyStableParcelable
marque une déclaration parcelable (et non une définition) comme stable afin qu'elle puisse être référencée à partir d'autres types AIDL stables. Cette méthode est semblable à JavaOnlyStableParcelable
, mais NdkOnlyStableParcelable
marque une déclaration parcelable comme stable pour le backend du NDK plutôt que pour Java.
Pour utiliser ce parcelable:
- Vous devez spécifier
ndk_header
. - Vous devez disposer d'une bibliothèque NDK spécifiant le parcelable et la bibliothèque doit être compilée dans la bibliothèque. Par exemple, dans le système de compilation principal d'un module
cc_*
, utilisezstatic_libs
oushared_libs
. Pouraidl_interface
, ajoutez la bibliothèque sousadditional_shared_libraries
dansAndroid.bp
.
JavaOnlyStableParcelable
JavaOnlyStableParcelable
marque une déclaration parcelable (et non une définition) comme stable afin qu'elle puisse être référencée à partir d'autres types AIDL stables.
L'AIDL stable exige que tous les types définis par l'utilisateur soient stables. Pour les parcelables, la stabilité nécessite que leurs champs soient explicitement décrits dans le fichier source 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
}
Si le parcelable était non structuré (ou simplement déclaré), il ne peut pas être référencé.
parcelable Data; // Data is NOT a structured parcelable
parcelable AnotherData {
Data d; // Error
}
JavaOnlyStableParcelable
vous permet de remplacer la vérification lorsque le parcelable que vous référencez est déjà disponible en toute sécurité dans le SDK Android.
@JavaOnlyStableParcelable
parcelable Data;
parcelable AnotherData {
Data d; // OK
}
JavaDerive
JavaDerive
génère automatiquement des méthodes pour les types parcelables dans le backend Java.
@JavaDerive(equals = true, toString = true)
parcelable Data {
int number;
String str;
}
L'annotation nécessite des paramètres supplémentaires pour contrôler les éléments à générer. Les paramètres acceptés sont les suivants:
equals=true
génère les méthodesequals
ethashCode
.toString=true
génère la méthodetoString
qui imprime le nom du type et des champs. Exemple :Data{number: 42, str: foo}
JavaDefault
JavaDefault
, ajouté dans Android 13, contrôle si la prise en charge de la gestion des versions par défaut de l'implémentation est générée (pour setDefaultImpl
). Cette prise en charge n'est plus générée par défaut afin d'économiser de l'espace.
JavaPassthrough
JavaPassthrough
permet d'annoter l'API Java générée avec une annotation Java arbitraire.
Les annotations suivantes dans AIDL
@JavaPassthrough(annotation="@android.annotation.Alice")
@JavaPassthrough(annotation="@com.android.Alice(arg=com.android.Alice.Value.A)")
devenir
@android.annotation.Alice
@com.android.Alice(arg=com.android.Alice.Value.A)
dans le code Java généré.
La valeur du paramètre annotation
est émise directement. Le compilateur AIDL n'examine pas la valeur du paramètre. En cas d'erreur de syntaxe au niveau Java, elle ne sera pas détectée par le compilateur AIDL, mais par le compilateur Java.
Cette annotation peut être associée à n'importe quelle entité AIDL. Cette annotation est une opération no-op pour les backends autres que Java.
FixedSize
FixedSize
marque un parcelable structuré comme de taille fixe. Une fois cette case cochée, aucun nouveau champ ne pourra être ajouté au segmentable. Tous les champs du parcelable doivent également être des types de taille fixe, y compris les types primitifs, les énumérations, les tableaux de taille fixe et les autres parcelables marqués avec FixedSize
.
Cela ne garantit rien pour les différentes largeurs de bits et ne doit pas être utilisé pour la communication à largeur de bits mixte.
Titre
Descriptor
spécifie de force le descripteur d'interface d'une interface.
package android.foo;
@Descriptor(value="android.bar.IWorld")
interface IHello {...}
Le descripteur de cette interface est android.bar.IWorld
. Si l'annotation Descriptor
est manquante, le descripteur est android.foo.IHello
.
Cette option est utile pour renommer une interface déjà publiée. Rendre le descripteur de l'interface renommée identique au descripteur de l'interface avant le changement de nom permet aux deux interfaces de communiquer entre elles.
@hide dans les commentaires
Le compilateur AIDL reconnaît @hide
dans les commentaires et le transmet à la sortie Java pour que Metalava le récupère. Ce commentaire permet au système de compilation Android de savoir que les API AIDL ne sont pas des API de SDK.
@obsolète dans les commentaires
Le compilateur AIDL reconnaît @deprecated
dans les commentaires comme une balise permettant d'identifier une entité AIDL qui ne doit plus être utilisée.
interface IFoo {
/** @deprecated use bar() instead */
void foo();
void bar();
}
Chaque backend marque les entités obsolètes avec une annotation ou un attribut spécifique au backend afin que le code client soit averti s'il fait référence aux entités obsolètes. Par exemple, l'annotation @Deprecated
et la balise @deprecated
sont associées au code Java généré.