Anotaciones en el AIDL

El AIDL admite anotaciones que le brindan información adicional al compilador AIDL. sobre el elemento anotado, lo que también afecta el código de stub 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 de AIDL, como interface Foo, void method() o int arg Los se adjunta a la entidad que le sigue.

Algunas anotaciones pueden tener argumentos dentro de los paréntesis, como se muestra más arriba. Las anotaciones que no tienen un argumento no necesitan el paréntesis. Por ejemplo:

@AnnotationName AidlEntity

Estas anotaciones no son iguales a las de Java anotaciones, aunque se ven muy similares. Los usuarios no pueden definir AIDL personalizado anotaciones; las anotaciones están predefinidas. Algunas anotaciones solo afectan en un backend determinado y no funcionan en otros. Tienen diferentes restricciones a las que pueden adjuntarse.

Esta es la lista de anotaciones de AIDL predefinidas:

Anotaciones Se agregó 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

nullable

nullable declara que no se puede proporcionar el valor de la entidad anotada.

Esta anotación solo se puede adjuntar a tipos de datos que se devuelven, parámetros de métodos, 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 los tipos primitivos. El siguiente es un error.

void method(in @nullable int a); // int is a primitive type

Esta anotación es no-op para el backend de Java. Esto se debe a que, en Java, los tipos no primitivos se pasan por referencia, que podría ser null.

En el backend de la CPP, @nullable T se asigna a std::unique_ptr<T> en Android 11 o versiones anteriores, y a std::optional<T> en Android 12 o una versión posterior.

En el backend del NDK, @nullable T siempre se asigna a std::optional<T>.

Para un tipo similar a una lista, L, 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 de CPP para Android 11 o versiones anteriores).

Hay una excepción a esta asignación. Cuando T es IBinder o una interfaz de AIDL, @nullable es no-op. En otras palabras, tanto @nullable IBinder y IBinder se asignan también a android::sp<IBinder>, que ya es anulable porque es un puntero sólido (el CPP lee aún aplicar la nulabilidad, pero el tipo sigue siendo android::sp<IBinder>).

A partir de Android 13, @nullable(heap=true) se puede usar para campos parcelables para modelar tipos recursivos. No se puede usar @nullable(heap=true) con parámetros de métodos o tipos de datos que se devuelven. Cuando se anota con él, el campo se Se asignó a una referencia std::unique_ptr<T> asignada por el montón en el CPP/NDK backends. @nullable(heap=true) es no-op en el backend de Java.

utf8InCpp

utf8InCpp declara que un String se representa en formato UTF8 para el CPP. backend. Como su nombre lo indica, la anotación es una no-op para otros backends. Específicamente, String siempre es UTF16 en el backend de Java y UTF8 en el NDK backend.

Esta anotación se puede adjuntar siempre que se pueda usar el tipo String. incluidos valores que se devuelven, parámetros, declaraciones de constantes y valores .

Para el backend de la CPP, @utf8InCpp String en el AIDL se asigna a std::string, mientras que String sin la anotación se asigna a android::String16, donde se usa UTF16.

Ten en cuenta que la existencia de la anotación utf8InCpp no cambia la forma en que las cadenas se transmiten por cable. Las cadenas siempre se transmiten como UTF16. por el cable. Una cadena con anotaciones utf8InCpp se convierte a UTF16 antes de transmitirse. Cuando se recibe una cadena, se convierte de UTF16 a UTF8 si se anotó como utf8InCpp.

VintfStability

VintfStability declara que un tipo definido por el usuario (interfaz, parcelable, y enum) se pueden usar en los dominios del sistema y del proveedor. Consulta AIDL para HALs para obtener más información sobre interoperabilidad entre sistemas y proveedores.

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 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 aquí:

@VintfStability
interface IFoo {
    ....
}

@VintfStability
parcelable Data {
    ....
}

@VintfStability
enum Type {
    ....
}

Cuando un tipo se anota con VintfStability, cualquier otro tipo que se a las que se hace referencia en el tipo también deberían anotarse como tales. En la siguiente Por ejemplo, Data y IBar deberían tener anotaciones 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 con anotaciones VintfStability solo se pueden compilar con el tipo de módulo aidl_interface de Soong, con el La propiedad stability se estableció en "vintf".

aidl_interface {
    name: "my_interface",
    srcs: [...],
    stability: "vintf",
}

Uso de la aplicación no admitido

La anotación UnsupportedAppUsage indica que el tipo de AIDL anotado es parte de la interfaz que no pertenece al SDK y a la que pueden acceder las apps heredadas. Consulta Restricciones en el SDK que no pertenece al SDK. interfaces para obtener más información sobre las APIs ocultas.

La anotación UnsupportedAppUsage no afecta el comportamiento de la código generado. La anotación solo anota la clase Java generada con el Anotación Java del mismo nombre.

// in AIDL
@UnsupportedAppUsage
interface IFoo {...}

// in Java
@android.compat.annotation.UnsupportedAppUsage
public interface IFoo {...}

Esta es una no-op para backends que no son de Java.

Copia de seguridad

La anotación Backing especifica el tipo de almacenamiento de un tipo de enumeración del AIDL.

@Backing(type="int")
enum Color { RED, BLUE, }

En el backend de la CPP, se emite una clase enum C++ de tipo int32_t.

enum class Color : int32_t {
    RED = 0,
    BLUE = 1,
}

Si se omite la anotación, se supone que type es byte, lo cual en int8_t para el backend de CPP.

El argumento type solo se puede establecer en los siguientes tipos de integrales:

  • byte (ancho de 8 bits)
  • int (ancho de 32 bits)
  • long (ancho de 64 bits)

NdkOnlyStableParcelable

NdkOnlyStableParcelable marca una declaración parcelable (sin definición). como estable para que se pueda hacer referencia desde otros tipos de AIDL estables. Esta es como JavaOnlyStableParcelable, pero NdkOnlyStableParcelable marca una declaración parcelable como estable para el NDK. backend en lugar de para Java.

Para usar este objeto parcelable:

  • Debes especificar ndk_header.
  • Debes tener una biblioteca de NDK que especifique el elemento parcelable, y la biblioteca compilarse en la biblioteca. Por ejemplo, en el sistema de compilación central en un cc_*, usa static_libs o shared_libs. Para aidl_interface, agrega la biblioteca de additional_shared_libraries en Android.bp.

JavaOnlyStableParcelable

JavaOnlyStableParcelable marca una declaración parcelable (sin definición). como estable para que se pueda hacer referencia desde otros tipos de AIDL estables.

El AIDL estable requiere que todos los tipos definidos por el usuario sean estables. Para parcelables, ser estable requiere que sus campos se describan explícitamente en en el archivo fuente de 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 objeto parcelable no era estructurado (o se declaró recientemente), no se puede a los que se hace referencia.

parcelable Data; // Data is NOT a structured parcelable

parcelable AnotherData {
    Data d; // Error
}

JavaOnlyStableParcelable te permite anular la comprobación cuando el elemento a los que haces referencia ya está disponible de forma segura como parte del SDK de Android.

@JavaOnlyStableParcelable
parcelable Data;

parcelable AnotherData {
    Data d; // OK
}

JavaDerive

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 los siguientes:

  • equals=true genera los métodos equals y hashCode.
  • toString=true genera el método toString que imprime el nombre del tipo. y campos específicos. Por ejemplo: Data{number: 42, str: foo}

JavaDefault

JavaDefault, que se agregó en Android 13, controla si se genera la compatibilidad predeterminada con el control de versiones para la implementación (para setDefaultImpl). Esta compatibilidad ya no se genera de forma predeterminada para y ahorrar espacio.

JavaPassthrough

JavaPassthrough permite que la API de Java generada se anote con una anotación anotación de Java.

Las siguientes anotaciones en el AIDL

@JavaPassthrough(annotation="@android.annotation.Alice")
@JavaPassthrough(annotation="@com.android.Alice(arg=com.android.Alice.Value.A)")

convertirse en

@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 AIDL el compilador no analiza el valor del parámetro. Si hay alguna Error de sintaxis a nivel de Java, no será detectado por el compilador del AIDL, sino por el Compilador de Java.

Esta anotación se puede adjuntar a cualquier entidad de AIDL. Esta anotación es no-op para backends que no son de Java.

Tamaño fijo

FixedSize marca un objeto parcelable estructurado como tamaño fijo. Una vez que las marcas, parcelable no tendrá permisos que se le agreguen campos nuevos. Todos los campos de el parcelable también deben ser de tipo fijo, incluidos los tipos primitivos, enumeraciones, arrays de tamaño fijo y otros objetos parcelables marcados con FixedSize.

Esto no proporciona ninguna garantía en diferentes bits de datos y no debería de las que dependía para una comunicación mixta.

Descriptor

Descriptor especifica de manera forzosa el descriptor de interfaz de una interfaz.

package android.foo;

@Descriptor(value="android.bar.IWorld")
interface IHello {...}

El descriptor de esta interfaz es android.bar.IWorld. Si el botón 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 a la que le cambiaste el nombre de la misma manera que el descriptor de la interfaz antes del cambio de nombre permite que las dos interfaces se comuniquen entre sí.

@ocultar en los comentarios

El compilador de AIDL reconoce @hide en los comentarios y lo pasa por a la salida de Java para que metalava recoja. Este comentario garantiza que el código de compilación reconoce que las APIs de AIDL no son APIs del SDK.

@obsoleto en los comentarios

El compilador de AIDL reconoce @deprecated en los comentarios como una etiqueta para identificar un Es la entidad de AIDL que ya no se debe usar.

interface IFoo {
  /** @deprecated use bar() instead */
  void foo();
  void bar();
}

Cada backend marca las entidades obsoletas con una anotación específica de backend o para que el código del cliente reciba una advertencia si hace referencia al atributo obsoleto entidades. Por ejemplo, la anotación @Deprecated y @deprecated etiqueta de estado se adjuntan al código Java generado.