Anotasi dalam AIDL

AIDL mendukung anotasi yang memberi kompiler AIDL info tambahan tentang elemen beranotasi, yang juga memengaruhi kode rintisan yang dihasilkan.

Sintaksnya mirip dengan Java:

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

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

Beberapa anotasi dapat memiliki argumen yang diatur di dalam tanda kurung, seperti yang ditunjukkan di atas. Anotasi yang tidak memiliki argumen tidak memerlukan tanda kurung. Sebagai contoh:

@AnnotationName AidlEntity

Anotasi ini tidak sama dengan anotasi Java, meskipun terlihat sangat mirip. Pengguna tidak dapat menentukan anotasi AIDL khusus; semua anotasi telah ditentukan sebelumnya. Beberapa anotasi hanya memengaruhi backend tertentu dan tidak berfungsi di backend lain. Mereka memiliki batasan yang 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
JavaOnlyStableParcelable 11
JavaDerive 12
JavaPassthrough 12
FixedSize 12
Descriptor 12

tidak dapat dibatalkan

nullable menyatakan bahwa nilai entitas beranotasi 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 cocok untuk backend Java. Ini karena, di Jawa, semua tipe non-primitif dilewatkan dengan referensi, yang bisa berupa null .

Di backend CPP, @nullable T memetakan 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 memetakan ke std::optional<T> .

Untuk tipe L seperti daftar seperti T[] atau List<T> , @nullable L memetakan ke std::optional<std::vector<std::optional<T>>> (atau std::unique_ptr<std::vector<std::unique_ptr<T>>> dalam hal backend CPP untuk Android 11 atau lebih rendah).

Ada pengecualian untuk pemetaan ini. Ketika T adalah IBinder atau antarmuka AIDL, @nullable adalah no-op. Dengan kata lain, baik @nullable IBinder dan IBinder sama-sama memetakan ke android::sp<IBinder> , yang sudah nullable karena merupakan pointer yang kuat (pembacaan CPP masih memberlakukan nullability, tetapi tipenya masih android::sp<IBinder> ).

Dimulai dengan Android T (AOSP eksperimental), @nullable(heap=true) dapat digunakan untuk bidang parcelable untuk memodelkan jenis rekursif. @nullable(heap=true) tidak dapat digunakan dengan parameter metode atau tipe pengembalian. Saat dianotasi dengannya, bidang 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 menyatakan bahwa sebuah String direpresentasikan dalam format UTF8 untuk backend CPP. Seperti namanya, anotasi adalah larangan untuk backend lainnya. Secara khusus, String selalu UTF16 di backend Java dan UTF8 di backend NDK.

Anotasi ini dapat dilampirkan di mana saja tipe String dapat digunakan, termasuk nilai kembalian, parameter, deklarasi konstanta, dan bidang parsel.

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

Perhatikan bahwa keberadaan anotasi utf8InCpp tidak mengubah cara string ditransmisikan melalui kabel. String selalu ditransmisikan sebagai UTF16 melalui kabel. String beranotasi utf8InCpp dikonversi ke UTF16 sebelum ditransmisikan. Ketika sebuah string diterima, string tersebut akan 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 tipe, tetapi ketika disetel, instans tipe 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 dirujuk dalam tipe tersebut juga harus dianotasi seperti itu. Pada contoh di bawah ini, 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 yang mendefinisikan tipe yang dianotasi dengan VintfStability hanya dapat dibuat menggunakan tipe modul aidl_interface Soong, dengan properti stability disetel ke "vintf" .

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

PenggunaanAplikasi yang Tidak Didukung

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

Anotasi UnsupportedAppUsage tidak memengaruhi perilaku kode yang dihasilkan. Anotasi hanya menganotasi 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-Java.

Dukungan

Anotasi Backing menentukan tipe penyimpanan tipe enum AIDL.

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

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

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

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

Argumen type hanya dapat disetel ke tipe integral berikut:

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

JavaOnlyStableParcelable

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

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

parcelable Data; // Data is NOT a structured parcelable

parcelable AnotherData {
    Data d; // Error
}

JavaOnlyStableParcelable memungkinkan Anda untuk mengesampingkan pemeriksaan ketika parcelable yang Anda rujuk sudah tersedia dengan aman sebagai bagian dari Android SDK.

@JavaOnlyStableParcelable
parcelable Data;

parcelable AnotherData {
    Data d; // OK
}

Turunan Jawa

JavaDerive secara otomatis menghasilkan metode untuk tipe 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 tipe dan bidang. Misalnya: Data{number: 42, str: foo}

JavaDefault

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

JawaPassthrough

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

Anotasi berikut dalam 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, itu tidak akan ditangkap oleh kompiler AIDL tetapi oleh kompiler Java.

Anotasi ini dapat dilampirkan ke entitas AIDL mana pun. Anotasi ini adalah larangan untuk backend non-Java.

Ukuran tetap

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

Ini tidak memberikan jaminan apa pun di berbagai bitness dan tidak boleh diandalkan untuk komunikasi bitness campuran.

deskripsi

Descriptor secara paksa menentukan deskriptor antarmuka dari 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 diterbitkan. Membuat deskriptor antarmuka yang diganti 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 output Java untuk metalava untuk diambil. Komentar ini memastikan bahwa sistem pembangunan Android mengetahui bahwa API AIDL bukan API SDK.

@ditinggalkan 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.