Format penampung Android Pony EXpress (APEX) diperkenalkan di Android 10 dan digunakan dalam alur penginstalan untuk modul sistem level bawah. Format ini memfasilitasi update komponen sistem yang tidak sesuai dengan model aplikasi Android standar. Beberapa contoh komponen adalah layanan dan library native, lapisan abstraksi hardware (HAL), runtime (ART), dan library class.
Istilah "APEX" juga dapat merujuk ke file APEX.
Latar belakang
Meskipun Android mendukung update modul yang sesuai dalam model aplikasi standar (misalnya, layanan, aktivitas) melalui aplikasi penginstal paket (seperti aplikasi Google Play Store), penggunaan model serupa untuk komponen OS tingkat bawah memiliki kekurangan berikut:
- Modul berbasis APK tidak dapat digunakan di awal urutan booting. Pengelola paket adalah repositori pusat informasi tentang aplikasi dan hanya dapat dimulai dari pengelola aktivitas, yang siap pada tahap selanjutnya dari prosedur booting.
- Format APK (terutama manifes) dirancang untuk aplikasi Android dan modul sistem tidak selalu cocok.
Desain
Bagian ini menjelaskan desain tingkat tinggi format file APEX dan pengelola APEX, yang merupakan layanan yang mengelola file APEX.
Untuk mengetahui informasi selengkapnya tentang alasan desain ini dipilih untuk APEX, lihat Alternatif yang dipertimbangkan saat mengembangkan APEX.
Format APEX
Ini adalah format file APEX.
Gambar 1. Format file APEX
Di tingkat teratas, file APEX adalah file zip yang menyimpan file tanpa dikompresi dan terletak di batas 4 KB.
Empat file dalam file APEX adalah:
apex_manifest.json
AndroidManifest.xml
apex_payload.img
apex_pubkey
File apex_manifest.json
berisi nama dan versi paket, yang mengidentifikasi file APEX. Ini adalah
ApexManifest
buffer protokol dalam format JSON.
File AndroidManifest.xml
memungkinkan file APEX menggunakan alat dan infrastruktur terkait APK seperti ADB, PackageManager, dan aplikasi penginstal paket (seperti Play Store). Misalnya, file APEX dapat menggunakan alat yang ada seperti aapt
untuk memeriksa metadata dasar dari file. File berisi nama paket dan
informasi versi. Informasi ini umumnya juga tersedia di
apex_manifest.json
.
apex_manifest.json
direkomendasikan daripada AndroidManifest.xml
untuk kode dan
sistem baru yang menangani APEX. AndroidManifest.xml
mungkin berisi informasi penargetan tambahan yang dapat digunakan oleh alat publikasi aplikasi yang ada.
apex_payload.img
adalah image sistem file ext4 yang didukung oleh dm-verity. Image
dipasang saat runtime melalui perangkat loopback. Secara khusus, pohon hash dan
blok metadata dibuat menggunakan library libavb
. Payload sistem file
tidak diuraikan (karena gambar harus dapat di-mount di tempat). File reguler disertakan di dalam file apex_payload.img
.
apex_pubkey
adalah kunci publik yang digunakan untuk menandatangani image sistem file. Saat runtime,
kunci ini memastikan bahwa APEX yang didownload ditandatangani dengan entity yang sama
yang menandatangani APEX yang sama di partisi bawaan.
Panduan penamaan APEX
Untuk membantu mencegah konflik penamaan antara APEX baru seiring perkembangan platform, gunakan panduan penamaan berikut:
com.android.*
- Dicadangkan untuk APEX AOSP. Tidak unik untuk perusahaan atau perangkat mana pun.
com.<companyname>.*
- Disediakan untuk perusahaan. Berpotensi digunakan oleh beberapa perangkat dari perusahaan tersebut.
com.<companyname>.<devicename>.*
- Dicadangkan untuk APEX unik pada perangkat tertentu (atau subset perangkat).
Pengelola APEX
Pengelola APEX (atau apexd
) adalah proses native mandiri yang bertanggung jawab untuk memverifikasi, menginstal, dan meng-uninstal file APEX. Proses ini diluncurkan dan siap di awal urutan booting. File APEX biasanya sudah diinstal sebelumnya di perangkat di bagian /system/apex
. Pengelola APEX secara default menggunakan paket ini jika tidak ada update yang tersedia.
Urutan update APEX menggunakan class PackageManager dan sebagai berikut.
- File APEX didownload melalui aplikasi penginstal paket, ADB, atau sumber lainnya.
- Pengelola paket memulai prosedur penginstalan. Setelah mengenali bahwa file adalah APEX, pengelola paket mentransfer kontrol ke pengelola APEX.
- Pengelola APEX memverifikasi file APEX.
- Jika file APEX diverifikasi, database internal pengelola APEX akan diperbarui untuk menunjukkan bahwa file APEX diaktifkan saat booting berikutnya.
- Pemohon penginstalan menerima siaran setelah verifikasi paket berhasil.
- Untuk melanjutkan penginstalan, sistem harus dimulai ulang.
Saat booting berikutnya, pengelola APEX dimulai, membaca database internal, dan melakukan hal berikut untuk setiap file APEX yang tercantum:
- Memverifikasi file APEX.
- Membuat perangkat loopback dari file APEX.
- Membuat perangkat blok pemeta perangkat di atas perangkat loopback.
- Memasang perangkat blok pemeta perangkat ke jalur unik (misalnya,
/apex/name@ver
).
Setelah semua file APEX yang tercantum dalam database internal di-mount, pengelola APEX menyediakan layanan binder bagi komponen sistem lain untuk mengkueri informasi tentang file APEX yang diinstal. Misalnya, komponen sistem lain dapat mengkueri daftar file APEX yang diinstal di perangkat atau mengkueri jalur persis tempat APEX tertentu di-mount, sehingga file dapat diakses.
File APEX adalah file APK
File APEX adalah file APK yang valid karena merupakan arsip zip yang ditandatangani (menggunakan skema tanda tangan APK) yang berisi file AndroidManifest.xml
. Hal ini memungkinkan file APEX menggunakan infrastruktur untuk file APK, seperti aplikasi penginstal paket, utilitas penandatanganan, dan pengelola paket.
File AndroidManifest.xml
di dalam file APEX bersifat minimal, terdiri dari
paket name
, versionCode
, dan targetSdkVersion
, minSdkVersion
,
serta maxSdkVersion
opsional untuk penargetan yang lebih terperinci. Informasi ini memungkinkan file APEX dikirimkan melalui saluran yang ada seperti aplikasi penginstal paket dan ADB.
Jenis file yang didukung
Format APEX mendukung jenis file berikut:
- Library bersama native
- File yang dapat dieksekusi native
- File JAR
- File data
- File konfigurasi
Hal ini tidak berarti APEX dapat mengupdate semua jenis file ini. Apakah jenis file dapat diperbarui bergantung pada platform dan seberapa stabil definisi antarmuka untuk jenis file tersebut.
Opsi penandatanganan
File APEX ditandatangani dengan dua cara. Pertama, file apex_payload.img
(khususnya,
deskriptor vbmeta yang ditambahkan ke apex_payload.img
) ditandatangani dengan kunci.
Kemudian, seluruh APEX ditandatangani menggunakan
APK signature scheme v3. Dua kunci berbeda digunakan
dalam proses ini.
Di sisi perangkat, kunci publik yang sesuai dengan kunci pribadi yang digunakan untuk menandatangani deskriptor vbmeta diinstal. Pengelola APEX menggunakan kunci publik untuk memverifikasi APEX yang diminta untuk diinstal. Setiap APEX harus ditandatangani dengan kunci yang berbeda dan diterapkan pada waktu build dan runtime.
APEX di partisi bawaan
File APEX dapat berada di partisi bawaan seperti /system
. Partisi
sudah melalui dm-verity, sehingga file APEX dipasang langsung
melalui perangkat loopback.
Jika APEX ada di partisi bawaan, APEX dapat diupdate dengan
menyediakan paket APEX dengan nama paket yang sama dan kode versi yang lebih besar dari atau sama dengan. APEX baru disimpan di /data
dan, mirip dengan APK, versi yang baru diinstal akan menggantikan versi yang sudah ada di partisi bawaan. Namun, tidak seperti APK, APEX versi yang baru diinstal hanya diaktifkan setelah perangkat dimulai ulang.
Persyaratan kernel
Untuk mendukung modul utama APEX di perangkat Android, fitur kernel Linux berikut diperlukan: driver loopback dan dm-verity. Driver loopback memasang image sistem file dalam modul APEX dan dm-verity memverifikasi modul APEX.
Performa driver loopback dan dm-verity penting untuk mencapai performa sistem yang baik saat menggunakan modul APEX.
Versi kernel yang didukung
Modul utama APEX didukung di perangkat yang menggunakan kernel versi 4.4 atau yang lebih tinggi. Perangkat baru yang diluncurkan dengan Android 10 atau yang lebih tinggi harus menggunakan kernel versi 4.9 atau yang lebih tinggi untuk mendukung modul APEX.
Patch kernel yang diperlukan
Patch kernel yang diperlukan untuk mendukung modul APEX disertakan dalam struktur umum Android. Untuk mendapatkan patch guna mendukung APEX, gunakan versi terbaru dari pohon umum Android.
Kernel versi 4.4
Versi ini hanya didukung untuk perangkat yang diupgrade dari Android 9 ke
Android 10 dan ingin mendukung modul APEX. Untuk mendapatkan patch yang diperlukan, sangat disarankan untuk melakukan penggabungan ke bawah dari cabang android-4.4
. Berikut adalah daftar patch individual yang diperlukan
untuk kernel versi 4.4.
- UPSTREAM: loop: add ioctl for changing logical block size (4.4)
- BACKPORT: block/loop: set hw_sectors (4.4)
- UPSTREAM: loop: Add LOOP_SET_BLOCK_SIZE in compat ioctl (4.4)
- ANDROID: mnt: Fix next_descendent (4.4)
- ANDROID: mnt: pemasangan ulang harus diteruskan ke turunan dari turunan (4.4)
- ANDROID: mnt: Propagasi pemasangan ulang dengan benar (4.4)
- Kembalikan "ANDROID: dm verity: add minimum prefetch size" (4.4)
- UPSTREAM: loop: drop caches if offset or block_size are changed (4.4)
Versi kernel 4.9/4.14/4.19
Untuk mendapatkan patch yang diperlukan untuk kernel versi 4.9/4.14/4.19, lakukan down-merge dari
cabang android-common
.
Opsi konfigurasi kernel yang diperlukan
Daftar berikut menunjukkan persyaratan konfigurasi dasar untuk mendukung modul APEX yang diperkenalkan di Android 10. Item dengan tanda bintang (*) adalah persyaratan yang sudah ada dari Android 9 dan yang lebih rendah.
(*) CONFIG_AIO=Y # AIO support (for direct I/O on loop devices)
CONFIG_BLK_DEV_LOOP=Y # for loop device support
CONFIG_BLK_DEV_LOOP_MIN_COUNT=16 # pre-create 16 loop devices
(*) CONFIG_CRYPTO_SHA1=Y # SHA1 hash for DM-verity
(*) CONFIG_CRYPTO_SHA256=Y # SHA256 hash for DM-verity
CONFIG_DM_VERITY=Y # DM-verity support
Persyaratan parameter command line kernel
Untuk mendukung APEX, pastikan parameter command line kernel memenuhi persyaratan berikut:
loop.max_loop
TIDAK boleh ditetapkanloop.max_part
harus <= 8
Membangun APEX
Bagian ini menjelaskan cara membuat APEX menggunakan sistem build Android.
Berikut adalah contoh Android.bp
untuk APEX bernama apex.test
.
apex {
name: "apex.test",
manifest: "apex_manifest.json",
file_contexts: "file_contexts",
// libc.so and libcutils.so are included in the apex
native_shared_libs: ["libc", "libcutils"],
binaries: ["vold"],
java_libs: ["core-all"],
prebuilts: ["my_prebuilt"],
compile_multilib: "both",
key: "apex.test.key",
certificate: "platform",
}
Contoh apex_manifest.json
:
{
"name": "com.android.example.apex",
"version": 1
}
Contoh file_contexts
:
(/.*)? u:object_r:system_file:s0
/sub(/.*)? u:object_r:sub_file:s0
/sub/file3 u:object_r:file3_file:s0
Jenis dan lokasi file di APEX
Jenis file | Lokasi di APEX |
---|---|
Galeri foto bersama | /lib dan /lib64 (/lib/arm untuk
ARM yang diterjemahkan di x86) |
Dapat dieksekusi | /bin |
Library Java | /javalib |
Bawaan | /etc |
Dependensi transitif
File APEX secara otomatis menyertakan dependensi transitif dari library bersama atau file yang dapat dieksekusi native. Misalnya, jika libFoo
bergantung pada libBar
, kedua pustaka akan disertakan jika hanya libFoo
yang tercantum di properti native_shared_libs
.
Menangani beberapa ABI
Instal properti native_shared_libs
untuk antarmuka biner aplikasi (ABI) primer dan sekunder perangkat. Jika APEX menargetkan perangkat dengan satu ABI (yaitu, hanya 32 bit atau hanya 64 bit), hanya library dengan ABI yang sesuai yang diinstal.
Instal properti binaries
hanya untuk ABI utama perangkat seperti yang dijelaskan di bawah:
- Jika perangkat hanya 32 bit, hanya varian biner 32 bit yang diinstal.
- Jika perangkat hanya 64 bit, hanya varian biner 64-bit yang diinstal.
Untuk menambahkan kontrol terperinci atas ABI library dan biner native,
gunakan
properti
multilib.[first|lib32|lib64|prefer32|both].[native_shared_libs|binaries]
.
first
: Cocok dengan ABI utama perangkat. Ini adalah default untuk biner.lib32
: Cocok dengan ABI 32-bit perangkat, jika didukung.lib64
: Cocok dengan ABI 64-bit perangkat yang didukung.prefer32
: Cocok dengan ABI 32-bit perangkat, jika didukung. Jika ABI 32-bit tidak didukung, ABI tersebut cocok dengan ABI 64-bit.both
: Mencocokkan kedua ABI. Ini adalah default untuknative_shared_libraries
.
Properti java
, libraries
, dan prebuilts
tidak bergantung pada ABI.
Contoh ini adalah untuk perangkat yang mendukung 32/64 dan tidak lebih memilih 32:
apex {
// other properties are omitted
native_shared_libs: ["libFoo"], // installed for 32 and 64
binaries: ["exec1"], // installed for 64, but not for 32
multilib: {
first: {
native_shared_libs: ["libBar"], // installed for 64, but not for 32
binaries: ["exec2"], // same as binaries without multilib.first
},
both: {
native_shared_libs: ["libBaz"], // same as native_shared_libs without multilib
binaries: ["exec3"], // installed for 32 and 64
},
prefer32: {
native_shared_libs: ["libX"], // installed for 32, but not for 64
},
lib64: {
native_shared_libs: ["libY"], // installed for 64, but not for 32
},
},
}
Penandatanganan vbmeta
Menandatangani setiap APEX dengan kunci yang berbeda. Saat kunci baru diperlukan, buat pasangan kunci publik-pribadi dan buat modul apex_key
. Gunakan properti key
untuk
menandatangani APEX menggunakan kunci. Kunci publik otomatis disertakan dalam
APEX dengan nama avb_pubkey
.
# create an rsa key pairopenssl genrsa -out foo.pem 4096
# extract the public key from the key pairavbtool extract_public_key --key foo.pem --output foo.avbpubkey
# in Android.bpapex_key { name: "apex.test.key", public_key: "foo.avbpubkey", private_key: "foo.pem", }
Dalam contoh di atas, nama kunci publik (foo
) menjadi ID
kunci. ID kunci yang digunakan untuk menandatangani APEX ditulis dalam APEX. Saat runtime,
apexd
memverifikasi APEX menggunakan kunci publik dengan ID yang sama di perangkat.
Penandatanganan APEX
Tandatangani APEX dengan cara yang sama seperti Anda menandatangani APK. Tandatangani APEX dua kali; sekali untuk
sistem file mini (file apex_payload.img
) dan sekali untuk seluruh file.
Untuk menandatangani APEX di tingkat file, tetapkan properti certificate
dengan salah satu dari tiga cara berikut:
- Tidak disetel: Jika tidak ada nilai yang disetel, APEX ditandatangani dengan sertifikat yang berada
di
PRODUCT_DEFAULT_DEV_CERTIFICATE
. Jika tidak ada tanda yang ditetapkan, jalur defaultnya adalahbuild/target/product/security/testkey
. <name>
: APEX ditandatangani dengan sertifikat<name>
di direktori yang sama denganPRODUCT_DEFAULT_DEV_CERTIFICATE
.:<name>
: APEX ditandatangani dengan sertifikat yang ditentukan oleh modul Soong bernama<name>
. Modul sertifikat dapat ditentukan sebagai berikut.
android_app_certificate {
name: "my_key_name",
certificate: "dir/cert",
// this will use dir/cert.x509.pem (the cert) and dir/cert.pk8 (the private key)
}
Menginstal APEX
Untuk menginstal APEX, gunakan ADB.
adb install apex_file_name
adb reboot
Jika supportsRebootlessUpdate
disetel ke true
di apex_manifest.json
dan APEX yang saat ini diinstal tidak digunakan (misalnya, semua layanan yang ada di dalamnya telah dihentikan), maka APEX baru dapat diinstal tanpa melakukan reboot dengan tanda --force-non-staged
.
adb install --force-non-staged apex_file_name
Menggunakan APEX
Setelah dimulai ulang, APEX dipasang di direktori /apex/<apex_name>@<version>
. Beberapa versi APEX yang sama dapat di-mount secara bersamaan.
Di antara jalur pemasangan, jalur yang sesuai dengan versi terbaru adalah
dipasang dengan bind di /apex/<apex_name>
.
Klien dapat menggunakan jalur yang terpasang untuk membaca atau mengeksekusi file dari APEX.
APEX biasanya digunakan sebagai berikut:
- OEM atau ODM memuat APEX di bawah
/system/apex
saat perangkat dikirim. - File di APEX diakses melalui jalur
/apex/<apex_name>/
. - Saat versi APEX yang diupdate diinstal di
/data/apex
, jalur menunjuk ke APEX baru setelah melakukan reboot.
Memperbarui layanan dengan APEX
Untuk mengupdate layanan menggunakan APEX:
Menandai layanan di partisi sistem sebagai dapat diupdate. Tambahkan opsi
updatable
ke definisi layanan./system/etc/init/myservice.rc: service myservice /system/bin/myservice class core user system ... updatable
Buat file
.rc
baru untuk layanan yang diupdate. Gunakan opsioverride
untuk mendefinisikan ulang layanan yang ada./apex/my.apex/etc/init.rc: service myservice /apex/my.apex/bin/myservice class core user system ... override
Definisi layanan hanya dapat ditentukan dalam file .rc
APEX. Pemicu
tindakan tidak didukung di APEX.
Jika layanan yang ditandai sebagai dapat diupdate dimulai sebelum APEX diaktifkan, maka mulai akan tertunda hingga aktivasi APEX selesai.
Mengonfigurasi sistem untuk mendukung update APEX
Tetapkan properti sistem berikut ke true
untuk mendukung update file APEX.
<device.mk>:
PRODUCT_PROPERTY_OVERRIDES += ro.apex.updatable=true
BoardConfig.mk:
TARGET_FLATTEN_APEX := false
atau hanya
<device.mk>:
$(call inherit-product, $(SRC_TARGET_DIR)/product/updatable_apex.mk)
APEX yang disederhanakan
Untuk perangkat lama, terkadang tidak mungkin atau tidak layak untuk mengupdate kernel lama agar mendukung APEX sepenuhnya. Misalnya, kernel mungkin telah dibangun
tanpa CONFIG_BLK_DEV_LOOP=Y
, yang sangat penting untuk memasang image sistem file
di dalam APEX.
APEX yang diratakan adalah APEX yang dibuat khusus yang dapat diaktifkan di perangkat dengan kernel lama. File dalam APEX yang diratakan diinstal langsung ke direktori
di bawah partisi bawaan. Misalnya, lib/libFoo.so
di APEX yang diratakan
my.apex
diinstal ke /system/apex/my.apex/lib/libFoo.so
.
Mengaktifkan APEX yang diratakan tidak melibatkan perangkat loop. Seluruh
direktori /system/apex/my.apex
dipasang langsung ke /apex/name@ver
.
APEX yang diratakan tidak dapat diupdate dengan mendownload versi APEX yang diupdate dari jaringan karena APEX yang didownload tidak dapat diratakan. APEX yang diratakan hanya dapat diupdate melalui OTA reguler.
APEX yang diratakan adalah konfigurasi default. Artinya, semua APEX diratakan secara default, kecuali jika Anda secara eksplisit mengonfigurasi perangkat untuk mem-build APEX yang tidak diratakan guna mendukung update APEX (seperti yang dijelaskan di atas).
Mencampur APEX yang diratakan dan tidak diratakan dalam perangkat TIDAK
didukung. APEX di perangkat harus semuanya tidak diratakan atau semuanya diratakan.
Hal ini sangat penting saat mengirimkan APEX bawaan yang telah ditandatangani sebelumnya untuk project seperti Mainline. APEX yang tidak ditandatangani sebelumnya (yaitu, dibangun dari
sumber) juga tidak boleh diratakan dan harus ditandatangani dengan kunci yang tepat. Perangkat
harus diwarisi dari updatable_apex.mk
seperti yang dijelaskan dalam
Memperbarui layanan dengan APEX.
APEX terkompresi
Android 12 dan yang lebih baru memiliki kompresi APEX untuk mengurangi dampak penyimpanan paket APEX yang dapat diupdate. Setelah update ke APEX diinstal, meskipun versi pra-instalnya tidak digunakan lagi, APEX tersebut tetap menempati ruang penyimpanan yang sama. Ruang yang ditempati tersebut tetap tidak tersedia.
Kompresi APEX meminimalkan dampak penyimpanan ini dengan menggunakan serangkaian file APEX yang sangat dikompresi pada partisi hanya baca (seperti partisi /system
). Android
12 dan yang lebih baru menggunakan algoritma kompresi zip DEFLATE.
Kompresi tidak memberikan pengoptimalan untuk hal berikut:
Mem-bootstrap APEX yang harus di-mount sangat awal dalam urutan booting.
APEX yang tidak dapat diupdate. Kompresi hanya bermanfaat jika versi APEX yang diperbarui diinstal di partisi
/data
. Daftar lengkap APEX yang dapat diupdate tersedia di halaman Komponen Sistem Modular.APEX library bersama dinamis. Karena
apexd
selalu mengaktifkan kedua versi APEX tersebut (yang sudah diinstal dan diupgrade), mengompresinya tidak akan menambah nilai.
Format file APEX terkompresi
Ini adalah format file APEX terkompresi.
Gambar 2. Format file APEX terkompresi
Di tingkat teratas, file APEX terkompresi adalah file zip yang berisi file apex asli dalam bentuk yang dideflasi dengan tingkat kompresi 9, dan dengan file lain yang disimpan tanpa dikompresi.
Empat file membentuk file APEX:
original_apex
: di-deflate dengan tingkat kompresi 9 Ini adalah file APEX asli yang tidak dikompresi.apex_manifest.pb
: hanya disimpanAndroidManifest.xml
: hanya disimpanapex_pubkey
: hanya disimpan
File apex_manifest.pb
, AndroidManifest.xml
, dan apex_pubkey
adalah
salinan dari file terkait di original_apex
.
Membangun APEX terkompresi
APEX yang dikompresi dapat dibangun menggunakan alat apex_compression_tool.py
yang terletak di
system/apex/tools
.
Beberapa parameter terkait kompresi APEX tersedia di sistem build.
Di Android.bp
, apakah file APEX dapat dikompresi atau tidak dikontrol oleh
properti compressible
:
apex {
name: "apex.test",
manifest: "apex_manifest.json",
file_contexts: "file_contexts",
compressible: true,
}
Flag produk PRODUCT_COMPRESSED_APEX
mengontrol apakah image sistem yang dibangun dari sumber harus berisi file APEX terkompresi.
Untuk eksperimen lokal, Anda dapat memaksa build mengompresi APEX dengan menyetel
OVERRIDE_PRODUCT_COMPRESSED_APEX=
ke true
.
File APEX terkompresi yang dihasilkan oleh sistem build memiliki ekstensi .capex
.
Ekstensi ini mempermudah pembedaan antara versi file APEX yang dikompresi dan tidak dikompresi.
Algoritma kompresi yang didukung
Android 12 hanya mendukung kompresi deflate-zip.
Mengaktifkan file APEX yang dikompresi selama booting
Sebelum APEX yang dikompresi dapat diaktifkan, file original_apex
di dalamnya
didekompresi ke direktori /data/apex/decompressed
. File APEX yang didekompresi
dihubungkan secara permanen ke direktori /data/apex/active
.
Perhatikan contoh berikut sebagai ilustrasi proses yang dijelaskan di atas.
Pertimbangkan /system/apex/com.android.foo.capex
sebagai APEX terkompresi yang diaktifkan, dengan versionCode 37.
- File
original_apex
di dalam/system/apex/com.android.foo.capex
akan didekompresi ke/data/apex/decompressed/com.android.foo@37.apex
. restorecon /data/apex/decompressed/com.android.foo@37.apex
dilakukan untuk memverifikasi bahwa aplikasi memiliki label SELinux yang benar.- Pemeriksaan verifikasi dilakukan pada
/data/apex/decompressed/com.android.foo@37.apex
untuk memastikan validitasnya:apexd
memeriksa kunci publik yang disertakan dalam/data/apex/decompressed/com.android.foo@37.apex
untuk memverifikasi bahwa kunci tersebut sama dengan kunci yang disertakan dalam/system/apex/com.android.foo.capex
. - File
/data/apex/decompressed/com.android.foo@37.apex
ditautkan secara permanen ke direktori/data/apex/active/com.android.foo@37.apex
. - Logika aktivasi reguler untuk file APEX yang tidak dikompresi dilakukan di
/data/apex/active/com.android.foo@37.apex
.
Interaksi dengan OTA
File APEX yang dikompresi memiliki implikasi pada pengiriman dan penerapan OTA. Karena update OTA mungkin berisi file APEX terkompresi dengan level versi yang lebih tinggi daripada yang aktif di perangkat, sejumlah ruang kosong harus dicadangkan sebelum perangkat di-reboot untuk menerapkan update OTA.
Untuk mendukung sistem OTA, apexd
mengekspos dua API binder ini:
calculateSizeForCompressedApex
- menghitung ukuran yang diperlukan untuk mendekompresi file APEX dalam paket OTA. Hal ini dapat digunakan untuk memverifikasi bahwa perangkat memiliki ruang yang cukup sebelum OTA didownload.reserveSpaceForCompressedApex
- mencadangkan ruang di disk untuk penggunaan di masa mendatang olehapexd
untuk mendekompresi file APEX terkompresi di dalam paket OTA.
Dalam kasus update OTA A/B, apexd
mencoba dekompresi di latar belakang sebagai bagian dari rutin OTA setelah penginstalan. Jika dekompresi gagal,
apexd
akan melakukan dekompresi selama booting yang menerapkan update OTA.
Alternatif yang dipertimbangkan saat mengembangkan APEX
Berikut beberapa opsi yang dipertimbangkan AOSP saat mendesain format file APEX, dan alasan opsi tersebut disertakan atau dikecualikan.
Sistem pengelolaan paket reguler
Distribusi Linux memiliki sistem pengelolaan paket seperti dpkg
dan rpm
,
yang canggih, matang, dan andal. Namun, mereka tidak
diadopsi untuk APEX karena tidak dapat melindungi paket setelah
penginstalan. Verifikasi dilakukan hanya saat paket diinstal.
Penyerang dapat merusak integritas paket yang diinstal tanpa diketahui. Hal ini merupakan regresi untuk Android yang semua komponen sistemnya disimpan dalam sistem file hanya baca yang integritasnya dilindungi oleh dm-verity untuk setiap I/O. Setiap
upaya merusak komponen sistem harus dilarang, atau dapat dideteksi sehingga
perangkat dapat menolak untuk melakukan booting jika disusupi.
dm-crypt untuk integritas
File dalam penampung APEX berasal dari partisi bawaan (misalnya, partisi /system
) yang dilindungi oleh dm-verity, yang melarang modifikasi apa pun pada file meskipun setelah partisi dipasang. Untuk memberikan tingkat keamanan yang sama pada file, semua file dalam APEX disimpan dalam image sistem file yang dipasangkan dengan pohon hash dan deskriptor vbmeta. Tanpa
dm-verity, APEX di partisi /data
rentan terhadap modifikasi yang tidak diinginkan yang dilakukan setelah diverifikasi dan diinstal.
Faktanya, partisi /data
juga dilindungi oleh lapisan enkripsi seperti dm-crypt. Meskipun memberikan tingkat perlindungan tertentu terhadap upaya merusak, tujuan utamanya adalah privasi, bukan integritas. Jika penyerang mendapatkan akses ke partisi
/data
, tidak ada lagi perlindungan, dan hal ini merupakan
regresi dibandingkan dengan setiap komponen sistem yang berada di partisi /data
./system
Pohon hash di dalam file APEX bersama dengan dm-verity memberikan tingkat perlindungan konten yang sama.
Mengalihkan jalur dari /system ke /apex
File komponen sistem yang dikemas dalam APEX dapat diakses melalui jalur baru seperti
/apex/<name>/lib/libfoo.so
. Jika file tersebut merupakan bagian dari partisi /system
, file tersebut dapat diakses melalui jalur seperti /system/lib/libfoo.so
. Klien
file APEX (file APEX lain atau platform) harus menggunakan jalur
baru. Anda mungkin perlu memperbarui kode yang ada sebagai akibat dari perubahan jalur.
Meskipun salah satu cara untuk menghindari perubahan jalur adalah dengan menempatkan konten file di file APEX ke partisi /system
, tim Android memutuskan untuk tidak menempatkan file di partisi /system
karena hal ini dapat memengaruhi performa seiring bertambahnya jumlah file yang ditempatkan (bahkan mungkin ditumpuk satu demi satu).
Opsi lainnya adalah membajak fungsi akses file seperti open
, stat
, dan
readlink
, sehingga jalur yang dimulai dengan /system
dialihkan ke jalur yang
sesuai di /apex
. Tim Android membatalkan opsi ini
karena tidak mungkin mengubah semua fungsi yang menerima jalur.
Misalnya, beberapa aplikasi menautkan Bionic secara statis, yang mengimplementasikan fungsi.
Dalam kasus seperti ini, aplikasi tersebut tidak dialihkan.