AIDL Stabil

Android 10 menambahkan dukungan untuk Antarmuka Android stabil Definition Language (AIDL), cara baru untuk melacak program aplikasi antarmuka (API) dan antarmuka biner aplikasi (ABI) yang disediakan oleh AIDL antarmuka. AIDL stabil bekerja persis seperti AIDL, tetapi sistem build melacak kompatibilitas antarmuka, dan ada batasan pada apa yang dapat Anda lakukan:

  • Antarmuka ditentukan dalam sistem build dengan aidl_interfaces.
  • Antarmuka hanya boleh berisi data terstruktur. Parcelable yang mewakili jenis yang disukai dibuat secara otomatis berdasarkan definisi AIDL mereka dan akan disusun dan diatur{i> <i}secara otomatis.
  • Antarmuka dapat dideklarasikan sebagai stabil (kompatibel dengan versi lama). Jika terjadi, API mereka dilacak dan dibuat versinya dalam file di samping AIDL dalam antarmuka berbasis web yang sederhana.

AIDL terstruktur versus stabil

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

AIDL stabil memerlukan AIDL terstruktur sehingga sistem build dan compiler dapat memahami apakah perubahan yang dibuat pada parcelable kompatibel dengan versi sebelumnya. Namun, tidak semua antarmuka terstruktur stabil. Agar stabil, antarmuka harus menggunakan jenis terstruktur saja, dan itu juga harus menggunakan pembuatan versi yang baru. Sebaliknya, antarmuka tidak stabil jika build inti digunakan untuk membangunnya atau jika unstable:true disetel.

Menentukan 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 secara unik mengidentifikasi AIDL.
  • srcs: Daftar file sumber AIDL yang menyusun antarmuka. Jalur untuk jenis AIDL Foo yang ditentukan dalam paket com.acme 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. Dalam contoh sebelumnya, <base_path> adalah srcs/aidl.
  • local_include_dir: Jalur tempat nama paket dimulai. Ini sesuai dengan <base_path> yang dijelaskan di atas.
  • imports: Daftar modul aidl_interface yang digunakannya. Jika salah satu Antarmuka AIDL menggunakan antarmuka atau parcelable dari aidl_interface, masukkan namanya di sini. Dapat berupa nama itu sendiri, untuk merujuk ke versi, atau nama dengan akhiran versi (seperti -V1) yang akan dirujuk menggunakan versi tertentu. Menentukan versi telah didukung sejak Android 12
  • versions: Versi antarmuka sebelumnya yang berhenti di bawah api_dir, Mulai Android 11, versions akan dibekukan dalam aidl_api/name. Jika tidak ada versi beku dari antarmuka, ini tidak boleh ditentukan, dan tidak akan ada pemeriksaan kompatibilitas. Kolom ini telah diganti dengan versions_with_info untuk Android 13 dan lebih tinggi.
  • versions_with_info: Daftar tuple, yang masing-masing berisi nama versi frozen dan daftar dengan impor versi aidl_interface lainnya modul yang diimpor oleh versi {i> aidl_interface<i} ini. Definisi versi V dari antarmuka AIDL IFACE terletak di aidl_api/IFACE/V. Kolom ini diperkenalkan di Android 13, dan tidak boleh dimodifikasi di Android.bp secara langsung. Isiannya adalah yang ditambahkan atau diperbarui dengan memanggil *-update-api atau *-freeze-api. Selain itu, versions kolom otomatis dimigrasikan ke versions_with_info saat pengguna memanggil *-update-api atau *-freeze-api.
  • stability: Flag opsional untuk janji stabilitas antarmuka ini. Ini hanya mendukung "vintf". Jika stability tidak disetel, build sistem akan memeriksa apakah antarmukanya kompatibel dengan versi sebelumnya, kecuali unstable ditentukan. Jika kebijakan tidak disetel, antarmuka akan stabilitas dalam konteks kompilasi ini (baik semua hal sistem, untuk misalnya, hal-hal di system.img dan partisi terkait, atau semua vendor misalnya hal-hal di vendor.img dan partisi terkait). Jika stability disetel ke "vintf", yang sesuai dengan promise stabilitas: antarmuka harus tetap stabil selama digunakan.
  • gen_trace: Flag opsional untuk mengaktifkan atau menonaktifkan pelacakan. Dimulai dalam Android 14, defaultnya adalah true untuk cpp dan backend java.
  • host_supported: Flag opsional yang jika ditetapkan ke true akan membuat yang dihasilkan oleh library yang tersedia di lingkungan {i>host<i}.
  • unstable: Flag opsional yang digunakan untuk menandai bahwa antarmuka ini tidak stabil. Jika kebijakan ini disetel ke true, sistem build tidak akan membuat dump API untuk antarmuka atau mengharuskannya diupdate.
  • frozen: Tanda opsional yang jika ditetapkan ke true berarti bahwa antarmuka tidak memiliki perubahan sejak versi antarmuka sebelumnya. Hal ini memungkinkan lebih banyak pemeriksaan waktu build. Jika ditetapkan ke false, ini berarti antarmuka digunakan dan memiliki perubahan baru, jadi menjalankan foo-freeze-api akan menghasilkan versi baru dan secara otomatis mengubah nilainya menjadi true. Diperkenalkan dalam Android 14.
  • backend.<type>.enabled: Tanda ini mengalihkan setiap backend yang yang dihasilkan oleh kompiler AIDL. Empat backend adalah didukung: Java, C++, NDK, dan Rust. Backend Java, C++, dan NDK diaktifkan secara {i>default<i}. Jika salah satu dari ketiga {i>backend<i} ini tidak diperlukan, maka perlu dinonaktifkan secara eksplisit. Rust dinonaktifkan secara default hingga Android 15.
  • backend.<type>.apex_available: Daftar nama APEX yang dihasilkan library stub tersedia.
  • backend.[cpp|java].gen_log: Flag opsional yang mengontrol apakah akan membuat kode tambahan untuk mengumpulkan informasi tentang transaksi.
  • backend.[cpp|java].vndk.enabled: Flag opsional untuk membuat antarmuka ini bagian dari VNDK. Defaultnya adalah false.
  • backend.[cpp|ndk].additional_shared_libraries: Diperkenalkan dalam 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". Ini tidak boleh disetel jika backend.java.platform_apis adalah true.
  • backend.java.platform_apis: Flag opsional yang harus ditetapkan ke true saat library yang dihasilkan harus di-build dengan API platform dan bukan SDK.

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

Menulis file AIDL

Antarmuka di AIDL stabil mirip dengan antarmuka tradisional, dengan pengecualian bahwa mereka tidak diperbolehkan menggunakan parcelable tidak terstruktur (karena ini tidak stabil! lihat Terstruktur versus stabil AIDL). Perbedaan utama dalam AIDL stabil adalah bagaimana parcelable ditentukan. Sebelumnya, parcelable dideklarasikan ke depan; inci AIDL stabil (dan karenanya terstruktur), isian dan variabel parcelables didefinisikan secara eksplisit.

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

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

Setelan default didukung (tetapi tidak wajib) untuk boolean, char, float, double, byte, int, long, dan String. Di Android 12, 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 ada tidak ada enumerator nol.

Menggunakan library stub

Setelah menambahkan library stub sebagai dependensi ke modul, dapat memasukkannya ke dalam file Anda. Berikut contoh library stub di 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 your preference 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. Setelah dibuat, foo-freeze-api menambahkan definisi API baru berdasarkan api_dir atau aidl_api/name, bergantung pada versi Android, dan menambahkan file .hash, keduanya mewakili versi yang baru dibekukan dalam antarmuka berbasis web yang sederhana. foo-freeze-api juga memperbarui properti versions_with_info untuk mencerminkan versi tambahan dan imports untuk versi tersebut. Pada dasarnya, imports di versions_with_info disalin dari kolom imports. Tapi 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 berjalan pemeriksaan kompatibilitas antara versi yang dibekukan dan juga antara Top of Tree (ToT) dan versi beku 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 ke akhir antarmuka (atau metode dengan ID baru yang didefinisikan secara eksplisit serial)
  • Elemen ke akhir parcelable (harus ditambahkan 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 mengubah antarmuka (jika tidak, mereka berisiko bentrok dengan perubahan yang dibuat pemilik).

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

  • AIDL_FROZEN_REL=true m ... - build memerlukan semua antarmuka AIDL stabil untuk dibekukan yang tidak mempunyai bidang owner: yang ditetapkan.
  • AIDL_FROZEN_OWNERS="aosp test" - build memerlukan semua antarmuka AIDL stabil dibekukan dengan kolom owner: yang ditentukan sebagai "AOSP" atau "uji coba".

Stabilitas impor

Memperbarui versi impor untuk versi antarmuka yang dibekukan adalah kompatibel dengan versi sebelumnya di lapisan AIDL Stabil. Namun, pembaruan ini memerlukan memperbarui semua server dan klien yang menggunakan antarmuka versi sebelumnya, dan beberapa aplikasi mungkin bingung saat menggabungkan berbagai versi jenis. Umumnya, untuk paket khusus jenis atau umum, ini aman karena kode perlu sudah ditulis untuk menangani jenis yang tidak diketahui dari transaksi IPC.

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

Menggunakan antarmuka berversi

Metode antarmuka

Saat runtime, ketika mencoba memanggil metode baru di server lama, klien baru akan mengalami error atau pengecualian, tergantung 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 diterapkan.

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

Parcelable

Saat kolom baru ditambahkan ke parcelable, klien dan server lama akan menghapusnya. Ketika klien dan server baru menerima parcelable lama, nilai default untuk akan terisi secara otomatis. Ini berarti {i>default-<i}nya harus yang ditentukan untuk semua kolom baru dalam parcelable.

Klien tidak seharusnya mengharapkan server menggunakan {i>field <i}baru kecuali mereka mengetahui server mengimplementasikan versi yang memiliki {i>field<i} yang sudah ditentukan (lihat versi kueri).

Enum dan konstanta

Demikian pula, klien dan server harus menolak atau mengabaikan konstanta dan enumerator yang sesuai, karena lebih banyak lagi dapat ditambahkan dalam masa depan. Misalnya, server tidak boleh membatalkan saat menerima enumerator yang tidak diketahuinya. Server harus mengabaikan enumerator, atau menampilkan sesuatu sehingga klien tahu itu tidak didukung di dalam implementasi ini.

Serikat

Upaya mengirim union dengan isian baru akan gagal jika penerima sudah lawas dan tidak mengetahui bidang tersebut. Implementasinya tidak akan pernah membedakan ikatan dengan bidang baru. Kegagalan akan diabaikan jika transaksi satu arah; jika tidak, error-nya adalah BAD_VALUE(untuk C++ atau NDK backend) atau IllegalArgumentException(untuk backend Java). Errornya adalah diterima jika klien mengirimkan union yang ditetapkan ke kolom baru ke server, atau ketika itu adalah klien lama yang menerima gabungan dari server baru.

Mengelola beberapa versi

Namespace penaut di Android hanya dapat memiliki 1 versi aidl tertentu untuk menghindari situasi ketika jenis aidl yang dihasilkan memiliki beberapa definisi. C++ memiliki Satu Aturan Definisi yang hanya memerlukan satu definisi dari setiap simbol.

Build Android akan memberikan error jika modul bergantung pada dari library aidl_interface yang sama. Modul mungkin tergantung pada perpustakaan ini secara langsung atau tidak langsung melalui dependensi dependensi. Error ini menampilkan grafik dependensi dari modul yang gagal versi library aidl_interface yang bertentangan. Semua dependensi perlu diupdate untuk menyertakan versi yang sama (biasanya yang terbaru) library ini.

Jika library antarmuka digunakan oleh banyak modul yang berbeda, library ini akan sangat membantu untuk membuat cc_defaults, java_defaults, dan rust_defaults untuk grup apa pun {i>library<i} dan proses yang perlu menggunakan versi yang sama. Saat memperkenalkan antarmuka versi baru, {i>default<i}-nya dapat diperbarui dan semua modul menggunakannya diperbarui bersama, memastikan bahwa mereka tidak menggunakan versi yang berbeda antarmuka.

cc_defaults {
  name: "my.aidl.my-process-group-ndk-shared",
  shared_libs: ["my.aidl-V3-ndk"],
  ...
}

cc_library {
  name: "foo",
  defaults: ["my.aidl.my-process-group-ndk-shared"],
  ...
}

cc_binary {
  name: "bar",
  defaults: ["my.aidl.my-process-group-ndk-shared"],
  ...
}

Saat modul aidl_interface mengimpor modul aidl_interface lainnya, hal ini akan membuat dependensi tambahan yang memerlukan versi tertentu untuk digunakan bersama. Ini situasi ini dapat menjadi sulit dikelola jika terdapat aidl_interface modul yang diimpor dalam beberapa modul aidl_interface yang digunakan bersama-sama dalam proses yang sama.

aidl_interfaces_defaults dapat digunakan untuk menyimpan salah satu definisi versi terbaru dependensi untuk aidl_interface yang dapat diupdate di satu tempat, dan digunakan oleh semua modul aidl_interface yang ingin mengimpor antarmuka yang umum itu.

aidl_interface_defaults {
  name: "android.popular.common-latest-defaults",
  imports: ["android.popular.common-V3"],
  ...
}

aidl_interface {
  name: "android.foo",
  defaults: ["my.aidl.latest-ndk-shared"],
  ...
}

aidl_interface {
  name: "android.bar",
  defaults: ["my.aidl.latest-ndk-shared"],
  ...
}

Pengembangan berbasis bendera

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

AIDL mendukung fallback waktu proses untuk library antarmuka yang tidak dibekukan ini secara berurutan agar kode ditulis berdasarkan versi terbaru yang tidak dibekukan dan masih digunakan pada perangkat rilis. Perilaku klien yang kompatibel dengan versi mundur mirip dengan perilaku yang ada dan dengan penggantian, implementasi juga harus mengikuti perilaku-perilaku tersebut. Lihat Gunakan antarmuka berversi.

Flag build AIDL

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

Matriks dan manifes kompatibilitas

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

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

Matriks

Antarmuka milik partner ditambahkan ke perangkat atau produk tertentu matriks kompatibilitas yang ditargetkan perangkat selama pengembangan. Jadi, ketika seorang versi antarmuka yang baru dan tidak beku ditambahkan ke matriks kompatibilitas, versi beku sebelumnya harus tetap bertahan selama RELEASE_AIDL_USE_UNFROZEN=false. Anda dapat menangani hal ini dengan menggunakan berbagai file matriks kompatibilitas untuk berbagai RELEASE_AIDL_USE_UNFROZEN konfigurasi umum atau mengizinkan kedua versi dalam satu file matriks kompatibilitas yang digunakan di 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 frozen 4 digunakan saat RELEASE_AIDL_USE_UNFROZEN false.

Manifes

Di Android 15, perubahan dalam libvintf diperkenalkan untuk mengubah file manifes pada waktu pembangunan berdasarkan nilai RELEASE_AIDL_USE_UNFROZEN.

Manifes dan fragmen manifes mendeklarasikan versi antarmuka yang diimplementasikan oleh suatu layanan. Saat menggunakan versi antarmuka yang tidak dibekukan, manifes harus diperbarui untuk mencerminkan versi baru ini. Kapan RELEASE_AIDL_USE_UNFROZEN=false entri manifes disesuaikan dengan libvintf untuk mencerminkan perubahan dalam library AIDL yang dihasilkan. Versi diubah dari versi yang tidak dibekukan, N, menjadi versi dibekukan terakhir N - 1. Oleh karena itu, pengguna tidak perlu mengelola banyak manifes atau fragmen manifes yang sama untuk setiap layanannya.

Perubahan klien HAL

Kode klien HAL harus kompatibel dengan kode frozen sebelumnya yang didukung . Jika RELEASE_AIDL_USE_UNFROZEN adalah false, layanan akan selalu terlihat seperti versi beku terakhir atau sebelumnya (misalnya, memanggil versi baru yang tidak dibekukan menampilkan UNKNOWN_TRANSACTION, atau kolom parcelable baru memiliki nilai default). Klien framework Android harus menjalankan versi sebelumnya dengan versi tambahan sebelumnya, tetapi ini adalah detail baru untuk klien vendor, dan klien dari antarmuka yang dimiliki mitra.

Perubahan implementasi HAL

Perbedaan terbesar dalam pengembangan HAL dengan pengembangan berbasis flag adalah persyaratan implementasi HAL agar kompatibel dengan versi frozen akan berfungsi jika RELEASE_AIDL_USE_UNFROZEN adalah false. Mempertimbangkan kompatibilitas mundur dalam implementasi dan kode perangkat adalah latihan. Lihat Menggunakan berversi antarmuka.

Pertimbangan kompatibilitas mundur umumnya sama untuk klien dan server, dan untuk kode kerangka kerja dan kode vendor, tetapi ada perbedaan kecil yang perlu Anda perhatikan, karena Anda sekarang secara efektif menerapkan dua versi yang menggunakan kode sumber yang sama (versi saat ini, ).

Contoh: Antarmuka memiliki tiga versi frozen. Antarmuka diperbarui dengan metode baru. Klien dan layanan diupdate untuk menggunakan versi baru 4 library. Karena pustaka V4 didasarkan pada versi {i>unfrozen<i} dari , perilakunya seperti versi beku terakhir, versi 3, saat RELEASE_AIDL_USE_UNFROZEN adalah false, dan mencegah penggunaan metode baru.

Saat antarmuka dibekukan, semua nilai RELEASE_AIDL_USE_UNFROZEN akan menggunakan fungsi tersebut versi beku, 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 dari callback berdasarkan konfigurasi rilis, sehingga Anda tidak bisa mengasumsikan bahwa klien mengirimkan versi terbaru, dan metode baru mungkin mengembalikan ini. Ini mirip dengan cara klien AIDL stabil mempertahankan versi sebelumnya kompatibilitas dengan server yang dijelaskan di Menggunakan versi antarmuka.

// 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 saat RELEASE_AIDL_USE_UNFROZEN false dan nilai kolom baru yang coba dikirim oleh layanan akan dihapus jalan keluar dari proses tersebut.

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

Implementasi tidak pernah menerima panggilan untuk metode baru dari klien mana pun RELEASE_AIDL_USE_UNFROZEN adalah false.

Hati-hati saat menggunakan enumerator baru hanya dengan versi yang diperkenalkan, dan bukan versi sebelumnya.

Biasanya, Anda menggunakan foo->getInterfaceVersion() untuk melihat versi remote control digunakan oleh antarmuka Anda. Namun, dengan dukungan pembuatan versi berbasis tanda, Anda menerapkan dua versi yang berbeda, jadi Anda mungkin ingin mendapatkan versi antarmuka saat ini. Anda dapat melakukannya dengan mendapatkan versi antarmuka objek saat ini, misalnya, this->getInterfaceVersion() atau yang lainnya metode untuk my_ver. Lihat Mengkueri versi antarmuka remote objek untuk informasi selengkapnya.

Antarmuka stabil VINTF baru

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

Anda dapat menambahkan layanan secara bersyarat berdasarkan nilai Tanda RELEASE_AIDL_USE_UNFROZEN pada 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 bersyarat, Anda dapat memeriksa untuk melihat apakah layanan dideklarasikan dengan IServiceManager::isDeclared(). Jika dinyatakan dan gagal didaftarkan, maka membatalkan proses. Jika tidak dideklarasikan, maka diperkirakan gagal didaftarkan.

Sotong sebagai alat pengembangan

Setiap tahun setelah VINTF dibekukan, kami menyesuaikan kompatibilitas framework matrix (FCM) target-level dan PRODUCT_SHIPPING_API_LEVEL Cuttlefish sehingga mencerminkan perangkat yang akan diluncurkan dengan rilis tahun depan. Kita menyesuaikan target-level dan PRODUCT_SHIPPING_API_LEVEL untuk memastikan ada beberapa meluncurkan perangkat yang telah diuji dan memenuhi persyaratan baru untuk uji coba data.

Jika RELEASE_AIDL_USE_UNFROZEN adalah true, cumi-cumi adalah yang digunakan untuk pengembangan rilis Android mendatang. Target Android tahun depan level FCM dan PRODUCT_SHIPPING_API_LEVEL rilis, sehingga harus memenuhi rilis berikutnya yang berjudul Vendor Software Requirements (VSR).

Jika RELEASE_AIDL_USE_UNFROZEN adalah false, Sotong memiliki atribut sebelumnya target-level dan PRODUCT_SHIPPING_API_LEVEL untuk mencerminkan perangkat rilis. Di Android 14 dan yang lebih lama, diferensiasi ini akan menjadi dicapai dengan berbagai cabang Git yang tidak menerima perubahan pada FCM target-level, API level pengiriman, atau kode lain yang menargetkan level data.

Aturan penamaan modul

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

  • ifacename: nama modul aidl_interface
  • version adalah salah satu
    • Vversion-number untuk versi beku
    • Vlatest-frozen-version-number + 1 untuk versi tip-of-tree (belum beku)
  • backend adalah salah satu
    • java untuk backend Java,
    • cpp untuk backend C++,
    • ndk atau ndk_platform untuk backend NDK. Yang pertama adalah untuk aplikasi, dan yang terakhir adalah untuk penggunaan platform hingga Android 13. Di beberapa Android 13 dan yang lebih baru, hanya gunakan ndk.
    • rust untuk backend Rust.

Misalkan ada modul dengan nama foo dan versi terbarunya adalah 2, dan mendukung NDK dan C++. Dalam hal ini, AIDL menghasilkan modul-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 versi menjadi foo-V2-backend
  • foo-unstable-backend, yang merujuk pada ToT versi 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 AIDL stabil selalu menyertakan versinya.

Metode antarmuka meta baru

Android 10 menambahkan beberapa metode antarmuka meta untuk AIDL yang stabil.

Mengkueri versi antarmuka objek jarak jauh

Klien dapat mengkueri versi dan hash antarmuka yang objek jarak jauh mengimplementasikan dan membandingkan nilai yang dikembalikan 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 saat menyalin dan menempel. 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.) dibagikan antara klien dan server (misalnya, kelas-kelas bisa dalam proses booting {i>classpath<i}). Ketika kelas dibagikan, server juga ditautkan ke versi terbaru meskipun mungkin telah dibuat dengan database versi antarmuka. Jika antarmuka meta ini diimplementasikan dalam , versi terbaru akan selalu ditampilkan. Namun, dengan menerapkan metode seperti di atas, nomor versi antarmuka ditanamkan dalam kode server (karena IFoo.VERSION adalah static final int yang menjadi inline saat direferensikan) sehingga metode ini bisa mengembalikan versi yang sama dengan yang digunakan untuk membangun server.

Menangani antarmuka yang lebih lama

Mungkin saja klien diperbarui dengan versi AIDL yang lebih baru tapi server menggunakan antarmuka AIDL lama. Dalam kasus tersebut, memanggil metode di antarmuka lama akan menampilkan UNKNOWN_TRANSACTION.

Dengan AIDL stabil, klien memiliki kontrol yang lebih besar. Di sisi klien, Anda bisa mengatur implementasi default ke antarmuka AIDL. Sebuah metode dalam nilai default hanya akan dipanggil jika metode tidak diterapkan di remote (karena dibuat dengan versi antarmuka yang lebih lama). Sejak ditetapkan secara global, dan tidak boleh digunakan dari sumber konteks tambahan.

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 semua metode dalam AIDL dalam antarmuka berbasis web yang sederhana. Metode yang dijamin akan diimplementasikan di sisi jarak jauh (karena Anda yakin bahwa remote dibangun ketika metode berada di Deskripsi antarmuka AIDL) tidak perlu diganti di impl default .

Mengonversi AIDL yang ada menjadi AIDL terstruktur atau stabil

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

  1. Identifikasi semua dependensi antarmuka Anda. Untuk setiap paket, bergantung pada, menentukan apakah paket ditentukan dalam AIDL stabil. Jika tidak ditentukan, paket harus dikonversi.

  2. Konversi semua parcelable di antarmuka Anda menjadi parcelable stabil ( file antarmuka itu sendiri bisa tetap tidak berubah). Lakukan 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 yang dijelaskan di atas) yang berisi nama modul Anda, dependensinya, dan informasi lain apa pun yang Anda butuhkan. Untuk membuatnya stabil (tidak hanya terstruktur), model tersebut juga perlu dibuat versinya. Untuk mengetahui informasi selengkapnya, lihat Antarmuka pembuatan versi.