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 AIDLFoo
yang ditentukan dalam paketcom.acme
harus berada di<base_path>/com/acme/Foo.aidl
, dengan<base_path>
dapat berupa direktori apa pun yang terkait dengan direktori tempatAndroid.bp
berada. Dalam contoh sebelumnya,<base_path>
adalahsrcs/aidl
.local_include_dir
: Jalur tempat nama paket dimulai. Ini sesuai dengan<base_path>
yang dijelaskan di atas.imports
: Daftar modulaidl_interface
yang digunakannya. Jika salah satu Antarmuka AIDL menggunakan antarmuka atau parcelable dariaidl_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 12versions
: Versi antarmuka sebelumnya yang berhenti di bawahapi_dir
, Mulai Android 11,versions
akan dibekukan dalamaidl_api/name
. Jika tidak ada versi beku dari antarmuka, ini tidak boleh ditentukan, dan tidak akan ada pemeriksaan kompatibilitas. Kolom ini telah diganti denganversions_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 diaidl_api/IFACE/V
. Kolom ini diperkenalkan di Android 13, dan tidak boleh dimodifikasi diAndroid.bp
secara langsung. Isiannya adalah yang ditambahkan atau diperbarui dengan memanggil*-update-api
atau*-freeze-api
. Selain itu,versions
kolom otomatis dimigrasikan keversions_with_info
saat pengguna memanggil*-update-api
atau*-freeze-api
.stability
: Flag opsional untuk janji stabilitas antarmuka ini. Ini hanya mendukung"vintf"
. Jikastability
tidak disetel, build sistem akan memeriksa apakah antarmukanya kompatibel dengan versi sebelumnya, kecualiunstable
ditentukan. Jika kebijakan tidak disetel, antarmuka akan stabilitas dalam konteks kompilasi ini (baik semua hal sistem, untuk misalnya, hal-hal disystem.img
dan partisi terkait, atau semua vendor misalnya hal-hal divendor.img
dan partisi terkait). Jikastability
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 adalahtrue
untukcpp
dan backendjava
.host_supported
: Flag opsional yang jika ditetapkan ketrue
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 ketrue
, sistem build tidak akan membuat dump API untuk antarmuka atau mengharuskannya diupdate.frozen
: Tanda opsional yang jika ditetapkan ketrue
berarti bahwa antarmuka tidak memiliki perubahan sejak versi antarmuka sebelumnya. Hal ini memungkinkan lebih banyak pemeriksaan waktu build. Jika ditetapkan kefalse
, ini berarti antarmuka digunakan dan memiliki perubahan baru, jadi menjalankanfoo-freeze-api
akan menghasilkan versi baru dan secara otomatis mengubah nilainya menjaditrue
. 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 adalahfalse
.backend.[cpp|ndk].additional_shared_libraries
: Diperkenalkan dalam Android 14, flag ini menambahkan dependensi ke library native. Tanda ini berguna denganndk_header
dancpp_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 jikabackend.java.platform_apis
adalahtrue
.backend.java.platform_apis
: Flag opsional yang harus ditetapkan ketrue
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 bidangowner:
yang ditetapkan.AIDL_FROZEN_OWNERS="aosp test"
- build memerlukan semua antarmuka AIDL stabil dibekukan dengan kolomowner:
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
mendapatkanSTATUS_UNKNOWN_TRANSACTION
. - Backend
java
mendapatkanandroid.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 modulaidl_interface
version
adalah salah satuVversion-number
untuk versi bekuVlatest-frozen-version-number + 1
untuk versi tip-of-tree (belum beku)
backend
adalah salah satujava
untuk backend Java,cpp
untuk backend C++,ndk
ataundk_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 gunakanndk
.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 menjadifoo-V2-backend
foo-unstable-backend
, yang merujuk pada ToT versi menjadifoo-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.
Identifikasi semua dependensi antarmuka Anda. Untuk setiap paket, bergantung pada, menentukan apakah paket ditentukan dalam AIDL stabil. Jika tidak ditentukan, paket harus dikonversi.
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).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.