Anotasi dalam AIDL

AIDL mendukung anotasi yang memberikan info tambahan kepada compiler AIDL tentang elemen yang dianotasi, 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 entity AIDL seperti interface Foo, void method(), atau int arg. Channel dilampirkan pada entitas yang mengikutinya.

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

@AnnotationName AidlEntity

Anotasi ini tidak sama dengan Java walaupun keduanya terlihat sangat mirip. Pengguna tidak dapat menentukan AIDL kustom anotasi; semua anotasi telah ditetapkan sebelumnya. Beberapa anotasi hanya memengaruhi backend tertentu dan tidak ada pengoperasian di backend lainnya. Terdapat berbagai pembatasan yang dapat dilampirkan.

Berikut adalah daftar anotasi AIDL yang telah ditetapkan sebelumnya:

Anotasi Ditambahkan di versi 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 mendeklarasikan bahwa nilai entity yang dianotasi mungkin tidak diberikan.

Anotasi ini hanya dapat dilampirkan ke jenis nilai yang ditampilkan metode, parameter metode, dan parcelable.

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 ini adalah error.

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

Anotasi ini tidak memiliki pengoperasian untuk backend Java. Hal ini karena, di Java, semua jenis non-primitif diteruskan melalui referensi, yang dapat berupa null.

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

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

Untuk jenis L seperti daftar 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 backend CPP untuk Android 11 atau yang lebih lama).

Ada pengecualian untuk pemetaan ini. Saat T adalah IBinder atau antarmuka AIDL, @nullable tidak beroperasi. Dengan kata lain, keduanya @nullable IBinder dan IBinder sama-sama dipetakan ke android::sp<IBinder>, yang sudah nullable karena merupakan pointer yang kuat (CPP membaca diam menerapkan nullability, tetapi jenisnya masih android::sp<IBinder>).

Mulai Android 13, @nullable(heap=true) dapat digunakan untuk isian yang dapat dibagikan untuk memodelkan tipe rekursif. @nullable(heap=true) tidak dapat digunakan dengan parameter metode atau jenis nilai yang ditampilkan. Ketika dianotasi dengannya, bidang ini akan dipetakan ke referensi dengan alokasi heap std::unique_ptr<T> di CPP/NDK backend. @nullable(heap=true) tidak memiliki pengoperasian di backend Java.

{i>utf8InCpp<i}

utf8InCpp mendeklarasikan bahwa String direpresentasikan dalam format UTF8 untuk CPP backend. Seperti namanya, anotasi ini merupakan tanpa pengoperasian untuk backend lainnya. Secara khusus, String selalu UTF16 di backend Java dan UTF8 di NDK backend.

Anotasi ini dapat disertakan di mana pun jenis String dapat digunakan, termasuk nilai return, parameter, deklarasi konstanta, dan parcelable kolom.

Untuk backend CPP, @utf8InCpp String di AIDL dipetakan ke std::string, sedangkan String tanpa anotasi dipetakan ke android::String16 yang menggunakan UTF16.

Perlu diperhatikan bahwa keberadaan anotasi utf8InCpp tidak mengubah cara {i>string<i} ditransmisikan melalui kabel. String selalu ditransmisikan sebagai UTF16 melalui kabel. String beranotasi utf8InCpp dikonversi ke UTF16 sebelum ditransmisikan. Ketika diterima, string dikonversi dari UTF16 ke UTF8 jika dianotasi sebagai utf8InCpp.

Kestabilan

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

Anotasi tidak mengubah tanda tangan jenis, tetapi ketika diatur, instance jenis ditandai sebagai stabil sehingga dapat melakukan perjalanan 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 dianotasikan dengan VintfStability, jenis lain apa pun yang di dalam tipe itu juga harus dianotasi sebagaimana mestinya. Dalam contoh, Data dan IBar harus dianotasi 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 menentukan jenis yang dianotasi dengan VintfStability hanya dapat dibuat menggunakan jenis modul aidl_interface Soong, dengan Properti stability ditetapkan ke "vintf".

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

PenggunaanAplikasi yang Tidak Didukung

Anotasi UnsupportedAppUsage menunjukkan bahwa jenis AIDL yang dianotasi bagian dari antarmuka non-SDK yang dapat diakses untuk aplikasi lama. Lihat Batasan terkait non-SDK antarmuka untuk 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 kondisi tanpa pengoperasian untuk backend non-Java.

Pendukung

Anotasi Backing menentukan jenis penyimpanan jenis enum AIDL.

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

Di backend CPP, class ini memunculkan class enum C++ jenis int32_t.

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

Jika anotasi dihilangkan, type diasumsikan sebagai byte, yang memetakan 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 parcelable (bukan definisi) stabil sehingga bisa direferensikan dari jenis AIDL stabil lainnya. Ini seperti JavaOnlyStableParcelable, tetapi NdkOnlyStableParcelable menandai deklarasi parcelable sebagai stabil untuk NDK backend, 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, dalam sistem build inti pada Modul cc_*, gunakan static_libs atau shared_libs. Untuk aidl_interface, tambahkan library di bawah additional_shared_libraries di Android.bp.

JavaOnlyStableParcelable

JavaOnlyStableParcelable menandai deklarasi parcelable (bukan definisi) stabil sehingga bisa direferensikan dari jenis AIDL stabil lainnya.

AIDL stabil mengharuskan semua jenis yang ditentukan pengguna stabil. Sebagai 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 tidak dapat yang direferensikan.

parcelable Data; // Data is NOT a structured parcelable

parcelable AnotherData {
    Data d; // Error
}

JavaOnlyStableParcelable memungkinkan Anda mengganti pemeriksaan saat parcelable yang Anda rujuk sudah tersedia dengan aman sebagai bagian dari Android SDK.

@JavaOnlyStableParcelable
parcelable Data;

parcelable AnotherData {
    Data d; // OK
}

JavaDerive

JavaDerive otomatis menghasilkan metode untuk jenis parcelable di Backend Java.

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

Anotasi membutuhkan parameter tambahan untuk mengontrol buat. Parameter yang didukung adalah:

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

JavaDefault

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

JavaPassthrough

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

Anotasi berikut di AIDL

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

menjadi

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

dalam kode Java yang dihasilkan.

Nilai parameter annotation langsung ditampilkan. AIDL compiler tidak mempertimbangkan nilai parameter. Jika ada pada tingkat Java, itu tidak akan ditangkap oleh compiler AIDL tetapi oleh compiler Java.

Anotasi ini dapat disertakan ke entitas AIDL mana pun. Anotasi ini adalah tanpa pengoperasian untuk backend non-Java.

Ukuran Tetap

FixedSize menandai parcelable terstruktur sebagai ukuran tetap. Setelah ditandai, parcelable tidak akan diizinkan untuk menambahkan {i>field<i} baru ke dalamnya. Semua bidang {i>parcelable<i} juga harus berupa jenis berukuran tetap, termasuk jenis primitif, enum, array ukuran tetap, dan parcelable lainnya yang ditandai dengan FixedSize.

Hal ini tidak memberikan jaminan pada jumlah pesan yang berbeda dan seharusnya tidak diandalkan untuk komunikasi {i>mix-bitness<i}.

Deskripsi

Descriptor secara paksa menentukan deskriptor antarmuka antarmuka.

package android.foo;

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

Deskripsi 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. Melakukan deskriptor antarmuka yang diganti namanya sama dengan deskriptor antarmuka sebelum penggantian nama memungkinkan kedua antarmuka berkomunikasi satu sama lain.

@sembunyikan di komentar

Compiler AIDL mengenali @hide dalam komentar dan meneruskannya melalui ke output Java untuk metalava yang akan diambil. Komentar ini memastikan bahwa Android sistem build tahu bahwa API AIDL bukan API SDK.

@tidak digunakan lagi di komentar

Compiler AIDL mengenali @deprecated dalam komentar sebagai tag untuk mengidentifikasi Entitas AIDL yang sebaiknya tidak digunakan lagi.

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

Setiap backend menandai entity yang tidak digunakan lagi dengan anotasi khusus backend atau sehingga kode klien akan diperingatkan jika mengacu pada kode yang entitas. Misalnya, anotasi @Deprecated dan @deprecated yang dikaitkan dengan kode yang dihasilkan Java.