Annotazioni in AIDL

AIDL supporta annotazioni che forniscono al compilatore AIDL informazioni aggiuntive sull'elemento annotato, che influisce anche sul codice stub generato.

La sintassi è simile a quella di Java:

@AnnotationName(argument1=value, argument2=value) AidlEntity

In questo caso, AnnotationName è il nome dell'annotazione, mentre AidlEntity è un'entità AIDL come interface Foo, void method() o int arg. Un all'entità che la segue.

Alcune annotazioni possono avere argomenti impostati tra parentesi, come mostrato sopra. Le annotazioni che non hanno un argomento non hanno bisogno delle parentesi. Ad esempio:

@AnnotationName AidlEntity

Queste annotazioni non sono le stesse delle annotazioni Java anche se molto simili. Gli utenti non possono definire l'AIDL personalizzato annotazioni; tutte le annotazioni sono predefinite. Alcune annotazioni interessano solo un determinato backend e non sono operativi in altri backend. Hanno diversi tipi di restrizioni a cui possono essere associati.

Ecco l'elenco delle annotazioni AIDL predefinite:

Annotazioni Aggiunto 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

annullabile

nullable dichiara che il valore dell'entità annotata potrebbe non essere fornito.

Questa annotazione può essere collegata solo ai tipi restituiti dal metodo, ai parametri del metodo e campi assegnabili.

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 ai tipi primitivi. Quello che segue è un errore.

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

Questa annotazione è autonoma per il backend Java. Questo perché, in Java, tutti i tipi non primitivi vengono passati per riferimento, che può essere null.

Nel backend CPP, @nullable T viene mappato a std::unique_ptr<T> in Android 11 o versioni precedenti e a std::optional<T> in Android 12 o successiva.

Nel backend NDK, @nullable T viene sempre mappato a std::optional<T>.

Per un tipo di tipo 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 non è operativo. In altre parole, sia @nullable IBinder e IBinder vengono mappati equamente a android::sp<IBinder>, che è già nullo perché è un pointer efficace (CPP legge ancora forzare l'uso dei valori null, ma il tipo è ancora android::sp<IBinder>).

A partire da Android 13, è possibile utilizzare @nullable(heap=true) per campi assegnabili per creare modelli di tipi ricorsivi. Impossibile utilizzare @nullable(heap=true) con parametri di metodo o tipi restituiti. Quando è annotato, il campo mappato a un riferimento allocato dall'heap std::unique_ptr<T> nel CPP/NDK di backend. @nullable(heap=true) è autonomo nel backend Java.

Utf8InCpp

utf8InCpp dichiara che un String è rappresentato in formato UTF8 per il CPP di un backend cloud. Come indica il suo nome, l'annotazione è autonoma per altri backend. Nello specifico, String è sempre UTF16 nel backend Java e UTF8 nel backend NDK di un backend cloud.

Questa annotazione può essere allegata ovunque sia possibile usare il tipo String, inclusi valori restituiti, parametri, dichiarazioni costanti e campi.

Per il backend CPP, @utf8InCpp String in AIDL viene mappato a std::string, mentre String senza l'annotazione corrisponde a android::String16, dove viene utilizzato UTF16.

Tieni presente che l'esistenza dell'annotazione utf8InCpp non cambia il modo stringhe vengono trasmesse attraverso il cavo. Le stringhe vengono sempre trasmesse come UTF16 in cavo. Una stringa annotata utf8InCpp viene convertita in UTF16 prima vengono trasmessi. Quando una stringa viene ricevuta, viene convertita da UTF16 a UTF8 se è stato annotato come utf8InCpp.

VintfStability

VintfStability dichiara che un tipo definito dall'utente (interfaccia, parcelable, ed enum) possono essere utilizzati nei domini del sistema e dei fornitori. Consulta AIDL per gli HAL per saperne di più su e l'interoperabilità tra fornitori di sistema e fornitore di servizi.

L'annotazione non modifica la firma del tipo, ma quando viene impostata, l'istanza del tipo è contrassegnata come stabile in modo che possa spostarsi i processi del fornitore e del sistema.

L'annotazione può essere collegata solo alle dichiarazioni dei tipi definite dall'utente, come mostrato qui:

@VintfStability
interface IFoo {
    ....
}

@VintfStability
parcelable Data {
    ....
}

@VintfStability
enum Type {
    ....
}

Quando un tipo è annotato con VintfStability, qualsiasi altro tipo sia a cui si fa riferimento nel tipo deve anche essere annotato come tale. Nel seguente ad 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 indicati con VintfStability può essere creato solo utilizzando il tipo di modulo Presto aidl_interface, con Proprietà stability impostata su "vintf".

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

Utilizzo di app non supportato

L'annotazione UnsupportedAppUsage indica che il tipo AIDL annotato è facenti parte dell'interfaccia non SDK accessibile alle app precedenti. Consulta le restrizioni relative alle app non SDK interfacce per ulteriori informazioni sulle API nascoste.

L'annotazione UnsupportedAppUsage non influisce sul comportamento del componente generato il codice. L'annotazione annota solo la classe Java generata con il Annotazione Java con lo stesso nome.

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

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

Questa è un'operazione autonoma per i backend non Java.

Supporto

L'annotazione Backing specifica il tipo di archiviazione di un tipo enum AIDL.

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

Nel backend CPP, emette una classe enum C++ di tipo int32_t.

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

Se l'annotazione viene omessa, si presume che type sia byte, che viene mappata a int8_t per il backend CPP.

L'argomento type può essere impostato solo sui seguenti tipi integrali:

  • byte (larghezza di 8 bit)
  • int (larghezza a 32 bit)
  • long (larghezza a 64 bit)

NdkOnlyStableParcelable

NdkOnlyStableParcelable contrassegna una dichiarazione "parcelable" (non cumulabile) stabile, in modo da potervi fare riferimento da altri tipi di AIDL stabili. Questo è simile a JavaOnlyStableParcelable, ma NdkOnlyStableParcelable contrassegna una dichiarazione "parcelable" come stabile per l'NDK per Java.

Per utilizzare questa particella:

  • Devi specificare ndk_header.
  • Devi avere una libreria NDK che specifichi il valore "parcelable" e la libreria deve essere compilati nella libreria. Ad esempio, nel sistema di compilazione principale su Modulo cc_*, usa static_libs o shared_libs. Per aidl_interface, aggiungi la raccolta in additional_shared_libraries in Android.bp.

Pacchetti disponibili solo Java

JavaOnlyStableParcelable contrassegna una dichiarazione "parcelable" (non cumulabile) stabile, in modo da potervi fare riferimento da altri tipi di AIDL stabili.

Il modello AIDL stabile richiede che tutti i tipi definiti dall'utente siano stabili. Per particellari, essere stabili richiede che i suoi campi siano descritti esplicitamente in il 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 era non strutturato (o appena dichiarato), non può a cui viene fatto riferimento.

parcelable Data; // Data is NOT a structured parcelable

parcelable AnotherData {
    Data d; // Error
}

JavaOnlyStableParcelable consente di ignorare il controllo quando il valore "parcelable" a cui fai riferimento è già disponibile in sicurezza come parte dell'SDK Android.

@JavaOnlyStableParcelable
parcelable Data;

parcelable AnotherData {
    Data d; // OK
}

Estrazione Java

JavaDerive genera automaticamente metodi per i tipi "parcelable" in il backend Java.

@JavaDerive(equals = true, toString = true)
parcelable Data {
  int number;
  String str;
}

L'annotazione richiede parametri aggiuntivi per controllare cosa generati. I parametri supportati sono:

  • equals=true genera i metodi equals e hashCode.
  • toString=true genera il metodo toString che stampa il nome del tipo e campi. Ad esempio: Data{number: 42, str: foo}

Predefinito di Java

JavaDefault, aggiunta ad Android 13, stabilisce se viene generato il supporto del controllo delle versioni dell'implementazione predefinita (ad setDefaultImpl). Questo supporto non viene più generato per impostazione predefinita al fine di: per risparmiare spazio.

JavaPassthrough

JavaPassthrough consente all'API Java generata di essere annotata con un Annotazione Java.

Le seguenti annotazioni in AIDL

@JavaPassthrough(annotation="@android.annotation.Alice")
@JavaPassthrough(annotation="@com.android.Alice(arg=com.android.Alice.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. AIDL il compilatore non esamina il valore del parametro. Se sono presenti Errore di sintassi a livello Java, non viene rilevato dal compilatore AIDL, ma dal compilatore Java.

Questa annotazione può essere collegata a qualsiasi entità AIDL. Questa annotazione è autonoma per i backend non Java.

Dimensioni fisse

FixedSize contrassegna un elemento "parcelable" strutturato come dimensione fissa. Una volta contrassegnata, non potranno essere aggiunti nuovi campi. Tutti i campi di il parcelable deve essere anche di tipo con dimensioni fisse, inclusi i tipi primitivi, enum, array a dimensione fissa e altri elementi particellari contrassegnati con FixedSize.

Ciò non fornisce alcuna garanzia per le diverse durate e non dovrebbe essere si è fatto affidamento per le comunicazioni con bitness mista.

Descrittore

Descriptor specifica in modo forzato il descrittore di un'interfaccia.

package android.foo;

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

Il descrittore di questa interfaccia è android.bar.IWorld. Se Annotazione Descriptor mancante, il descrittore sarebbe android.foo.IHello.

Ciò è utile per rinominare un'interfaccia già pubblicata. Rendendo descrittore dell'interfaccia rinominata uguale a quello dell'interfaccia consente alle due interfacce di comunicare tra loro.

@nascondi nei commenti

Il compilatore AIDL riconosce @hide nei commenti e lo passa in Java per il metalava al pickup. Questo commento garantisce che Android sa 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 dovrebbe più essere utilizzata.

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

Ogni backend contrassegna entità deprecate con un'annotazione specifica in modo che il codice client venga avvisato se fa riferimento all'attributo deprecato le entità. Ad esempio, l'annotazione @Deprecated e @deprecated sono associati al codice generato da Java.