AIDL admite anotaciones que brindan al compilador AIDL información adicional sobre el elemento anotado, lo que también afecta el código auxiliar generado.
La sintaxis es similar a la de Java:
@AnnotationName(argument1=value, argument2=value) AidlEntity
Aquí, AnnotationName
es el nombre de la anotación y AidlEntity
es una entidad AIDL como interface Foo
, void method()
o int arg
. Se adjunta una anotación a la entidad que le sigue.
Algunas anotaciones pueden tener argumentos entre paréntesis, como se muestra arriba. Las anotaciones que no tienen argumento no necesitan paréntesis. Por ejemplo:
@AnnotationName AidlEntity
Estas anotaciones no son las mismas que las de Java, aunque parecen muy similares. Los usuarios no pueden definir anotaciones AIDL personalizadas; todas las anotaciones están predefinidas. Algunas anotaciones afectan solo a un determinado backend y no son operativas en otros backends. Tienen diferentes restricciones a las que se pueden adjuntar.
A continuación se muestra la lista de anotaciones AIDL predefinidas:
Anotaciones | Agregado en la versión de 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 |
anulable
nullable
declara que no se puede proporcionar el valor de la entidad anotada.
Esta anotación solo se puede adjuntar a tipos de devolución de métodos, parámetros de métodos y campos parcelables.
interface IFoo {
// method return types
@nullable Data method();
// method parameters
void method2(in @nullable Data d);
}
parcelable Data {
// parcelable fields
@nullable Data d;
}
No se pueden adjuntar anotaciones a tipos primitivos. Lo siguiente es un error.
void method(in @nullable int a); // int is a primitive type
Esta anotación no es operativa para el backend de Java. Esto se debe a que, en Java, todos los tipos no primitivos se pasan por referencia, que podría ser null
.
En el backend de CPP, @nullable T
se asigna a std::unique_ptr<T>
en Android 11 o inferior, y a std::optional<T>
en Android 12 o superior.
En el backend del NDK, @nullable T
siempre se asigna a std::optional<T>
.
Para un tipo L
similar a una lista como T[]
o List<T>
, @nullable L
se asigna a std::optional<std::vector<std::optional<T>>>
(o std::unique_ptr<std::vector<std::unique_ptr<T>>>
en el caso del backend CPP para Android 11 o inferior).
Hay una excepción a este mapeo. Cuando T
es IBinder
o una interfaz AIDL, @nullable
no funciona. En otras palabras, tanto @nullable IBinder
como IBinder
se asignan igualmente a android::sp<IBinder>
, que ya es anulable porque es un puntero fuerte (las lecturas de CPP aún imponen la nulidad, pero el tipo sigue siendo android::sp<IBinder>
).
A partir de Android 13, @nullable(heap=true)
se puede utilizar para campos parcelables para modelar tipos recursivos. @nullable(heap=true)
no se puede utilizar con parámetros de método o tipos de retorno. Cuando se anota con él, el campo se asigna a una referencia asignada al montón std::unique_ptr<T>
en los backends de CPP/NDK. @nullable(heap=true)
no es operativo en el backend de Java.
utf8InCpp
utf8InCpp
declara que una String
se representa en formato UTF8 para el backend de CPP. Como su nombre lo indica, la anotación no es operativa para otros backends. Específicamente, String
siempre es UTF16 en el backend de Java y UTF8 en el backend de NDK.
Esta anotación se puede adjuntar en cualquier lugar donde se pueda usar el tipo String
, incluidos valores de retorno, parámetros, declaraciones constantes y campos parcelables.
Para el backend de CPP, @utf8InCpp String
en AIDL se asigna a std::string
, mientras que String
sin la anotación se asigna a android::String16
donde se usa UTF16.
Tenga en cuenta que la existencia de la anotación utf8InCpp
no cambia la forma en que se transmiten las cadenas por cable. Las cadenas siempre se transmiten como UTF16 a través del cable. Una cadena anotada utf8InCpp
se convierte a UTF16 antes de transmitirse. Cuando se recibe una cadena, se convierte de UTF16 a UTF8 si se anotó como utf8InCpp
.
VintfEstabilidad
VintfStability
declara que se puede utilizar un tipo definido por el usuario (interfaz, parcelable y enumeración) en todo el sistema y los dominios del proveedor. Consulte AIDL para HAL para obtener más información sobre la interoperabilidad del sistema y el proveedor.
La anotación no cambia la firma del tipo, pero cuando se establece, la instancia del tipo se marca como estable para que pueda viajar a través de los procesos del proveedor y del sistema.
La anotación solo se puede adjuntar a declaraciones de tipo definidas por el usuario como se muestra a continuación:
@VintfStability
interface IFoo {
....
}
@VintfStability
parcelable Data {
....
}
@VintfStability
enum Type {
....
}
Cuando un tipo se anota con VintfStability
, cualquier otro tipo al que se haga referencia en el tipo también debe anotarse como tal. En el siguiente ejemplo, tanto Data
como IBar
deben anotarse 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 {...}
Además, los archivos AIDL que definen tipos anotados con VintfStability
solo se pueden crear utilizando el tipo de módulo aidl_interface
Soong, con la propiedad stability
establecida en "vintf"
.
aidl_interface {
name: "my_interface",
srcs: [...],
stability: "vintf",
}
Uso de aplicaciones no admitidas
La anotación UnsupportedAppUsage
indica que el tipo AIDL anotado es parte de la interfaz que no es SDK a la que han podido acceder las aplicaciones heredadas. Consulte Restricciones en interfaces que no son SDK para obtener más información sobre las API ocultas.
La anotación UnsupportedAppUsage
no afecta el comportamiento del código generado. La anotación solo anota la clase Java generada con la anotación Java del mismo nombre.
// in AIDL
@UnsupportedAppUsage
interface IFoo {...}
// in Java
@android.compat.annotation.UnsupportedAppUsage
public interface IFoo {...}
Esta es una operación no operativa para backends que no son Java.
Apoyo
La anotación Backing
especifica el tipo de almacenamiento de un tipo de enumeración AIDL.
@Backing(type="int")
enum Color { RED, BLUE, }
En el backend de CPP, lo anterior emite una clase de enumeración C++ de tipo int32_t
.
enum class Color : int32_t {
RED = 0,
BLUE = 1,
}
Si se omite la anotación, se supone que el type
es byte
, que se asigna a int8_t
para el backend de CPP.
El argumento type
solo se puede establecer en los siguientes tipos integrales:
-
byte
(8 bits de ancho) -
int
(32 bits de ancho) -
long
(ancho de 64 bits)
NdkSoloEstableParcelable
NdkOnlyStableParcelable
marca una declaración parcelable (no una definición) como estable para que se pueda hacer referencia a ella desde otros tipos AIDL estables. Esto es como JavaOnlyStableParcelable
, pero NdkOnlyStableParcelable
marca una declaración parcelable como estable para el backend de NDK en lugar de para Java.
Para utilizar este paquete: * Debes especificar ndk_header
. * Debe tener una biblioteca NDK que especifique el paquete y la biblioteca debe estar compilada en la biblioteca. Por ejemplo, en el sistema de compilación principal en un módulo cc_*
, use static_libs
o shared_libs
. Para aidl_interface
, agregue la biblioteca en additional_shared_libraries
en Android.bp
.
JavaOnlyStableParcelable
JavaOnlyStableParcelable
marca una declaración parcelable (no una definición) como estable para que se pueda hacer referencia a ella desde otros tipos AIDL estables.
AIDL estable requiere que todos los tipos definidos por el usuario sean estables. Para los partículables, ser estable requiere que sus campos se describan explícitamente en el archivo fuente 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 el paquete no estaba estructurado (o simplemente estaba declarado), entonces no se puede hacer referencia a él.
parcelable Data; // Data is NOT a structured parcelable
parcelable AnotherData {
Data d; // Error
}
JavaOnlyStableParcelable
le permite anular la verificación cuando el paquete al que hace referencia ya está disponible de forma segura como parte del SDK de Android.
@JavaOnlyStableParcelable
parcelable Data;
parcelable AnotherData {
Data d; // OK
}
JavaDerivar
JavaDerive
genera automáticamente métodos para tipos parcelables en el backend de Java.
@JavaDerive(equals = true, toString = true)
parcelable Data {
int number;
String str;
}
La anotación requiere parámetros adicionales para controlar qué generar. Los parámetros admitidos son:
-
equals=true
genera métodosequals
yhashCode
. -
toString=true
genera el métodotoString
que imprime el nombre del tipo y los campos. Por ejemplo:Data{number: 42, str: foo}
JavaPor defecto
JavaDefault
, agregado en Android 13, controla si se genera el soporte de versiones de implementación predeterminado (para setDefaultImpl
). Este soporte ya no se genera por defecto para ahorrar espacio.
JavaPassthrough
JavaPassthrough
permite anotar la API de Java generada con una anotación Java arbitraria.
Las siguientes anotaciones en AIDL
@JavaPassthrough(annotation="@android.annotation.Alice")
@JavaPassthrough(annotation="@com.android.Alice(arg=com.android.Alice.Value.A)")
convertirse
@android.annotation.Alice
@com.android.Alice(arg=com.android.Alice.Value.A)
en el código Java generado.
El valor del parámetro annotation
se emite directamente. El compilador AIDL no analiza el valor del parámetro. Si hay algún error de sintaxis a nivel de Java, no será detectado por el compilador AIDL sino por el compilador de Java.
Esta anotación se puede adjuntar a cualquier entidad AIDL. Esta anotación no es operativa para backends que no sean Java.
Tamaño fijo
FixedSize
marca un paquete estructurado como de tamaño fijo. Una vez marcado, no se permitirá que se le agreguen nuevos campos al paquete parcelable. Todos los campos del paquete también deben ser tipos de tamaño fijo, incluidos tipos primitivos, enumeraciones, matrices de tamaño fijo y otros paquetes marcados con FixedSize
.
Esto no ofrece ninguna garantía entre diferentes bits y no se debe confiar en él para la comunicación de bits mixtos.
Descriptor
Descriptor
especifica a la fuerza el descriptor de interfaz de una interfaz.
package android.foo;
@Descriptor(value="android.bar.IWorld")
interface IHello {...}
El descriptor de la interfaz anterior es android.bar.IWorld
. Si falta la anotación Descriptor
, el descriptor sería android.foo.IHello
.
Esto es útil para cambiar el nombre de una interfaz ya publicada. Hacer que el descriptor de la interfaz renombrada sea el mismo que el descriptor de la interfaz antes del cambio de nombre permite que las dos interfaces se comuniquen entre sí.
@ocultar en comentarios
El compilador AIDL reconoce @hide
en los comentarios y lo pasa a la salida de Java para que metalava lo recoja. Este comentario garantiza que el sistema de compilación de Android sepa que las API de AIDL no son API de SDK.
@deprecated en comentarios
El compilador AIDL reconoce @deprecated
en los comentarios como una etiqueta para identificar una entidad AIDL que ya no debe usarse.
interface IFoo {
/** @deprecated use bar() instead */
void foo();
void bar();
}
Cada backend marca entidades obsoletas con una anotación/atributo específico del backend para que se advierta al código del cliente si hace referencia a entidades obsoletas. Por ejemplo, la anotación @Deprecated
y la etiqueta @deprecated
se adjuntan al código generado por Java.