AIDL Stabil

Android 10 menambahkan dukungan untuk Android Interface Definition Language (AIDL) stabil, cara baru untuk memantau antarmuka program aplikasi (API)/antarmuka biner aplikasi (ABI) yang disediakan oleh antarmuka AIDL. AIDL stabil memiliki beberapa perbedaan utama berikut dengan AIDL:

  • Antarmuka ditentukan dalam sistem build dengan aidl_interfaces.
  • Antarmuka hanya boleh berisi data terstruktur. Parcelable yang mewakili jenis yang diinginkan dibuat secara otomatis berdasarkan definisi AIDL mereka dan secara otomatis disusun dan tidak disusun.
  • Antarmuka dapat dideklarasikan sebagai stabil (kompatibel dengan versi lama). Jika hal ini terjadi, API-nya akan dilacak dan dibuat versi dalam file di samping antarmuka AIDL.

AIDL terstruktur versus stabil

AIDL terstruktur mengacu pada jenis yang ditentukan hanya dalam AIDL. Misalnya, deklarasi parcelable (parcelable kustom) bukan AIDL terstruktur. Parcelable dengan kolom yang ditentukan dalam AIDL disebut structured parcelable.

AIDL stabil memerlukan AIDL terstruktur agar sistem build dan compiler dapat memahami apakah perubahan yang dibuat pada parcelable kompatibel dengan versi lama. Namun, tidak semua antarmuka terstruktur stabil. Agar stabil, antarmuka hanya boleh menggunakan jenis terstruktur, dan juga harus menggunakan fitur pembuatan versi berikut. Sebaliknya, antarmuka tidak stabil jika sistem build inti digunakan untuk membangunnya atau jika unstable:true disetel.

Mendefinisikan antarmuka AIDL

Definisi aidl_interface akan terlihat seperti ini:

aidl_interface {
    name: "my-aidl",
    srcs: ["srcs/aidl/**/*.aidl"],
    local_include_dir: "srcs/aidl",
    imports: ["other-aidl"],
    versions_with_info: [
        {
            version: "1",
            imports: ["other-aidl-V1"],
        },
        {
            version: "2",
            imports: ["other-aidl-V3"],
        }
    ],
    stability: "vintf",
    backend: {
        java: {
            enabled: true,
            platform_apis: true,
        },
        cpp: {
            enabled: true,
        },
        ndk: {
            enabled: true,
        },
        rust: {
            enabled: true,
        },
    },

}
  • name: Nama modul antarmuka AIDL yang mengidentifikasi antarmuka AIDL secara unik.
  • srcs: Daftar file sumber AIDL yang menyusun antarmuka. Jalur untuk Foo jenis AIDL yang ditentukan dalam com.acme paket harus berada di <base_path>/com/acme/Foo.aidl, dengan <base_path> dapat berupa direktori apa pun yang terkait dengan direktori tempat Android.bp berada. Pada contoh di atas, <base_path> adalah srcs/aidl.
  • local_include_dir: Jalur tempat nama paket dimulai. Hal ini sesuai dengan <base_path> yang dijelaskan di atas.
  • imports: Daftar modul aidl_interface yang digunakannya. Jika salah satu antarmuka AIDL Anda menggunakan antarmuka atau parcelable dari aidl_interface lain, masukkan namanya di sini. Nama ini dapat berupa nama itu sendiri, untuk merujuk ke versi terbaru, atau nama dengan akhiran versi (seperti -V1) untuk merujuk ke versi tertentu. Menentukan versi telah didukung sejak Android 12
  • versions: Versi antarmuka sebelumnya yang dibekukan dalam api_dir. Mulai Android 11, versions akan dibekukan di bawah aidl_api/name. Jika tidak ada versi antarmuka yang dibekukan, hal ini tidak boleh ditentukan, dan tidak akan ada pemeriksaan kompatibilitas. Kolom ini telah diganti dengan versions_with_info untuk 13 dan yang lebih baru.
  • versions_with_info: Daftar tuple, yang masing-masing berisi nama versi yang dibekukan dan daftar dengan impor versi modul aidl_interface lainnya yang diimpor oleh versi aidl_interface ini. Definisi versi V dari antarmuka AIDL IFACE terletak di aidl_api/IFACE/V. Kolom ini diperkenalkan di Android 13, dan tidak boleh diubah di Android.bp secara langsung. Kolom ini ditambahkan atau diperbarui dengan memanggil *-update-api atau *-freeze-api. Selain itu, kolom versions otomatis dimigrasikan ke versions_with_info saat pengguna memanggil *-update-api atau *-freeze-api.
  • stability: Flag opsional untuk janji stabilitas antarmuka ini. Saat ini, setelan ini hanya mendukung "vintf". Jika stability tidak disetel, sistem build akan memeriksa apakah antarmuka tersebut kompatibel dengan versi lama kecuali jika unstable ditentukan. Jika kebijakan tidak disetel, antarmuka dengan stabil dalam konteks kompilasi ini (baik semua hal sistem, misalnya hal-hal di system.img dan partisi terkait, atau semua hal vendor, misalnya hal-hal di vendor.img dan partisi terkait). Jika stability disetel ke "vintf", ini sesuai dengan promise stabilitas: antarmuka harus tetap stabil selama digunakan.
  • gen_trace: Flag opsional untuk mengaktifkan atau menonaktifkan pelacakan. Mulai Android 14, defaultnya adalah true untuk backend cpp dan java.
  • host_supported: Flag opsional yang jika ditetapkan ke true akan membuat library yang dihasilkan tersedia untuk lingkungan host.
  • unstable: Flag opsional yang digunakan untuk menandai bahwa antarmuka ini tidak harus stabil. Jika disetel ke true, sistem build tidak akan membuat dump API untuk antarmuka atau mengharuskannya diupdate.
  • frozen: Flag opsional yang jika ditetapkan ke true berarti antarmuka tidak memiliki perubahan sejak versi antarmuka sebelumnya. Hal ini memungkinkan lebih banyak pemeriksaan waktu build. Jika ditetapkan ke false, ini berarti antarmuka sedang dalam pengembangan dan memiliki perubahan baru, sehingga menjalankan foo-freeze-api akan menghasilkan versi baru dan otomatis mengubah nilai menjadi true. Diperkenalkan di Android 14.
  • backend.<type>.enabled: Tanda ini mengalihkan setiap backend yang menghasilkan kode oleh compiler AIDL. Saat ini, empat backend didukung: Java, C++, NDK, dan Rust. Backend Java, C++, dan NDK diaktifkan secara default. Jika salah satu dari ketiga backend ini tidak diperlukan, backend harus dinonaktifkan secara eksplisit. Rust dinonaktifkan secara default hingga Android 15 (Eksperimental AOSP).
  • backend.<type>.apex_available: Daftar nama APEX yang menyediakan library stub yang dihasilkan.
  • backend.[cpp|java].gen_log: Flag opsional yang mengontrol apakah akan menghasilkan kode tambahan untuk mengumpulkan informasi tentang transaksi atau tidak.
  • backend.[cpp|java].vndk.enabled: Flag opsional untuk menjadikan antarmuka ini bagian dari VNDK. Defaultnya adalah false.
  • backend.[cpp|ndk].additional_shared_libraries: Diperkenalkan di Android 14, flag ini menambahkan dependensi ke library native. Tanda ini berguna dengan ndk_header dan cpp_header.
  • backend.java.sdk_version: Flag opsional untuk menentukan versi SDK yang menjadi dasar pembuatan library stub Java. Defaultnya adalah "system_current". Nilai ini tidak boleh ditetapkan jika backend.java.platform_apis benar.
  • backend.java.platform_apis: Flag opsional yang harus ditetapkan ke true saat library yang dihasilkan harus di-build dengan API platform, bukan SDK.

Untuk setiap kombinasi versi dan backend yang diaktifkan, library stub akan dibuat. Untuk mengetahui cara merujuk ke versi tertentu library stub untuk backend tertentu, lihat Aturan penamaan modul.

Menulis file AIDL

Antarmuka di AIDL stabil mirip dengan antarmuka tradisional, tetapi tidak diizinkan menggunakan parcelable tidak terstruktur (karena tidak stabil. lihat AIDL terstruktur versus stabil). Perbedaan utama dalam AIDL stabil adalah cara parcelable ditentukan. Sebelumnya, parcelable dideklarasikan ke depan; dalam AIDL stabil (dan karenanya terstruktur), kolom dan variabel parcelable ditentukan secara eksplisit.

// in a file like 'some/package/Thing.aidl'
package some.package;

parcelable SubThing {
    String a = "foo";
    int b;
}

Default saat ini didukung (tetapi tidak wajib) untuk boolean, char, float, double, byte, int, long, dan String. Di Android 12, setelan default untuk enumerasi yang ditentukan pengguna juga didukung. Jika nilai default tidak ditentukan, nilai seperti 0 atau kosong akan digunakan. Enumerasi tanpa nilai default diinisialisasi ke 0 meskipun tidak ada enumerator nol.

Menggunakan library stub

Setelah menambahkan library stub sebagai dependensi ke modul, Anda dapat menyertakannya ke dalam file. Berikut adalah contoh library stub dalam sistem build (Android.mk juga dapat digunakan untuk definisi modul lama):

cc_... {
    name: ...,
    shared_libs: ["my-module-name-cpp"],
    ...
}
# or
java_... {
    name: ...,
    // can also be shared_libs if desire is to load a library and share
    // it among multiple users or if you only need access to constants
    static_libs: ["my-module-name-java"],
    ...
}
# or
rust_... {
    name: ...,
    rustlibs: ["my-module-name-rust"],
    ...
}

Contoh dalam C++:

#include "some/package/IFoo.h"
#include "some/package/Thing.h"
...
    // use just like traditional AIDL

Contoh di Java:

import some.package.IFoo;
import some.package.Thing;
...
    // use just like traditional AIDL

Contoh dalam Rust:

use aidl_interface_name::aidl::some::package::{IFoo, Thing};
...
    // use just like traditional AIDL

Antarmuka pembuatan versi

Mendeklarasikan modul dengan nama foo juga akan membuat target dalam sistem build yang dapat Anda gunakan untuk mengelola API modul. Saat dibuat, foo-freeze-api menambahkan definisi API baru pada api_dir atau aidl_api/name, bergantung pada versi Android, dan menambahkan file .hash, yang keduanya mewakili antarmuka yang baru dibekukan. foo-freeze-api juga mengupdate properti versions_with_info untuk mencerminkan versi tambahan dan imports untuk versi tersebut. Pada dasarnya, imports di versions_with_info disalin dari kolom imports. Namun, versi stabil terbaru ditentukan di imports di versions_with_info untuk impor yang tidak memiliki versi eksplisit. Setelah properti versions_with_info ditentukan, sistem build akan menjalankan pemeriksaan kompatibilitas antara versi frozen serta antara Top of Tree (ToT) dan versi frozen terbaru.

Selain itu, Anda perlu mengelola definisi API versi ToT. Setiap kali API diupdate, jalankan foo-update-api untuk mengupdate aidl_api/name/current yang berisi definisi API versi ToT.

Untuk menjaga stabilitas antarmuka, pemilik dapat menambahkan hal baru:

  • Metode untuk akhir antarmuka (atau metode dengan serial baru yang ditentukan secara eksplisit)
  • Elemen ke akhir parcelable (harus ditambahkan secara default untuk setiap elemen)
  • Nilai konstanta
  • Di Android 11, enumerator
  • Di Android 12, kolom ke akhir union

Tidak ada tindakan lain yang diizinkan, dan tidak ada orang lain yang dapat memodifikasi antarmuka (jika tidak, mereka berisiko bentrok dengan perubahan yang dibuat oleh pemilik).

Untuk menguji apakah semua antarmuka dibekukan untuk dirilis, Anda dapat mem-build dengan kumpulan variabel lingkungan berikut:

  • AIDL_FROZEN_REL=true m ... - build mengharuskan semua antarmuka AIDL stabil dibekukan yang tidak memiliki kolom owner: yang ditentukan.
  • AIDL_FROZEN_OWNERS="aosp test" - build mengharuskan semua antarmuka AIDL stabil dibekukan dengan kolom owner: yang ditentukan sebagai "AOSP" atau "test".

Stabilitas impor

Memperbarui versi impor untuk versi antarmuka yang dibekukan akan memiliki kompatibilitas mundur pada lapisan AIDL Stabil. Namun, mengupdate hal ini mengharuskan mengupdate semua server dan klien yang menggunakan antarmuka versi lama, dan beberapa aplikasi dapat membingungkan saat menggabungkan jenis versi yang berbeda. Umumnya, untuk paket khusus jenis atau umum, hal ini aman karena kode harus sudah ditulis untuk menangani jenis yang tidak diketahui dari transaksi IPC.

Dalam kode platform Android, kode android.hardware.graphics.common adalah contoh terbesar dari jenis upgrade versi ini.

Menggunakan antarmuka berversi

Metode antarmuka

Saat runtime, ketika mencoba memanggil metode baru di server lama, klien baru akan mendapatkan error atau pengecualian, bergantung pada backend-nya.

  • Backend cpp mendapatkan ::android::UNKNOWN_TRANSACTION.
  • Backend ndk mendapatkan STATUS_UNKNOWN_TRANSACTION.
  • Backend java mendapatkan android.os.RemoteException dengan pesan yang menyatakan API tidak diimplementasikan.

Untuk mengetahui strategi guna menangani hal ini, lihat versi membuat kueri dan menggunakan default.

Parcelable

Saat kolom baru ditambahkan ke parcelable, klien dan server lama akan menghapusnya. Saat klien dan server baru menerima parcelable lama, nilai default untuk kolom baru akan otomatis diisi. Ini berarti bahwa {i>default<i} harus ditentukan untuk semua {i>field<i} baru di parcelable.

Klien tidak perlu mengharapkan server menggunakan kolom baru, kecuali jika mereka mengetahui bahwa server menerapkan versi kolom yang telah ditentukan (lihat versi membuat kueri).

Enum dan konstanta

Demikian pula, klien dan server harus menolak atau mengabaikan nilai konstanta dan enumerator yang tidak dikenal sebagaimana mestinya, karena nilai konstanta dan enumerator yang tidak dikenal mungkin akan ditambahkan di masa mendatang. Misalnya, server tidak boleh dibatalkan saat menerima enumerator yang tidak diketahuinya. Tindakan ini harus mengabaikannya, atau menampilkan sesuatu agar klien tahu bahwa kode tersebut tidak didukung dalam implementasi ini.

Serikat

Mencoba mengirim union dengan kolom baru akan gagal jika penerima sudah lama dan tidak mengetahui kolom tersebut. Implementasi tidak akan pernah melihat gabungan dengan kolom baru. Kegagalan akan diabaikan jika merupakan transaksi satu arah; jika tidak, error-nya adalah BAD_VALUE(untuk backend C++ atau NDK) atau IllegalArgumentException(untuk backend Java). Error diterima jika klien mengirimkan union yang ditetapkan ke kolom baru ke server lama, atau jika klien adalah klien lama yang menerima union dari server baru.

Pengembangan berbasis bendera

Antarmuka dalam pengembangan (tidak dibekukan) tidak dapat digunakan pada perangkat rilis karena tidak dijamin akan kompatibel dengan versi lama.

AIDL mendukung penggantian waktu proses untuk library antarmuka yang tidak dibekukan ini agar kode dapat ditulis terhadap versi terbaru yang tidak dibekukan dan masih digunakan pada perangkat rilis. Perilaku klien yang kompatibel dengan versi lama serupa dengan perilaku yang ada dan dengan penggantian, implementasi juga harus mengikuti perilaku tersebut. Lihat Menggunakan antarmuka berversi.

Flag build AIDL

Flag yang mengontrol perilaku ini adalah RELEASE_AIDL_USE_UNFROZEN yang ditentukan dalam build/release/build_flags.bzl. true berarti versi antarmuka yang tidak dibekukan digunakan pada runtime, dan false berarti semua library versi yang tidak dibekukan berperilaku seperti versi frozen terakhir. Anda dapat mengganti tanda ini ke true untuk pengembangan lokal, tetapi harus mengembalikannya ke false sebelum rilis. Biasanya, pengembangan dilakukan dengan konfigurasi yang menetapkan tanda ke true.

Matriks dan manifes kompatibilitas

Objek antarmuka vendor (objek VINTF) menentukan versi yang diharapkan, dan versi yang disediakan di kedua sisi antarmuka vendor.

Sebagian besar perangkat non-Cuttlefish menargetkan matriks kompatibilitas terbaru hanya setelah antarmuka dibekukan, sehingga tidak ada perbedaan dalam library AIDL berdasarkan RELEASE_AIDL_USE_UNFROZEN.

Matriks

Antarmuka milik partner ditambahkan ke matriks kompatibilitas khusus perangkat atau khusus produk yang ditargetkan perangkat selama pengembangan. Jadi, saat versi antarmuka baru yang tidak dibekukan ditambahkan ke matriks kompatibilitas, versi yang dibekukan sebelumnya harus tetap digunakan untuk RELEASE_AIDL_USE_UNFROZEN=false. Anda dapat menangani hal ini dengan menggunakan file matriks kompatibilitas yang berbeda untuk konfigurasi RELEASE_AIDL_USE_UNFROZEN yang berbeda, atau mengizinkan kedua versi dalam satu file matriks kompatibilitas yang digunakan dalam semua konfigurasi.

Misalnya, saat menambahkan versi 4 yang tidak dibekukan, gunakan <version>3-4</version>.

Jika versi 4 dibekukan, Anda dapat menghapus versi 3 dari matriks kompatibilitas karena versi yang dibekukan akan digunakan jika RELEASE_AIDL_USE_UNFROZEN adalah false.

Manifes

Di Android 15 (Eksperimental AOSP), perubahan pada libvintf diperkenalkan untuk mengubah file manifes pada waktu build berdasarkan nilai RELEASE_AIDL_USE_UNFROZEN.

Manifes dan fragmen manifes mendeklarasikan versi antarmuka mana yang diimplementasikan oleh layanan. Saat menggunakan versi antarmuka yang tidak dibekukan terbaru, manifes harus diupdate untuk mencerminkan versi baru ini. Saat RELEASE_AIDL_USE_UNFROZEN=false, entri manifes disesuaikan oleh libvintf untuk mencerminkan perubahan dalam library AIDL yang dihasilkan. Versi ini diubah dari versi tidak dibekukan, N, menjadi versi beku terakhir N - 1. Oleh karena itu, pengguna tidak perlu mengelola beberapa manifes atau fragmen manifes untuk setiap layanan mereka.

Perubahan klien HAL

Kode klien HAL harus kompatibel dengan versi frozen sebelumnya yang didukung. Jika RELEASE_AIDL_USE_UNFROZEN adalah false, layanan akan selalu terlihat seperti versi beku terakhir atau yang lebih lama (misalnya, memanggil metode baru yang tidak dibekukan akan menampilkan UNKNOWN_TRANSACTION, atau kolom parcelable baru memiliki nilai defaultnya). Klien framework Android harus memiliki kompatibilitas mundur dengan versi tambahan sebelumnya, tetapi ini merupakan detail baru untuk klien vendor dan klien antarmuka milik partner.

Perubahan implementasi HAL

Perbedaan terbesar dalam pengembangan HAL dengan pengembangan berbasis tanda adalah persyaratan agar implementasi HAL kompatibel dengan versi frozen terakhir agar dapat berfungsi saat RELEASE_AIDL_USE_UNFROZEN adalah false. Mempertimbangkan kompatibilitas mundur dalam implementasi dan kode perangkat adalah latihan baru. Lihat Menggunakan antarmuka berversi.

Pertimbangan kompatibilitas mundur umumnya sama untuk klien dan server, serta untuk kode framework dan kode vendor, tetapi ada sedikit perbedaan yang perlu Anda ketahui, karena Anda sekarang secara efektif menerapkan dua versi yang menggunakan kode sumber yang sama (versi saat ini yang tidak dibekukan).

Contoh: Antarmuka memiliki tiga versi frozen. Antarmuka diupdate dengan metode baru. Klien dan layanan diupdate untuk menggunakan library versi 4 yang baru. Karena didasarkan pada versi antarmuka yang tidak dibekukan, library ini akan berperilaku seperti versi beku terakhir, versi 3, jika RELEASE_AIDL_USE_UNFROZEN adalah false, dan mencegah penggunaan metode baru.

Saat antarmuka dibekukan, semua nilai RELEASE_AIDL_USE_UNFROZEN akan menggunakan versi frozen tersebut, dan kode yang menangani kompatibilitas mundur dapat dihapus.

Saat memanggil metode pada callback, Anda harus menangani kasus dengan baik ketika UNKNOWN_TRANSACTION ditampilkan. Klien mungkin mengimplementasikan dua versi callback yang berbeda berdasarkan konfigurasi rilis, sehingga Anda tidak dapat berasumsi bahwa klien akan mengirimkan versi terbaru, dan metode baru mungkin menampilkannya. Hal ini mirip dengan cara klien AIDL stabil mempertahankan kompatibilitas mundur dengan server yang dijelaskan dalam Menggunakan antarmuka berversi.

// Get the callback along with the version of the callback
ScopedAStatus RegisterMyCallback(const std::shared_ptr<IMyCallback>& cb) override {
    mMyCallback = cb;
    // Get the version of the callback for later when we call methods on it
    auto status = mMyCallback->getInterfaceVersion(&mMyCallbackVersion);
    return status;
}

// Example of using the callback later
void NotifyCallbackLater() {
  // From the latest frozen version (V2)
  mMyCallback->foo();
  // Call this method from the unfrozen V3 only if the callback is at least V3
  if (mMyCallbackVersion >= 3) {
    mMyCallback->bar();
  }
}

Kolom baru dalam jenis yang ada (parcelable, enum, union) mungkin tidak ada atau berisi nilai defaultnya jika RELEASE_AIDL_USE_UNFROZEN adalah false dan nilai kolom baru yang coba dikirim oleh layanan akan dihapus saat proses selesai.

Jenis baru yang ditambahkan dalam versi tidak beku ini tidak dapat dikirim atau diterima melalui antarmuka.

Implementasi tidak pernah mendapatkan panggilan untuk metode baru dari klien jika RELEASE_AIDL_USE_UNFROZEN adalah false.

Berhati-hatilah saat menggunakan enumerator baru hanya dengan versi yang diperkenalkan, bukan versi sebelumnya.

Biasanya, Anda menggunakan foo->getInterfaceVersion() untuk melihat versi yang digunakan antarmuka jarak jauh. Namun, dengan dukungan pembuatan versi berbasis tanda, Anda mengimplementasikan dua versi yang berbeda, sehingga Anda mungkin ingin mendapatkan versi antarmuka saat ini. Anda dapat melakukannya dengan mendapatkan versi antarmuka objek saat ini, misalnya this->getInterfaceVersion() atau metode lain untuk my_ver. Lihat Mengkueri versi antarmuka objek jarak jauh untuk mengetahui informasi selengkapnya.

Antarmuka stabil VINTF baru

Saat paket antarmuka AIDL baru ditambahkan, tidak akan ada versi frozen terakhir, sehingga tidak ada perilaku yang dapat dikembalikan saat RELEASE_AIDL_USE_UNFROZEN adalah false. Jangan gunakan antarmuka ini. Jika RELEASE_AIDL_USE_UNFROZEN adalah false, Pengelola Layanan tidak akan mengizinkan layanan untuk mendaftarkan antarmuka dan klien tidak akan menemukannya.

Anda dapat menambahkan layanan secara kondisional berdasarkan nilai flag RELEASE_AIDL_USE_UNFROZEN dalam makefile perangkat:

ifeq ($(RELEASE_AIDL_USE_UNFROZEN),true)
PRODUCT_PACKAGES += \
    android.hardware.health.storage-service
endif

Jika layanan adalah bagian dari proses yang lebih besar sehingga Anda tidak dapat menambahkannya ke perangkat secara bersyarat, Anda dapat memeriksa apakah layanan dideklarasikan dengan IServiceManager::isDeclared(). Jika sudah dideklarasikan dan gagal didaftarkan, batalkan proses. Jika tidak dideklarasikan, maka diperkirakan gagal didaftarkan.

Sotong sebagai alat pengembangan

Setiap tahun setelah VINTF dibekukan, kami menyesuaikan matriks kompatibilitas framework (FCM) target-level dan PRODUCT_SHIPPING_API_LEVEL Cuttlefish agar mencerminkan perangkat yang diluncurkan dengan rilis tahun depan. Kami menyesuaikan target-level dan PRODUCT_SHIPPING_API_LEVEL untuk memastikan ada beberapa perangkat yang diluncurkan yang telah diuji dan memenuhi persyaratan baru untuk rilis tahun depan.

Jika RELEASE_AIDL_USE_UNFROZEN adalah true, Cuttlefish digunakan untuk pengembangan rilis Android mendatang. Rilis ini menargetkan level FCM dan PRODUCT_SHIPPING_API_LEVEL rilis Android tahun depan, yang mengharuskannya memenuhi Persyaratan Software Vendor (VSR) rilis berikutnya.

Jika RELEASE_AIDL_USE_UNFROZEN adalah false, Cuttlefish memiliki target-level dan PRODUCT_SHIPPING_API_LEVEL sebelumnya untuk mencerminkan perangkat rilis. Di Android 14 dan yang lebih rendah, diferensiasi ini akan dilakukan dengan cabang Git lain yang tidak menerima perubahan ke FCM target-level, pengiriman API level, atau kode lain yang menargetkan rilis berikutnya.

Aturan penamaan modul

Di Android 11, untuk setiap kombinasi versi dan backend yang diaktifkan, modul library stub akan dibuat secara otomatis. Untuk merujuk ke modul library stub tertentu untuk penautan, jangan gunakan nama modul aidl_interface, melainkan nama modul library stub, yaitu ifacename-version-backend, dengan

  • ifacename: nama modul aidl_interface
  • version adalah salah satu dari
    • Vversion-number untuk versi beku
    • Vlatest-frozen-version-number + 1 untuk versi ujung pohon (belum beku)
  • backend adalah salah satu dari
    • java untuk backend Java,
    • cpp untuk backend C++,
    • ndk atau ndk_platform untuk backend NDK. Yang pertama adalah untuk aplikasi, dan yang terakhir untuk penggunaan platform,
    • rust untuk backend Rust.

Asumsikan ada modul dengan nama foo dan versi terbarunya adalah 2, dan mendukung NDK dan C++. Dalam hal ini, AIDL akan menghasilkan modul berikut:

  • Berdasarkan versi 1
    • foo-V1-(java|cpp|ndk|ndk_platform|rust)
  • Berdasarkan versi 2 (versi stabil terbaru)
    • foo-V2-(java|cpp|ndk|ndk_platform|rust)
  • Berdasarkan versi ToT
    • foo-V3-(java|cpp|ndk|ndk_platform|rust)

Dibandingkan dengan Android 11,

  • foo-backend, yang merujuk ke versi stabil terbaru menjadi foo-V2-backend
  • foo-unstable-backend, yang dirujuk ke versi ToT menjadi foo-V3-backend

Nama file output selalu sama dengan nama modul.

  • Berdasarkan versi 1: foo-V1-(cpp|ndk|ndk_platform|rust).so
  • Berdasarkan versi 2: foo-V2-(cpp|ndk|ndk_platform|rust).so
  • Berdasarkan versi ToT: foo-V3-(cpp|ndk|ndk_platform|rust).so

Perlu diperhatikan bahwa compiler AIDL tidak membuat modul versi unstable, atau modul tanpa versi untuk antarmuka AIDL stabil. Mulai Android 12, nama modul yang dihasilkan dari antarmuka AIDL stabil selalu menyertakan versi.

Metode antarmuka meta baru

Android 10 menambahkan beberapa metode antarmuka meta untuk AIDL stabil.

Membuat kueri versi antarmuka objek jarak jauh

Klien dapat mengkueri versi dan hash antarmuka yang diterapkan oleh objek jarak jauh dan membandingkan nilai yang ditampilkan dengan nilai antarmuka yang digunakan klien.

Contoh dengan backend cpp:

sp<IFoo> foo = ... // the remote object
int32_t my_ver = IFoo::VERSION;
int32_t remote_ver = foo->getInterfaceVersion();
if (remote_ver < my_ver) {
  // the remote side is using an older interface
}

std::string my_hash = IFoo::HASH;
std::string remote_hash = foo->getInterfaceHash();

Contoh dengan backend ndk (dan ndk_platform):

IFoo* foo = ... // the remote object
int32_t my_ver = IFoo::version;
int32_t remote_ver = 0;
if (foo->getInterfaceVersion(&remote_ver).isOk() && remote_ver < my_ver) {
  // the remote side is using an older interface
}

std::string my_hash = IFoo::hash;
std::string remote_hash;
foo->getInterfaceHash(&remote_hash);

Contoh dengan backend java:

IFoo foo = ... // the remote object
int myVer = IFoo.VERSION;
int remoteVer = foo.getInterfaceVersion();
if (remoteVer < myVer) {
  // the remote side is using an older interface
}

String myHash = IFoo.HASH;
String remoteHash = foo.getInterfaceHash();

Untuk bahasa Java, sistem jarak jauh HARUS mengimplementasikan getInterfaceVersion() dan getInterfaceHash() sebagai berikut (super digunakan sebagai pengganti IFoo untuk menghindari kesalahan salin/tempel. Anotasi @SuppressWarnings("static") mungkin diperlukan untuk menonaktifkan peringatan, bergantung pada konfigurasi javac):

class MyFoo extends IFoo.Stub {
    @Override
    public final int getInterfaceVersion() { return super.VERSION; }

    @Override
    public final String getInterfaceHash() { return super.HASH; }
}

Hal ini karena class yang dihasilkan (IFoo, IFoo.Stub, dll.) digunakan bersama antara klien dan server (misalnya, class dapat berada di classpath boot). Saat class dibagikan, server juga akan ditautkan ke class terbaru meskipun class mungkin telah di-build dengan versi antarmuka yang lebih lama. Jika diimplementasikan di class bersama, antarmuka meta ini akan selalu menampilkan versi terbaru. Namun, dengan menerapkan metode seperti di atas, nomor versi antarmuka akan disematkan dalam kode server (karena IFoo.VERSION adalah static final int yang menjadi inline saat direferensikan), sehingga metode ini dapat menampilkan versi yang sama persis dengan yang digunakan untuk membangun server.

Menangani antarmuka yang lebih lama

Ada kemungkinan klien diupdate dengan versi antarmuka AIDL yang lebih baru, tetapi server menggunakan antarmuka AIDL lama. Dalam kasus tersebut, memanggil metode pada antarmuka lama akan menampilkan UNKNOWN_TRANSACTION.

Dengan AIDL stabil, klien memiliki kontrol yang lebih besar. Di sisi klien, Anda dapat menetapkan implementasi default ke antarmuka AIDL. Metode dalam implementasi default hanya dipanggil jika metode tersebut tidak diimplementasikan di sisi jarak jauh (karena di-build dengan versi antarmuka yang lebih lama). Karena default ditetapkan secara global, nilai default tidak boleh digunakan dari konteks yang berpotensi bersama.

Contoh di C++ di Android 13 dan yang lebih baru:

class MyDefault : public IFooDefault {
  Status anAddedMethod(...) {
   // do something default
  }
};

// once per an interface in a process
IFoo::setDefaultImpl(::android::sp<MyDefault>::make());

foo->anAddedMethod(...); // MyDefault::anAddedMethod() will be called if the
                         // remote side is not implementing it

Contoh di Java:

IFoo.Stub.setDefaultImpl(new IFoo.Default() {
    @Override
    public xxx anAddedMethod(...)  throws RemoteException {
        // do something default
    }
}); // once per an interface in a process


foo.anAddedMethod(...);

Anda tidak perlu menyediakan implementasi default untuk semua metode dalam antarmuka AIDL. Metode yang dijamin akan diimplementasikan di sisi jarak jauh (karena Anda yakin bahwa remote di-build saat metode berada dalam deskripsi antarmuka AIDL) tidak perlu diganti di class impl default.

Mengonversi AIDL yang ada menjadi AIDL terstruktur/stabil

Jika Anda sudah memiliki antarmuka AIDL dan kode yang menggunakannya, gunakan langkah-langkah berikut untuk mengonversi antarmuka menjadi antarmuka AIDL yang stabil.

  1. Identifikasi semua dependensi antarmuka Anda. Untuk setiap paket yang menjadi dependensi antarmuka, tentukan apakah paket didefinisikan dalam AIDL stabil. Jika tidak ditentukan, paket harus dikonversi.

  2. Mengonversi semua parcelable di antarmuka Anda menjadi parcelable stabil (file antarmuka itu sendiri tetap tidak berubah). Lakukan hal ini dengan mengekspresikan strukturnya secara langsung dalam file AIDL. Kelas manajemen harus ditulis ulang untuk menggunakan tipe baru ini. Hal ini dapat dilakukan sebelum Anda membuat paket aidl_interface (di bawah).

  3. Buat paket aidl_interface (seperti dijelaskan di atas) yang berisi nama modul Anda, dependensinya, dan informasi lain yang Anda butuhkan. Untuk membuatnya stabil (tidak hanya terstruktur), model tersebut juga perlu dibuat versinya. Untuk mengetahui informasi selengkapnya, lihat Antarmuka pembuatan versi.