Anotasi di AIDL

AIDL mendukung anotasi yang memberikan info tambahan kepada compiler AIDL tentang elemen yang diberi anotasi, yang juga memengaruhi kode stub yang dihasilkan.

Sintaksisnya mirip dengan Java:

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

Di sini, AnnotationName adalah nama anotasi, dan AidlEntity adalah entitas AIDL seperti interface Foo, void method(), atau int arg. Anotasi dilampirkan ke entitas yang mengikutinya.

Beberapa anotasi dapat memiliki argumen yang ditetapkan di dalam tanda kurung, seperti yang ditunjukkan pada contoh sebelumnya. Anotasi yang tidak memiliki argumen tidak memerlukan tanda kurung. Contoh:

@AnnotationName AidlEntity

Anotasi ini tidak sama dengan anotasi Java, meskipun terlihat serupa. Semua anotasi telah ditentukan sebelumnya, dan memiliki batasan tempat Anda dapat melampirkannya. Beberapa anotasi hanya memengaruhi backend tertentu dan tidak beroperasi di backend lainnya.

Berikut adalah daftar anotasi AIDL yang telah ditentukan sebelumnya:

AnotasiDitambahkan di versi Android
nullable7
utf8InCpp7
VintfStability11
UnsupportedAppUsage10
Hide11
Backing11
NdkOnlyStableParcelable14
JavaOnlyStableParcelable11
JavaDerive12
JavaPassthrough12
FixedSize12
Descriptor12

nullable

nullable menyatakan bahwa nilai entitas yang diberi anotasi dapat berupa null.

Anda hanya dapat melampirkan anotasi ini ke jenis nilai yang ditampilkan metode, parameter metode, dan kolom yang dapat di-parcel:

interface IFoo {
    // method return types
    @nullable Data method();

    // method parameters
    void method2(in @nullable Data d);
}

parcelable Data {
    // parcelable fields
    @nullable Data d;
}

Anotasi tidak dapat dilampirkan ke jenis primitif. Berikut adalah error:

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

Anotasi ini tidak beroperasi untuk backend Java. Di Java, semua jenis non-primitif diteruskan berdasarkan referensi, yang bisa berupa null.

Di backend CPP, @nullable T dipetakan ke std::unique_ptr<T> di Android 11 atau yang lebih rendah, dan ke std::optional<T> di Android 12 atau yang lebih tinggi.

Di backend NDK, @nullable T dipetakan ke std::optional<T>.

Di backend Rust, @nullable T dipetakan ke Option<T>.

Untuk jenis seperti daftar L seperti T[] atau List<T>, @nullable L dipetakan ke std::optional<std::vector<std::optional<T>>> (atau std::unique_ptr<std::vector<std::unique_ptr<T>>> jika menggunakan backend CPP untuk Android 11 atau yang lebih rendah).

Ada pengecualian untuk pemetaan ini. Jika T adalah IBinder atau antarmuka AIDL, @nullable adalah no-op untuk semua backend kecuali untuk Rust. Dengan kata lain, @nullable IBinder dan IBinder sama-sama dipetakan ke android::sp<IBinder>, yang sudah dapat bernilai null karena merupakan pointer yang kuat (pembacaan CPP tetap menerapkan nullability, tetapi jenisnya tetap android::sp<IBinder>). Di Rust, jenis ini adalah nullable hanya jika dianotasi dengan @nullable. Mereka dipetakan ke Option<T> jika diberi anotasi.

Mulai Android 13, @nullable(heap=true) dapat digunakan untuk kolom parcelable guna memodelkan jenis rekursif. @nullable(heap=true) tidak dapat digunakan dengan parameter metode atau jenis nilai yang ditampilkan. Jika diberi anotasi, kolom akan dipetakan ke referensi std::unique_ptr<T> yang dialokasikan heap di backend CPP dan NDK. @nullable(heap=true) adalah no-op di backend Java.

utf8InCpp

utf8InCpp menyatakan bahwa String ditampilkan dalam format UTF8 untuk backend CPP. Seperti namanya, anotasi ini tidak beroperasi untuk backend lain. Secara khusus, String selalu UTF16 di backend Java dan UTF8 di backend NDK.

Anotasi ini dapat dilampirkan di mana pun jenis String dapat digunakan, termasuk nilai yang ditampilkan, parameter, deklarasi konstanta, dan kolom dapat di-parcel.

Untuk backend CPP, @utf8InCpp String di AIDL dipetakan ke std::string, dengan String tanpa anotasi dipetakan ke android::String16 tempat UTF16 digunakan.

VintfStability

VintfStability menyatakan bahwa jenis yang ditentukan pengguna (antarmuka, parcelable, dan enum) dapat digunakan di seluruh domain sistem dan vendor. Lihat AIDL untuk HAL untuk mengetahui informasi selengkapnya tentang interoperabilitas sistem-vendor.

Anotasi tidak mengubah tanda tangan jenis, tetapi saat disetel, instance jenis ditandai sebagai stabil sehingga dapat berpindah di seluruh proses vendor dan sistem.

Anotasi hanya dapat dilampirkan ke deklarasi jenis yang ditentukan pengguna seperti yang ditunjukkan di sini:

@VintfStability
interface IFoo {
    ....
}

@VintfStability
parcelable Data {
    ....
}

@VintfStability
enum Type {
    ....
}

Jika suatu jenis dianotasi dengan VintfStability, jenis lain yang direferensikan dalam jenis tersebut juga harus dianotasi seperti itu. Pada contoh berikut, Data dan IBar harus diberi anotasi dengan 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 {...}

Selain itu, file AIDL yang menentukan jenis yang diberi anotasi dengan VintfStability hanya dapat dibangun menggunakan jenis modul Soong aidl_interface, dengan properti stability disetel ke vintf:

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

UnsupportedAppUsage

Anotasi UnsupportedAppUsage menunjukkan bahwa jenis AIDL yang diberi anotasi adalah bagian dari antarmuka non-SDK yang telah dapat diakses oleh aplikasi lama. Lihat Pembatasan pada antarmuka non-SDK untuk mengetahui informasi selengkapnya tentang API tersembunyi.

Anotasi UnsupportedAppUsage tidak memengaruhi perilaku kode yang dihasilkan. Anotasi hanya menganotasi class Java yang dihasilkan dengan anotasi Java dengan nama yang sama:

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

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

Ini adalah no-op untuk backend non-Java.

Anotasi latar belakang

Anotasi Backing menentukan jenis penyimpanan jenis enum AIDL:

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

Di backend CPP, ini memancarkan class enum C++ dari jenis int32_t:

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

Jika anotasi tidak disertakan, type diasumsikan sebagai byte, yang dipetakan ke int8_t untuk backend CPP.

Argumen type hanya dapat ditetapkan ke jenis integral berikut:

  • byte (lebar 8-bit)
  • int (lebar 32-bit)
  • long (lebar 64 bit)

NdkOnlyStableParcelable

NdkOnlyStableParcelable menandai deklarasi (bukan definisi) parcelable sebagai stabil sehingga dapat dirujuk dari jenis AIDL stabil lainnya. Ini seperti JavaOnlyStableParcelable, tetapi NdkOnlyStableParcelable menandai deklarasi parcelable sebagai stabil untuk backend NDK, bukan untuk Java.

Untuk menggunakan parcelable ini:

  • Anda harus menentukan ndk_header.
  • Anda harus memiliki library NDK yang menentukan parcelable dan library harus dikompilasi ke dalam library. Misalnya, di sistem build inti pada modul cc_*, gunakan static_libs atau shared_libs. Untuk aidl_interface, tambahkan library di bagian additional_shared_libraries dalam Android.bp.

JavaOnlyStableParcelable

JavaOnlyStableParcelable menandai deklarasi (bukan definisi) parcelable sebagai stabil sehingga dapat dirujuk dari jenis AIDL stabil lainnya.

AIDL Stabil mengharuskan semua jenis yang ditentukan pengguna bersifat stabil. Untuk parcelable, agar stabil, kolomnya harus dijelaskan secara eksplisit dalam file sumber 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
}

Jika parcelable tidak terstruktur (atau hanya dideklarasikan), maka parcelable tidak dapat dirujuk:

parcelable Data; // Data is NOT a structured parcelable

parcelable AnotherData {
    Data d; // Error
}

JavaOnlyStableParcelable memungkinkan Anda mengganti pemeriksaan saat parcelable yang Anda referensikan tersedia dengan aman sebagai bagian dari Android SDK:

@JavaOnlyStableParcelable
parcelable Data;

parcelable AnotherData {
    Data d; // OK
}

JavaDerive

JavaDerive secara otomatis membuat metode untuk jenis parcelable di backend Java:

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

Anotasi memerlukan parameter tambahan untuk mengontrol apa yang akan dihasilkan. Parameter yang didukung adalah:

  • equals=true menghasilkan metode equals dan hashCode.
  • toString=true menghasilkan metode toString yang mencetak nama jenis dan kolom, misalnya, Data{number: 42, str: foo}.

JavaDefault (tidak digunakan lagi)

JavaDefault, yang ditambahkan di Android 13, mengontrol apakah dukungan pembuatan versi implementasi default dibuat (untuk setDefaultImpl). Dukungan ini tidak lagi dibuat secara default untuk menghemat ruang.

JavaPassthrough

JavaPassthrough memungkinkan Java API yang dihasilkan diberi anotasi dengan anotasi Java arbitrer.

Anotasi ini dalam AIDL:

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

menjadi berikut dalam kode Java yang dihasilkan:

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

Nilai parameter annotation dipancarkan secara langsung. Compiler AIDL tidak memeriksa nilai parameter. Jika ada error sintaksis tingkat Java, error tersebut tidak akan terdeteksi oleh compiler AIDL, tetapi oleh compiler Java.

Anotasi ini dapat dilampirkan ke entitas AIDL mana pun. Anotasi ini tidak melakukan apa pun untuk backend non-Java.

RustDerive

RustDerive otomatis menerapkan trait untuk jenis Rust yang dihasilkan.

Anotasi memerlukan parameter tambahan untuk mengontrol apa yang akan dihasilkan. Parameter yang didukung adalah:

  • Copy=true
  • Clone=true
  • Ord=true
  • PartialOrd=true
  • Eq=true
  • PartialEq=true
  • Hash=true

Untuk penjelasan tentang sifat-sifat ini, lihat Dokumentasi Rust.

FixedSize

FixedSize menandai parcelable terstruktur sebagai ukuran tetap. Setelah ditandai, Anda tidak dapat menambahkan kolom baru ke parcelable. Semua kolom parcelable harus berupa jenis ukuran tetap, termasuk jenis primitif, enum, array ukuran tetap, dan parcelable lain yang ditandai dengan FixedSize.

Deskripsi

Descriptor secara paksa menentukan deskriptor antarmuka dari antarmuka:

package android.foo;

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

Deskriptor antarmuka ini adalah android.bar.IWorld. Jika anotasi Descriptor tidak ada, deskriptornya adalah android.foo.IHello.

Hal ini berguna untuk mengganti nama antarmuka yang sudah dipublikasikan. Membuat deskriptor antarmuka yang diganti namanya sama dengan deskriptor antarmuka sebelum penggantian nama memungkinkan kedua antarmuka berkomunikasi satu sama lain.

@hide di komentar

Compiler AIDL mengenali @hide dalam komentar dan meneruskannya ke output Java agar diambil oleh metalava. Komentar ini membantu memastikan bahwa sistem build Android mengenali bahwa API AIDL bukan API SDK.

@deprecated dalam komentar

Compiler AIDL mengenali @deprecated dalam komentar sebagai tag untuk mengidentifikasi entitas AIDL yang tidak boleh digunakan lagi:

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

Setiap backend menandai entity yang tidak digunakan lagi dengan anotasi atau atribut khusus backend sehingga kode klien akan diperingatkan jika merujuk ke entity yang tidak digunakan lagi. Misalnya, anotasi @Deprecated dan tag @deprecated dilampirkan ke kode yang dihasilkan Java.