Vendor APEX

Anda dapat menggunakan format file APEX untuk mengemas dan menginstal modul Android OS tingkat yang lebih rendah. Hal ini memungkinkan pembuatan dan penginstalan komponen secara independen seperti layanan dan library native, implementasi HAL, firmware, file konfigurasi, dll.

APEX vendor diinstal oleh sistem build secara otomatis di partisi /vendor dan diaktifkan saat runtime oleh apexd, sama seperti APEX di partisi lain.

Kasus penggunaan

Modularisasi gambar vendor

APEX memfasilitasi pengelompokan dan modularisasi alami dari penerapan fitur pada image vendor.

Saat image vendor dibuat sebagai kombinasi APEX vendor yang dibuat secara independen, produsen perangkat dapat dengan mudah memilih dan menentukan implementasi vendor tertentu yang diinginkan di perangkat mereka. Produsen bahkan dapat membuat APEX vendor baru jika tidak ada APEX yang disediakan yang sesuai dengan kebutuhan mereka, atau mereka memiliki perangkat keras khusus baru.

Misalnya, OEM dapat memilih untuk mengomposisi perangkat mereka dengan APEX implementasi wifi AOSP, APEX implementasi bluetooth SoC, dan APEX implementasi telepon OEM kustom.

Tanpa APEX vendor, implementasi dengan begitu banyak dependensi di antara komponen vendor memerlukan koordinasi dan pelacakan yang cermat. Dengan menggabungkan semua (termasuk file konfigurasi dan pustaka tambahan) di APEX dengan antarmuka yang jelas pada setiap titik komunikasi lintas fitur, maka komponen yang berbeda menjadi dapat dipertukarkan.

Iterasi developer

APEX vendor membantu developer melakukan iterasi lebih cepat saat mengembangkan modul vendor dengan memaketkan seluruh implementasi fitur, seperti HAL wifi, di dalam vendor APEX. Developer kemudian dapat mem-build dan mendorong APEX vendor secara terpisah untuk menguji perubahan, bukan mem-build ulang seluruh image vendor.

Hal ini menyederhanakan dan mempercepat siklus iterasi developer untuk developer yang terutama bekerja di satu area fitur dan ingin melakukan iterasi pada fitur itu area tersebut.

Penggabungan alami area fitur ke dalam APEX juga menyederhanakan proses mem-build, mendorong, dan menguji perubahan untuk area fitur tersebut. Misalnya, menginstal ulang APEX akan otomatis mengupdate library atau file konfigurasi yang dipaketkan APEX.

Memaketkan area fitur ke dalam APEX juga menyederhanakan proses debug atau pengembalian jika perilaku perangkat yang buruk diamati. Misalnya, jika telepon berfungsi dengan buruk pada versi baru, pengembang bisa mencoba menginstal versi telepon lama implementasi APEX di perangkat (tanpa perlu mem-flash build penuh) dan melihat apakah perilaku yang baik dipulihkan.

Contoh alur kerja:

# Build the entire device and flash. OR, obtain an already-flashed device.
source build/envsetup.sh && lunch oem_device-userdebug
m
fastboot flashall -w

# Test the device.
... testing ...

# Check previous behavior using a vendor APEX from one week ago, downloaded from
# your continuous integration build.
... download command ...
adb install <path to downloaded APEX>
adb reboot
... testing ...

# Edit and rebuild just the APEX to change and test behavior.
... edit APEX source contents ...
m <apex module name>
adb install out/<path to built APEX>
adb reboot
... testing ...

Contoh

Dasar-dasar

Lihat halaman Format File APEX utama untuk mengetahui informasi APEX umum, termasuk persyaratan perangkat, detail format file, dan langkah-langkah penginstalan.

Di Android.bp, menetapkan properti vendor: true akan membuat modul APEX menjadi APEX vendor.

apex {
  ..
  vendor: true,
  ..
}

Biner dan library bersama

APEX menyertakan dependensi transitif di dalam payload APEX kecuali jika memiliki antarmuka yang stabil.

Antarmuka native yang stabil untuk dependensi APEX vendor menyertakan cc_library dengan stubs dan LLNDK. Dependensi ini dikecualikan dari paket, dan dependensi dicatat dalam manifes APEX. Manifesnya adalah diproses oleh linkerconfig sehingga dependensi native eksternal yang tersedia saat runtime.

Dalam cuplikan berikut, APEX berisi biner (my_service) dan atribut dependensi non-stabil (file *.so).

apex {
  ..
  vendor: true,
  binaries: ["my_service"],
  ..
}

Dalam cuplikan berikut, APEX berisi library bersama my_standalone_libdan semua dependensinya yang tidak stabil (seperti yang dijelaskan di atas).

apex {
  ..
  vendor: true,
  native_shared_libs: ["my_standalone_lib"],
  ..
}

Membuat APEX lebih kecil

APEX mungkin menjadi lebih besar karena memaketkan dependensi yang tidak stabil. Sebaiknya gunakan penautan statis. Library umum seperti libc++.so dan libbase.so dapat ditautkan secara statis ke biner HAL. Membuat dependensi untuk menyediakan antarmuka pengguna dapat menjadi pilihan lain. Dependensi tidak akan digabungkan dalam APEX.

Implementasi HAL

Untuk mendefinisikan implementasi HAL, sediakan biner dan pustaka yang sesuai di dalam APEX vendor yang mirip dengan contoh berikut:

Untuk mengenkapsulasi implementasi HAL sepenuhnya, APEX juga harus menentukan fragmen VINTF dan skrip init yang relevan.

Fragmen VINTF

Fragmen VINTF dapat ditayangkan dari APEX vendor saat fragmen berada di etc/vintf APEX.

Gunakan properti prebuilts untuk menyematkan fragmen VINTF di APEX.

apex {
  ..
  vendor: true,
  prebuilts: ["fragment.xml"],
  ..
}

prebuilt_etc {
  name: "fragment.xml",
  src: "fragment.xml",
  sub_dir: "vintf",
}

API Kueri

Saat fragmen VINTF ditambahkan ke APEX, gunakan libbinder_ndk API untuk mendapatkan pemetaan antarmuka HAL dan nama APEX.

  • AServiceManager_isUpdatableViaApex("com.android.foo.IFoo/default"). true jika instance HAL didefinisikan dalam APEX.
  • AServiceManager_getUpdatableApexName("com.android.foo.IFoo/default", ...) : mendapatkan nama APEX yang menentukan instance HAL.
  • AServiceManager_openDeclaredPassthroughHal("mapper", "instance", ...) : gunakan ini untuk membuka HAL passthrough.

Skrip init

APEX dapat menyertakan skrip init dengan dua cara: (A) file teks bawaan dalam payload APEX, atau (B) skrip init reguler di /vendor/etc. Anda dapat menetapkan keduanya untuk APEX yang sama.

Skrip init di APEX:

prebuilt_etc {
  name: "myinit.rc",
  src: "myinit.rc"
}

apex {
  ..
  vendor: true,
  prebuilts: ["myinit.rc"],
  ..
}

Skrip init di APEX vendor dapat memiliki definisi service dan perintah on <property or event>.

Pastikan definisi service mengarah ke biner di APEX yang sama. Misalnya, com.android.foo APEX dapat menentukan layanan bernama foo-service.

on foo-service /apex/com.android.foo/bin/foo
  ...

Berhati-hatilah saat menggunakan perintah on. Karena skrip init di APEX diurai dan dieksekusi setelah APEX diaktifkan, beberapa peristiwa atau properti tidak dapat digunakan. Gunakan apex.all.ready=true untuk mengaktifkan tindakan sedini mungkin. APEX Bootstrap dapat menggunakan on init, tetapi tidak on early-init.

Firmware

Contoh:

Sematkan firmware di APEX vendor dengan jenis modul prebuilt_firmware, sebagai mengikuti.

prebuilt_firmware {
  name: "my.bin",
  src: "path_to_prebuilt_firmware",
  vendor: true,
}

apex {
  ..
  vendor: true,
  prebuilts: ["my.bin"],  // installed inside APEX as /etc/firmware/my.bin
  ..
}

Modul prebuilt_firmware diinstal di <apex name>/etc/firmware APEX. ueventd memindai /apex/*/etc/firmware direktori untuk menemukan modul {i>firmware<i}.

file_contexts APEX harus memberi label pada setiap entri payload firmware dengan benar untuk memastikan bahwa file tersebut dapat diakses oleh ueventd saat runtime; biasanya, label vendor_file sudah cukup. Contoh:

(/.*)? u:object_r:vendor_file:s0

Modul kernel

Sematkan modul kernel dalam APEX vendor sebagai modul bawaan, sebagai berikut.

prebuilt_etc {
  name: "my.ko",
  src: "my.ko",
  vendor: true,
  sub_dir: "modules"
}

apex {
  ..
  vendor: true,
  prebuilts: ["my.ko"],  // installed inside APEX as /etc/modules/my.ko
  ..
}

file_contexts APEX harus memberi label entri payload modul kernel dengan benar. Contoh:

/etc/modules(/.*)? u:object_r:vendor_kernel_modules:s0

Modul kernel harus diinstal secara eksplisit. Contoh skrip init berikut di partisi vendor menunjukkan penginstalan melalui insmod:

my_init.rc:

on early-boot
  insmod /apex/myapex/etc/modules/my.ko
  ..

Overlay resource runtime

Contoh:

Menyematkan overlay resource runtime di APEX vendor menggunakan properti rros.

runtime_resource_overlay {
    name: "my_rro",
    soc_specific: true,
}


apex {
  ..
  vendor: true,
  rros: ["my_rro"],  // installed inside APEX as /overlay/my_rro.apk
  ..
}

File konfigurasi lainnya

APEX vendor mendukung berbagai file konfigurasi lainnya yang biasanya ditemukan di vendor partisi sebagai bawaan di dalam APEX vendor, dan banyak lagi yang ditambahkan.

Contoh:

APEX Vendor Bootstrap

Beberapa layanan HAL seperti keymint harus tersedia sebelum APEX diaktifkan. HAL tersebut biasanya menetapkan early_hal dalam definisi layanannya dalam skrip init. Contoh lainnya adalah class animation yang biasanya dimulai lebih awal daripada peristiwa post-fs-data. Ketika layanan HAL dini dikemas dalam APEX vendor, buat apex "vendorBootstrap": true di APEX-nya Manifes agar dapat diaktifkan lebih awal. Perhatikan bahwa APEX bootstrap dapat diaktifkan hanya dari lokasi bawaan seperti /vendor/apex, bukan dari /data/apex.

Properti sistem

Ini adalah properti sistem yang dibaca framework untuk mendukung vendor APEX:

  • input_device.config_file.apex=<apex name> - jika ditetapkan, inputnya file konfigurasi (*.idc, *.kl, dan *.kcm) ditelusuri dari /etc/usr dari APEX.
  • ro.vulkan.apex=<apex name> - jika ditetapkan, driver Vulkan akan dimuat dari APEX. Karena driver Vulkan digunakan oleh HAL awal, buat APEX Bootstrap APEX dan mengonfigurasi namespace penaut tersebut terlihat.

Tetapkan properti sistem di skrip init menggunakan perintah setprop.

Fitur pengembangan tambahan

Pemilihan APEX saat booting

Contoh:

Developer juga dapat menginstal beberapa versi APEX vendor yang memiliki nama dan kunci APEX yang sama, lalu memilih versi mana yang diaktifkan selama setiap proses booting menggunakan sysprop persisten. Untuk kasus penggunaan developer tertentu, hal ini mungkin lebih sederhana daripada menginstal salinan APEX baru menggunakan adb install.

Contoh kasus penggunaan:

  • Instal 3 versi APEX vendor HAL wifi: Tim QA dapat menjalankan pengujian manual atau otomatis menggunakan satu versi, lalu memulai ulang ke versi lain dan menjalankan ulang pengujian, lalu membandingkan hasil akhir.
  • Instal 2 versi APEX vendor HAL kamera APEX, saat ini dan eksperimental: Pengguna versi dogfood dapat menggunakan versi eksperimental tanpa mengunduh dan menginstal file tambahan, sehingga mereka dapat menukarnya kembali dengan mudah.

Selama booting, apexd mencari sysprops yang mengikuti format tertentu untuk mengaktifkan versi APEX yang tepat.

Format yang diharapkan untuk kunci properti adalah:

  • Bootconfig
    • Digunakan untuk menetapkan nilai default, dalam BoardConfig.mk.
    • androidboot.vendor.apex.<apex name>
  • Sysprop persisten
    • Digunakan untuk mengubah nilai default, yang ditetapkan pada perangkat yang sudah di-booting.
    • Mengganti nilai bootconfig jika ada.
    • persist.vendor.apex.<apex name>

Nilai properti harus berupa nama file APEX yang harus diaktifkan.

// Default version.
apex {
  name: "com.oem.camera.hal.my_apex_default",
  vendor: true,
  ..
}

// Non-default version.
apex {
  name: "com.oem.camera.hal.my_apex_experimental",
  vendor: true,
  ..
}

Versi default juga harus dikonfigurasi menggunakan {i>bootconfig<i} di BoardConfig.mk:

# Example for APEX "com.oem.camera.hal" with the default above:
BOARD_BOOTCONFIG += \
    androidboot.vendor.apex.com.oem.camera.hal=com.oem.camera.hal.my_apex_default

Setelah perangkat di-booting, ubah versi yang diaktifkan dengan menetapkan sysprop persisten:

$ adb root;
$ adb shell setprop \
    persist.vendor.apex.com.oem.camera.hal \
    com.oem.camera.hal.my_apex_experimental;
$ adb reboot;

Jika perangkat mendukung update bootconfig setelah melakukan flash (seperti melalui perintah fastboot oem), Anda dapat mengubah properti bootconfig untuk APEX juga mengubah versi yang diaktifkan saat {i>booting<i}.

Untuk perangkat referensi virtual berdasarkan Cuttlefish, Anda dapat menggunakan perintah --extra_bootconfig_args untuk menetapkan properti bootconfig secara langsung saat peluncuran. Contoh:

launch_cvd --noresume \
  --extra_bootconfig_args "androidboot.vendor.apex.com.oem.camera.hal:=com.oem.camera.hal.my_apex_experimental";