Anotasi di AIDL

AIDL mendukung anotasi yang memberikan info tambahan kepada kompiler AIDL tentang elemen yang dianotasi, yang juga memengaruhi kode rintisan yang dihasilkan.

Sintaksnya 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 mungkin memiliki argumen yang diatur di dalam tanda kurung, seperti yang ditunjukkan di atas. Anotasi yang tidak memiliki argumen tidak memerlukan tanda kurung. Misalnya:

@AnnotationName AidlEntity

Anotasi ini tidak sama dengan anotasi Java, meski terlihat sangat mirip. Pengguna tidak dapat menentukan anotasi AIDL khusus; semua anotasi sudah ditentukan sebelumnya. Beberapa anotasi hanya memengaruhi backend tertentu dan tidak dapat digunakan di backend lainnya. Mereka memiliki batasan berbeda di mana mereka dapat dilampirkan.

Di bawah ini adalah daftar anotasi AIDL yang telah ditentukan sebelumnya:

Anotasi Ditambahkan dalam 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

dapat dibatalkan

nullable menyatakan bahwa nilai entitas yang dianotasi tidak dapat diberikan.

Anotasi ini hanya dapat dilampirkan ke jenis pengembalian metode, parameter metode, dan bidang yang dapat dibagi.

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 tipe primitif. Berikut ini adalah kesalahan.

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

Anotasi ini tidak dapat digunakan untuk backend Java. Hal ini karena, di Java, semua tipe non-primitif diteruskan dengan referensi, yang bisa berupa null .

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

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

Untuk tipe 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>>> dalam kasus backend CPP untuk Android 11 atau lebih rendah).

Ada pengecualian untuk pemetaan ini. Jika T adalah IBinder atau antarmuka AIDL, @nullable tidak boleh dijalankan. Dengan kata lain, @nullable IBinder dan IBinder sama-sama dipetakan ke android::sp<IBinder> , yang sudah dapat dibatalkan karena merupakan penunjuk yang kuat (pembacaan CPP masih menerapkan nullabilitas, tetapi tipenya tetap android::sp<IBinder> ).

Dimulai dengan Android 13, @nullable(heap=true) dapat digunakan untuk kolom yang dapat dibagi untuk memodelkan tipe rekursif. @nullable(heap=true) tidak dapat digunakan dengan parameter metode atau tipe kembalian. Saat dianotasi dengannya, bidang tersebut dipetakan ke referensi yang dialokasikan heap std::unique_ptr<T> di backend CPP/NDK. @nullable(heap=true) tidak ada operasi di backend Java.

utf8InCpp

utf8InCpp mendeklarasikan bahwa sebuah String direpresentasikan dalam format UTF8 untuk backend CPP. Seperti yang ditunjukkan oleh namanya, anotasi ini tidak berlaku untuk backend lainnya. Secara khusus, String selalu berupa UTF16 di backend Java dan UTF8 di backend NDK.

Anotasi ini dapat dilampirkan di mana pun tipe String dapat digunakan, termasuk nilai kembalian, parameter, deklarasi konstan, dan bidang yang dapat dibagi.

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

Perhatikan bahwa keberadaan anotasi utf8InCpp tidak mengubah cara transmisi string melalui kabel. String selalu ditransmisikan sebagai UTF16 melalui kabel. String beranotasi utf8InCpp dikonversi ke UTF16 sebelum dikirim. Ketika sebuah string diterima, string tersebut dikonversi dari UTF16 ke UTF8 jika dianotasi sebagai utf8InCpp .

Stabilitas Vintf

VintfStability menyatakan bahwa tipe yang ditentukan pengguna (antarmuka, parsel, dan enum) dapat digunakan di seluruh sistem dan domain vendor. Lihat AIDL untuk HAL untuk mengetahui lebih lanjut tentang interoperabilitas sistem-vendor.

Anotasi tidak mengubah tanda tangan dari tipe tersebut, namun ketika diatur, instance dari tipe tersebut ditandai sebagai stabil sehingga dapat berjalan melintasi vendor dan proses sistem.

Anotasi hanya dapat dilampirkan ke deklarasi tipe yang ditentukan pengguna seperti yang ditunjukkan di bawah ini:

@VintfStability
interface IFoo {
    ....
}

@VintfStability
parcelable Data {
    ....
}

@VintfStability
enum Type {
    ....
}

Ketika suatu tipe dianotasi dengan VintfStability , tipe lain apa pun yang direferensikan dalam tipe tersebut juga harus dianotasi seperti itu. Pada contoh di bawah, 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, tipe definisi file AIDL yang dianotasi dengan VintfStability hanya dapat dibuat menggunakan tipe modul aidl_interface Soong, dengan properti stability diatur ke "vintf" .

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

Penggunaan Aplikasi Tidak Didukung

Anotasi UnsupportedAppUsage menunjukkan bahwa jenis AIDL yang dianotasi adalah bagian dari antarmuka non-SDK yang dapat diakses untuk aplikasi lama. Lihat Pembatasan antarmuka non-SDK untuk informasi selengkapnya tentang API tersembunyi.

Anotasi UnsupportedAppUsage tidak memengaruhi perilaku kode yang dihasilkan. Anotasi hanya memberi anotasi pada kelas 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 larangan untuk backend non-Jawa.

Dukungan

Anotasi Backing menentukan tipe penyimpanan tipe enum AIDL.

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

Di backend CPP, di atas memancarkan kelas C++ enum bertipe int32_t .

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

Jika anotasi dihilangkan, type diasumsikan byte , yang dipetakan ke int8_t untuk backend CPP.

Argumen type hanya dapat diatur ke tipe integral berikut:

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

NdkOnlyStableParcelable

NdkOnlyStableParcelable menandai deklarasi yang dapat dibagi (bukan definisi) sebagai stabil sehingga dapat direferensikan dari tipe AIDL stabil lainnya. Ini seperti JavaOnlyStableParcelable , namun NdkOnlyStableParcelable menandai deklarasi parsel sebagai stabil untuk backend NDK, bukan untuk Java.

Untuk menggunakan paket ini: * Anda harus menentukan ndk_header . * Anda harus memiliki perpustakaan NDK yang menentukan paketnya dan perpustakaan tersebut harus dikompilasi ke dalam perpustakaan. Misalnya, dalam sistem pembangunan inti pada modul cc_* , gunakan static_libs atau shared_libs . Untuk aidl_interface , tambahkan perpustakaan di bawah additional_shared_libraries di Android.bp .

JavaOnlyStableParcelable

JavaOnlyStableParcelable menandai deklarasi yang dapat dibagi (bukan definisi) sebagai stabil sehingga dapat direferensikan dari tipe AIDL stabil lainnya.

AIDL yang stabil mengharuskan semua tipe yang ditentukan pengguna stabil. Untuk parsel, menjadi stabil mengharuskan bidangnya 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 parsel tidak terstruktur (atau baru saja dideklarasikan), maka parsel tersebut tidak dapat direferensikan.

parcelable Data; // Data is NOT a structured parcelable

parcelable AnotherData {
    Data d; // Error
}

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

@JavaOnlyStableParcelable
parcelable Data;

parcelable AnotherData {
    Data d; // OK
}

JavaDeriv

JavaDerive secara otomatis menghasilkan metode untuk tipe paket 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 dengan dan hashCode .
  • toString=true menghasilkan metode toString yang mencetak nama jenis dan bidang. Misalnya: Data{number: 42, str: foo}

JavaDefault

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

JavaPassthrough

JavaPassthrough memungkinkan Java API yang dihasilkan dianotasi dengan anotasi Java yang berubah-ubah.

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 dipancarkan. Kompiler AIDL tidak melihat nilai parameter. Jika ada kesalahan sintaksis tingkat Java, kesalahan tersebut tidak akan ditangkap oleh kompiler AIDL tetapi oleh kompiler Java.

Anotasi ini dapat dilampirkan ke entitas AIDL mana pun. Anotasi ini tidak berlaku untuk backend non-Jawa.

Ukuran tetap

FixedSize menandai parsel terstruktur sebagai ukuran tetap. Setelah ditandai, parsel tidak akan diizinkan untuk menambahkan bidang baru ke dalamnya. Semua bidang dari parsel juga harus bertipe berukuran tetap, termasuk tipe primitif, enum, array berukuran tetap, dan parsel lainnya yang ditandai dengan FixedSize .

Hal ini tidak memberikan jaminan apa pun pada bitness yang berbeda dan tidak dapat diandalkan untuk komunikasi bitness campuran.

Deskripsi

Descriptor secara paksa menentukan deskriptor antarmuka suatu antarmuka.

package android.foo;

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

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

Ini berguna untuk mengganti nama antarmuka yang sudah dipublikasikan. Menjadikan deskriptor antarmuka yang diubah namanya sama dengan deskriptor antarmuka sebelum penggantian nama memungkinkan kedua antarmuka untuk berbicara satu sama lain.

@sembunyikan di komentar

Kompiler AIDL mengenali @hide dalam komentar dan meneruskannya ke keluaran Java untuk diambil oleh metalava. Komentar ini memastikan bahwa sistem build Android mengetahui bahwa API AIDL bukanlah API SDK.

@tidak digunakan lagi dalam komentar

Kompiler 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 entitas yang tidak digunakan lagi dengan anotasi/atribut khusus backend sehingga kode klien diperingatkan jika merujuk pada entitas yang tidak digunakan lagi. Misalnya, anotasi @Deprecated dan tag @deprecated dilampirkan ke kode yang dihasilkan Java.