Format file APEX

Format container Android Pony EXpress (APEX) diperkenalkan di Android 10 dan digunakan dalam alur instal untuk sistem di tingkat yang lebih rendah modul. Format ini memfasilitasi pembaruan komponen sistem yang tidak sesuai ke dalam model aplikasi Android standar. Beberapa contoh komponen bersifat native layanan dan library, lapisan abstraksi hardware (HAL), waktu proses (ART), dan library class.

Istilah "APEX" juga dapat merujuk ke file APEX.

Latar belakang

Meskipun Android mendukung update modul yang sesuai dengan aplikasi standar (misalnya, layanan, aktivitas) melalui aplikasi penginstal paket (seperti aplikasi Google Play Store), menggunakan model serupa untuk komponen OS tingkat rendah memiliki kelemahan berikut:

  • Modul berbasis APK tidak dapat digunakan di awal urutan booting. Paket adalah repositori pusat informasi tentang aplikasi dan hanya dapat dimulai dari pengelola aktivitas, yang akan siap di tahap selanjutnya prosedur {i>booting<i}.
  • Format APK (terutama manifes) dirancang untuk aplikasi Android dan modul sistem tidak selalu cocok.

Desain

Bagian ini menjelaskan desain tingkat tinggi dari format {i>file<i} APEX dan APEX Manager, yang merupakan layanan yang mengelola file APEX.

Untuk mengetahui informasi selengkapnya tentang mengapa desain untuk APEX ini dipilih, lihat Alternatif yang dipertimbangkan saat mengembangkan APEX.

Format APEX

Ini adalah format file APEX.

Format file APEX

Gambar 1. Format file APEX

Pada tingkat atas, file APEX adalah file {i>zip<i} tempat file disimpan tidak dikompresi dan terletak pada batas 4 KB.

Keempat 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 buffering protokol dalam format JSON.

File AndroidManifest.xml memungkinkan file APEX menggunakan alat terkait APK dan infrastruktur Anda seperti ADB, PackageManager, dan aplikasi penginstal paket (seperti Play Store). Misalnya, file APEX dapat menggunakan alat yang ada seperti aapt untuk memeriksa {i>metadata<i} dasar dari file itu. File berisi nama paket dan informasi versi. Informasi ini umumnya juga tersedia di apex_manifest.json.

apex_manifest.json lebih direkomendasikan daripada AndroidManifest.xml untuk kode baru dan yang berhubungan dengan APEX. AndroidManifest.xml mungkin berisi tambahan informasi penargetan yang dapat digunakan oleh alat publikasi aplikasi yang sudah ada.

apex_payload.img adalah image sistem file ext4 yang didukung oleh dm-verity. Gambar dipasang saat runtime melalui perangkat loopback. Secara khusus, {i>hash tree <i}dan Blok metadata dibuat menggunakan library libavb. Payload sistem file tidak diuraikan (karena gambar harus dapat dipasang di tempat). File biasa adalah 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 entitas yang sama yang menandatangani APEX yang sama di partisi bawaan.

Pedoman penamaan APEX

Untuk membantu mencegah konflik penamaan antara APEX baru saat platform berkembang, gunakan panduan penamaan berikut:

  • com.android.*
    • Dicadangkan untuk APEX AOSP. Tidak unik untuk perusahaan atau perangkat apa pun.
  • com.<companyname>.*
    • Direservasi untuk perusahaan. Kemungkinan digunakan oleh beberapa perangkat dari perusahaan Anda.
  • com.<companyname>.<devicename>.*
    • Dicadangkan untuk APEX yang unik untuk satu perangkat tertentu (atau subset perangkat).

Pengelola APEX

Pengelola APEX (atau apexd) adalah proses native mandiri yang bertanggung jawab untuk memverifikasi, menginstal, dan menghapus instalan file APEX. Proses ini dijalankan dan siap di awal urutan booting. File APEX biasanya sudah diinstal sebelumnya di perangkat di bawah /system/apex. Secara default, pengelola APEX akan menggunakan paket jika tidak ada pembaruan yang tersedia.

Urutan pembaruan APEX menggunakan metode Class PackageManager dan adalah sebagai berikut.

  1. File APEX didownload melalui aplikasi pemasang paket, ADB, atau sumber.
  2. Pengelola paket memulai prosedur instalasi. Setelah menyadari bahwa filenya adalah APEX, pengelola paket mentransfer kontrol ke APEX Google.
  3. Pengelola APEX memverifikasi file APEX.
  4. Jika file APEX diverifikasi, {i>database<i} internal pengelola APEX akan diperbarui untuk mencerminkan bahwa file APEX akan diaktifkan pada {i>booting<i} berikutnya.
  5. Pemohon instal menerima {i>broadcast<i} setelah paket berhasil verifikasi.
  6. Untuk melanjutkan penginstalan, sistem harus dimulai ulang.
  7. Pada {i>booting<i} berikutnya, pengelola APEX memulai, membaca {i>database<i} internal, dan melakukan berikut ini untuk setiap file APEX yang tercantum:

    1. Memverifikasi file APEX.
    2. Membuat perangkat loopback dari file APEX.
    3. Membuat perangkat blok mapper perangkat di atas perangkat loopback.
    4. Memasang perangkat blok mapper perangkat ke jalur unik (misalnya, /apex/name@ver).

Ketika semua file APEX yang tercantum dalam database internal terpasang, APEX manager menyediakan layanan binder untuk komponen sistem lain guna mengkueri informasi tentang file APEX yang terinstal. Misalnya, sistem lain komponen dapat melakukan kueri daftar file APEX yang terinstal di perangkat atau jalur persis tempat APEX tertentu dipasang, sehingga file tersebut dapat diakses.

File APEX adalah file APK

File APEX adalah file APK yang valid karena merupakan arsip zip bertanda tangan (menggunakan Skema tanda tangan APK) yang berisi file AndroidManifest.xml. Hal ini memungkinkan APEX untuk menggunakan infrastruktur file APK, seperti aplikasi penginstal paket, utilitas penandatanganan, dan pengelola paket.

Ukuran file AndroidManifest.xml dalam file APEX minimal, yang terdiri dari paket name, versionCode, dan targetSdkVersion, minSdkVersion opsional, dan maxSdkVersion untuk penargetan yang lebih detail. Informasi ini memungkinkan APEX file untuk dikirim melalui saluran yang ada seperti aplikasi {i>installer<i} paket dan dan proses selanjutnya.

Jenis file yang didukung

Format APEX mendukung jenis file ini:

  • Library bersama native
  • Native yang dapat dieksekusi
  • File JAR
  • File data
  • File konfigurasi

Ini tidak berarti bahwa APEX dapat memperbarui semua jenis file ini. Apakah file dapat diperbarui tergantung pada platform dan seberapa stabil definisi antarmuka untuk jenis file tersebut.

Opsi penandatanganan

File APEX ditandatangani dengan dua cara. Pertama, apex_payload.img (khususnya, file deskriptor vbmeta yang ditambahkan ke apex_payload.img) ditandatangani dengan kunci. Kemudian, seluruh APEX ditandatangani menggunakan APK signature scheme v3. Dua kunci yang 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 ditegakkan baik pada waktu build maupun pada saat {i>runtime<i}.

APEX di partisi bawaan

File APEX dapat ditempatkan di partisi bawaan seperti /system. Tujuan partisi sudah melalui {i>dm-verity<i}, sehingga file APEX dipasang secara langsung melalui perangkat {i>loopback<i}.

Jika APEX ada di partisi bawaan, APEX dapat diperbarui dengan memberikan paket APEX dengan nama paket yang sama dan lebih besar dari atau sama ke kode versi. APEX baru disimpan di /data dan, mirip dengan APK, versi yang baru diinstal membayangi versi yang sudah ada di partisi. Tapi tidak seperti APK, versi APEX yang baru diinstal hanya diaktifkan setelah {i>reboot<i}.

Persyaratan kernel

Untuk mendukung modul mainline APEX pada perangkat Android, arsitektur fitur {i>kernel<i} yang diperlukan: {i> loopback driver<i} dan {i>dm-verity<i}. Loopback {i>driver <i}memasang image sistem file dalam modul APEX dan dm-verity memverifikasi modul APEX.

Performa driver loopback dan dm-verity penting dalam mencapai kinerja sistem yang baik saat menggunakan modul APEX.

Versi kernel yang didukung

Modul mainline APEX didukung pada perangkat yang menggunakan kernel versi 4.4 atau lebih tinggi. Perangkat baru yang diluncurkan dengan Android 10 atau yang lebih baru harus menggunakan kernel versi 4.9 atau yang lebih tinggi untuk mendukung modul APEX.

Patch kernel yang diperlukan

Patch {i>kernel<i} yang diperlukan untuk mendukung modul APEX termasuk dalam Hierarki umum Android. Untuk mendapatkan patch yang 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, penggabungan turun dari cabang android-4.4 direkomendasikan. Berikut adalah daftar masing-masing patch yang diperlukan untuk {i>kernel<i} versi 4.4.

  • UPSTREAM: loop: menambahkan ioctl untuk mengubah ukuran blok logis (4,4)
  • BACKPORT: blok/loop: setel hw_sectors (4,4)
  • UPSTREAM: loop: Menambahkan LOOP_SET_BLOCK_SIZE di compat ioctl (4,4)
  • ANDROID: mnt: Perbaiki next_descendent (4,4)
  • ANDROID: mnt: remount harus diterapkan ke budak (4,4)
  • ANDROID: mnt: Menerapkan ulang dengan benar (4,4)
  • Kembalikan "ANDROID: dm verity: tambahkan ukuran pengambilan minimum" (4,4)
  • UPSTREAM: loop: menghapus cache jika offset atau block_size diubah (4,4)

Kernel versi 4.9/4.14/4.19

Untuk mendapatkan patch yang diperlukan untuk kernel versi 4.9/4.14/4.19, turunkan-penggabungan 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-item dengan tanda bintang (*) adalah persyaratan yang ada mulai 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 persyaratan:

  • loop.max_loop TIDAK boleh ditetapkan
  • loop.max_part harus <= 8

Membangun APEX

Bagian ini menjelaskan cara membangun APEX menggunakan sistem build Android. Berikut adalah contoh Android.bp untuk APEX yang 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 file dan lokasi di APEX

Jenis file Lokasi di APEX
Galeri foto bersama /lib dan /lib64 (/lib/arm untuk grup yang diterjemahkan dalam x86)
Dapat dijalankan /bin
Library Java /javalib
Bawaan /etc

Dependensi transitif

File APEX secara otomatis menyertakan dependensi transitif library native bersama atau file yang dapat dieksekusi. Misalnya, jika libFoo bergantung pada libBar, kedua library tersebut adalah disertakan jika hanya libFoo yang tercantum di properti native_shared_libs.

Menangani beberapa ABI

Instal properti native_shared_libs untuk utama dan sekunder antarmuka biner aplikasi (ABI) perangkat. Jika APEX menargetkan perangkat dengan ABI tunggal (yaitu, hanya 32 bit atau 64 bit saja), hanya ABI yang terkait akan diinstal.

Instal properti binaries hanya untuk ABI primer perangkat sebagai dijelaskan di bawah ini:

  • Jika perangkat hanya 32 bit, hanya varian biner 32-bit yang terinstal.
  • Jika perangkat hanya 64-bit, maka hanya varian 64-bit dari biner yang terinstal.

Untuk menambahkan kontrol mendetail atas ABI library dan biner native, gunakan multilib.[first|lib32|lib64|prefer32|both].[native_shared_libs|binaries] properti baru.

  • first: Mencocokkan ABI primer perangkat. Ini adalah default untuk biner.
  • lib32: Mencocokkan ABI 32-bit perangkat, jika didukung.
  • lib64: Mencocokkan ABI 64-bit perangkat, yang didukung.
  • prefer32: Mencocokkan ABI 32-bit perangkat, jika didukung. Jika ABI 32-bit tidak didukung, cocok dengan ABI 64-bit.
  • both: Mencocokkan kedua ABI. Ini adalah default untuk native_shared_libraries.

Properti java, libraries, dan prebuilts tidak bergantung pada ABI.

Contoh ini ditujukan untuk perangkat yang mendukung 32/64 dan tidak 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

Tanda tangani setiap APEX dengan kunci yang berbeda. Jika kunci baru diperlukan, buat pasangan kunci publik-pribadi dan membuat modul apex_key. Gunakan properti key untuk menandatangani APEX menggunakan kunci tersebut. Kunci publik secara otomatis disertakan dalam APEX dengan nama avb_pubkey.

# create an rsa key pair
openssl genrsa -out foo.pem 4096

# extract the public key from the key pair
avbtool extract_public_key --key foo.pem --output foo.avbpubkey

# in Android.bp
apex_key {
    name: "apex.test.key",
    public_key: "foo.avbpubkey",
    private_key: "foo.pem",
}

Pada contoh di atas, nama kunci publik (foo) menjadi ID tombol. 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

Tanda tangani APEX dengan cara yang sama seperti Anda menandatangani APK. Menandatangani APEX dua kali; sekali untuk sistem file mini (file apex_payload.img) dan satu kali untuk keseluruhan file.

Untuk menandatangani APEX di level file, tetapkan properti certificate di salah satu tiga cara ini:

  • Tidak ditetapkan: Jika tidak ada nilai yang ditetapkan, APEX ditandatangani dengan sertifikat yang berada pukul PRODUCT_DEFAULT_DEV_CERTIFICATE. Jika tidak ada tanda yang ditetapkan, jalur akan ditetapkan secara default ke build/target/product/security/testkey.
  • <name>: APEX ditandatangani dengan sertifikat <name> dalam sebagai PRODUCT_DEFAULT_DEV_CERTIFICATE.
  • :<name>: APEX ditandatangani dengan sertifikat yang ditentukan oleh Modul Soong bernama <name>. Modul sertifikat dapat didefinisikan sebagai mengikuti.
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 dalam apex_manifest.json dan APEX yang saat ini terinstal tidak terpakai (misalnya, layanan apa pun yang ada di dalamnya memiliki dihentikan), maka APEX baru dapat diinstal tanpa {i>reboot<i} dengan tanda --force-non-staged.

adb install --force-non-staged apex_file_name

Menggunakan APEX

Setelah reboot, APEX akan dipasang di /apex/<apex_name>@<version> saat ini. Beberapa versi APEX yang sama dapat dipasang secara bersamaan. Di antara jalur pemasangan, jalur yang sesuai dengan versi terbaru adalah terpasang pada /apex/<apex_name>.

Klien dapat menggunakan jalur yang di-bind-mount untuk membaca atau mengeksekusi file dari APEX.

APEX biasanya digunakan sebagai berikut:

  1. OEM atau ODM melakukan pramuat APEX di bawah /system/apex saat perangkat dikirimkan.
  2. File di APEX diakses melalui jalur /apex/<apex_name>/.
  3. Saat versi APEX yang diupdate diinstal di /data/apex, jalur tersebut mengarah ke APEX baru setelah {i>reboot<i}.

Mengupdate layanan dengan APEX

Untuk mengupdate layanan menggunakan APEX:

  1. Tandai layanan di partisi sistem sebagai dapat diperbarui. Menambahkan opsi updatable ke definisi layanan.

    /system/etc/init/myservice.rc:
    
    service myservice /system/bin/myservice
        class core
        user system
        ...
        updatable
    
  2. Buat file .rc baru untuk layanan yang diupdate. Gunakan opsi override 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 dari APEX. {i>Action<i} {i>trigger<i} tidak didukung di APEX.

Jika layanan yang ditandai sebagai dapat diperbarui dimulai sebelum APEX diaktifkan, dimulai ditunda sampai aktivasi APEX selesai.

Mengonfigurasi sistem untuk mendukung update APEX

Tetapkan properti sistem berikut ke true untuk mendukung pembaruan 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 Rata

Untuk perangkat lama, terkadang tidak mungkin atau tidak memungkinkan untuk mengupdate {i>kernel<i} untuk sepenuhnya mendukung APEX. Misalnya, {i>kernel<i} mungkin telah dibangun tanpa CONFIG_BLK_DEV_LOOP=Y, yang penting untuk memasang sistem file image di dalam APEX.

{i>Flattened APEX<i} adalah APEX yang dibuat khusus yang dapat diaktifkan pada perangkat dengan {i>kernel<i} lama. File dalam APEX yang disatukan langsung diinstal ke direktori di bawah partisi {i>built-in<i}. Misalnya, lib/libFoo.so dalam APEX yang diratakan my.apex diinstal ke /system/apex/my.apex/lib/libFoo.so.

Mengaktifkan APEX yang disatukan tidak melibatkan perangkat loop. Seluruh direktori /system/apex/my.apex langsung di-binding ke /apex/name@ver.

APEX rata tidak dapat diupdate dengan mendownload versi terbaru APEX dari jaringan karena APEX yang diunduh tidak dapat diratakan. APEX yang disatukan hanya dapat diupdate melalui OTA biasa.

APEX rata adalah konfigurasi default. Ini berarti bahwa semua APEX secara default disatukan kecuali Anda mengonfigurasi perangkat secara eksplisit untuk membangun APEX yang tidak disatukan guna mendukung update APEX (seperti yang dijelaskan di atas).

Mencampur APEX yang diratakan dan tidak diratakan di perangkat BUKAN didukung. APEX di perangkat harus tidak diratakan atau diratakan semua. Hal ini sangat penting ketika mengirimkan {i> pre-built<i} APEX yang telah ditandatangani untuk project seperti Mainline. APEX yang tidak ditandatangani sebelumnya (yaitu, dibuat dari sumbernya) juga harus tidak diratakan dan ditandatangani dengan kunci yang sesuai. Tujuan perangkat harus mewarisi dari updatable_apex.mk seperti yang dijelaskan dalam Mengupdate layanan dengan APEX.

APEX terkompresi

Android 12 dan yang lebih baru memiliki fitur kompresi APEX untuk mengurangi dampak penyimpanan dari paket APEX yang dapat diperbarui. Setelah pembaruan ke APEX sudah diinstal, meskipun versi yang telah diinstal sebelumnya tidak digunakan lagi, APEX masih menempati ruang yang sama. Ruang yang ditempati tetap tidak tersedia.

Kompresi APEX meminimalkan dampak penyimpanan ini dengan menggunakan kumpulan yang sangat terkompresi file APEX di partisi hanya baca (seperti partisi /system). Android 12 dan yang lebih baru menggunakan algoritma kompresi zip DEFLATE.

Kompresi tidak memberikan pengoptimalan untuk hal berikut:

  • APEX bootstrap yang harus dipasang sangat awal pada saat booting .

  • APEX yang tidak dapat diperbarui. Kompresi hanya bermanfaat jika versi APEX yang diupdate diinstal pada partisi /data. Daftar lengkap APEX yang dapat diperbarui tersedia di Komponen Sistem Modular kami.

  • APEX library bersama dinamis. Karena apexd selalu mengaktifkan kedua versi APEX tersebut (yang sudah diinstal sebelumnya dan diupgrade), mengompresinya tidak menambah nilai.

Format file APEX terkompresi

Ini adalah format file APEX yang dikompresi.

Diagram menunjukkan format file APEX yang dikompresi

Gambar 2. Format file APEX terkompresi

Pada tingkat atas, file APEX yang dikompresi adalah file ZIP yang berisi file asli file apex dalam bentuk mengempis dengan tingkat kompresi 9, dan dengan file lainnya disimpan tanpa kompresi.

Empat file terdiri dari sebuah file APEX:

  • original_apex: diturunkan dengan tingkat kompresi 9 Ini adalah file APEX asli yang tidak dikompresi.
  • apex_manifest.pb: hanya disimpan
  • AndroidManifest.xml: hanya disimpan
  • apex_pubkey: hanya disimpan

File apex_manifest.pb, AndroidManifest.xml, dan apex_pubkey salinan file yang sesuai di original_apex.

Membangun APEX terkompresi

APEX terkompresi dapat dibangun menggunakan alat apex_compression_tool.py yang terletak di system/apex/tools.

Beberapa parameter yang terkait dengan kompresi APEX tersedia dalam sistem build.

Di Android.bp, apakah file APEX dapat dikompresi dikontrol oleh Properti compressible:

apex {
    name: "apex.test",
    manifest: "apex_manifest.json",
    file_contexts: "file_contexts",
    compressible: true,
}

Tanda produk PRODUCT_COMPRESSED_APEX mengontrol apakah image sistem dibuat dari sumber harus berisi file APEX terkompresi.

Untuk eksperimen lokal, Anda dapat memaksa build untuk mengompresi APEX dengan menetapkan OVERRIDE_PRODUCT_COMPRESSED_APEX= hingga true.

File APEX terkompresi yang dihasilkan oleh sistem build memiliki ekstensi .capex. Ekstensi memudahkan membedakan antara yang dikompresi dan yang tidak dikompresi versi dari file APEX.

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 dalam direktori /data/apex/decompressed. Hasil file APEX yang didekompresi akan ditautkan ke direktori /data/apex/active.

Perhatikan contoh berikut sebagai ilustrasi dari proses yang dijelaskan di atas.

Pertimbangkan /system/apex/com.android.foo.capex sebagai APEX terkompresi diaktifkan, dengan versionCode 37.

  1. File original_apex di dalam /system/apex/com.android.foo.capex didekompresi menjadi /data/apex/decompressed/com.android.foo@37.apex.
  2. restorecon /data/apex/decompressed/com.android.foo@37.apex dilakukan untuk pastikan bahwa server memiliki label SELinux yang benar.
  3. Pemeriksaan verifikasi dilakukan pada /data/apex/decompressed/com.android.foo@37.apex untuk memastikan validitasnya: apexd memeriksa kunci publik yang dipaketkan dalam /data/apex/decompressed/com.android.foo@37.apex untuk memverifikasi bahwa sudah sama menjadi paket yang dipaketkan dalam /system/apex/com.android.foo.capex.
  4. File /data/apex/decompressed/com.android.foo@37.apex ditautkan dengan keras ke direktori /data/apex/active/com.android.foo@37.apex.
  5. 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 aplikasi OTA. Sejak update OTA mungkin berisi file APEX terkompresi dengan level versi yang lebih tinggi daripada yang aktif pada perangkat, sejumlah ruang kosong tertentu harus direservasi sebelum perangkat dimulai ulang untuk menerapkan pembaruan OTA.

Untuk mendukung sistem OTA, apexd mengekspos dua API binder ini:

  • calculateSizeForCompressedApex - menghitung ukuran yang diperlukan untuk dekompresi File APEX dalam paket OTA. Ini dapat digunakan untuk memverifikasi bahwa perangkat memiliki cukup ruang sebelum OTA diunduh.
  • reserveSpaceForCompressedApex - mencadangkan ruang disk untuk digunakan di lain waktu oleh apexd untuk mendekompresi file APEX terkompresi di dalam paket OTA.

Dalam kasus update OTA A/B, apexd akan mencoba dekompresi di latar belakang sebagai bagian dari rutinitas OTA pascapenginstalan. Jika dekompresi gagal, apexd melakukan dekompresi selama booting yang menerapkan OTA memperbarui.

Alternatif yang dipertimbangkan saat mengembangkan APEX

Berikut adalah beberapa opsi yang dipertimbangkan AOSP saat mendesain file APEX format apa pun, dan mengapa mereka disertakan atau dikecualikan.

Sistem pengelolaan paket reguler

Distribusi Linux memiliki sistem pengelolaan paket seperti dpkg dan rpm, yang tangguh, matang, dan tangguh. Namun, mereka tidak diadopsi untuk APEX karena mereka tidak dapat melindungi paket setelah penginstalan. Verifikasi hanya dilakukan ketika paket sedang diinstal. Penyerang dapat merusak integritas paket yang diinstal tanpa disadari. Ini adalah regresi untuk Android, di mana semua komponen sistem disimpan dengan metode {i>read-only<i} sistem file yang integritasnya dilindungi oleh {i>dm-verity<i} untuk setiap I/O. Apa saja gangguan terhadap komponen sistem harus dilarang, atau dapat dideteksi sehingga bahwa perangkat dapat menolak untuk mem-{i>booting<i} jika disusupi.

dm-crypt untuk integritas

File dalam container APEX berasal dari partisi bawaan (misalnya, /system) yang dilindungi oleh dm-verity, dengan perubahan pada file dilarang bahkan setelah partisi terpasang. Untuk menyediakan tingkat keamanan yang sama terhadap file, semua file dalam APEX disimpan dalam sebuah file yang dipasangkan dengan {i>hash tree <i} dan deskriptor vbmeta. Tanpa dm-verity, APEX di partisi /data rentan terhadap perubahan yang tidak diinginkan modifikasi yang dibuat setelah diverifikasi dan diinstal.

Bahkan, partisi /data juga dilindungi oleh lapisan enkripsi seperti dm-crypt. Meskipun ini memberikan beberapa tingkat perlindungan terhadap gangguan, tujuan utamanya adalah privasi, bukan integritas. Ketika penyerang mendapatkan akses ke /data, tidak ada perlindungan lebih lanjut, dan sekali lagi ini adalah regresi dibandingkan dengan setiap komponen sistem yang ada dalam partisi /system. Hierarki {i>hash<i} di dalam file APEX bersama dengan {i>dm-verity<i} memberikan tingkat perlindungan konten.

Mengalihkan jalur dari /system ke /apex

File komponen sistem yang dikemas dalam APEX dapat diakses melalui jalur baru seperti /apex/<name>/lib/libfoo.so. Kapan file tersebut merupakan bagian dari /system partisi, file tersebut dapat diakses melalui jalur seperti /system/lib/libfoo.so. J klien file APEX (platform atau file APEX lainnya) harus menggunakan klien . Anda mungkin perlu memperbarui kode yang ada karena perubahan jalur.

Meskipun salah satu cara untuk menghindari perubahan jalur adalah dengan menempatkan isi file dalam sebuah File APEX ke partisi /system, tim Android memutuskan untuk tidak melakukan overlay di partisi /system karena hal ini dapat memengaruhi performa sebagai jumlah file yang di-overlay (bahkan mungkin ditumpuk satu per satu) meningkat.

Pilihan 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 menghapus opsi ini karena tidak mungkin mengubah semua fungsi yang menerima jalur. Misalnya, beberapa aplikasi secara statis menautkan Bionic, yang mengimplementasikan fungsi. Dalam kasus tersebut, aplikasi tersebut tidak dialihkan.