Format file APEX

Format penampung Android Pony EXpress (APEX) diperkenalkan di Android 10 dan digunakan dalam alur penginstalan untuk modul sistem level lebih rendah. 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 dengan model 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. Pengelola paket adalah repositori pusat informasi tentang aplikasi dan hanya dapat dimulai dari pengelola aktivitas, yang siap di tahap berikutnya dari prosedur booting.
  • Format APK (terutama manifes) dirancang untuk aplikasi Android dan modul sistem tidak selalu cocok.

Desain

Bagian ini menjelaskan desain tingkat tinggi dari format file APEX dan pengelola APEX, yang merupakan layanan yang mengelola file APEX.

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

Format APEX

Ini adalah format file APEX.

Format file APEX

Gambar 1. Format file APEX

Di tingkat teratas, file APEX adalah file zip tempat file disimpan 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 buffer protokol ApexManifest 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 ini 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, hierarki hash dan blok metadata dibuat menggunakan library libavb. Payload sistem file tidak diuraikan (karena image harus dapat dipasang 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 entitas yang sama yang menandatangani APEX yang sama di partisi bawaan.

Panduan penamaan APEX

Untuk membantu mencegah konflik penamaan antara APEX baru seiring kemajuan platform, gunakan panduan penamaan berikut:

  • com.android.*
    • Direservasi untuk APEX AOSP. Tidak unik untuk perusahaan atau perangkat mana pun.
  • com.<companyname>.*
    • Disimpan untuk perusahaan. Berpotensi digunakan oleh beberapa perangkat dari perusahaan tersebut.
  • com.<companyname>.<devicename>.*
    • Direservasi untuk APEX yang unik untuk perangkat tertentu (atau subkumpulan 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 diinstal sebelumnya di perangkat pada /system/apex. Pengelola APEX secara default menggunakan paket ini jika tidak ada update yang tersedia.

Urutan update APEX menggunakan class PackageManager dan sebagai berikut.

  1. File APEX didownload melalui aplikasi penginstal paket, ADB, atau sumber lainnya.
  2. Pengelola paket memulai prosedur penginstalan. Setelah mengenali bahwa file tersebut adalah APEX, pengelola paket akan mentransfer kontrol ke pengelola APEX.
  3. Pengelola APEX memverifikasi file APEX.
  4. Jika file APEX diverifikasi, database internal pengelola APEX akan diperbarui untuk menunjukkan bahwa file APEX diaktifkan saat booting berikutnya.
  5. Pemohon penginstalan menerima siaran setelah verifikasi paket berhasil.
  6. Untuk melanjutkan penginstalan, sistem harus dimulai ulang.
  7. Saat booting berikutnya, pengelola APEX akan dimulai, membaca database internal, dan melakukan hal berikut untuk setiap file APEX yang tercantum:

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

Saat semua file APEX yang tercantum dalam database internal dipasang, pengelola APEX akan menyediakan layanan binder untuk komponen sistem lain guna membuat kueri informasi tentang file APEX yang diinstal. Misalnya, komponen sistem lainnya dapat mengkueri daftar file APEX yang diinstal di perangkat atau mengkueri jalur persis tempat APEX tertentu dipasang, 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, yang terdiri dari paket name, versionCode, dan targetSdkVersion, minSdkVersion, dan maxSdkVersion opsional untuk penargetan terperinci. Informasi ini memungkinkan file APEX dikirim 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 bahwa APEX dapat mengupdate semua jenis file ini. Apakah jenis file dapat diperbarui bergantung pada platform dan seberapa stabil definisi antarmuka untuk jenis file.

Opsi penandatanganan

File APEX ditandatangani dengan dua cara. Pertama, file apex_payload.img (khususnya, deskripsi vbmeta yang ditambahkan ke apex_payload.img) ditandatangani dengan kunci. Kemudian, seluruh APEX ditandatangani menggunakan skema tanda tangan APK v3. Dua kunci yang berbeda digunakan dalam proses ini.

Di sisi perangkat, kunci publik yang sesuai dengan kunci pribadi yang digunakan untuk menandatangani deskripsi 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 ditempatkan di partisi bawaan seperti /system. Partisi sudah berada di atas dm-verity, sehingga file APEX dipasang langsung di atas 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 atau sama. APEX baru disimpan di /data dan, mirip dengan APK, versi yang baru diinstal akan menyamarkan versi yang sudah ada di partisi bawaan. Namun, tidak seperti APK, versi APEX yang baru diinstal hanya diaktifkan setelah dimulai ulang.

Persyaratan kernel

Untuk mendukung modul mainline 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 dalam 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 hierarki umum Android. Untuk mendapatkan patch guna mendukung APEX, gunakan versi terbaru pohon umum Android.

Versi kernel 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 sangat direkomendasikan. Berikut adalah daftar patch individual yang diperlukan untuk kernel versi 4.4.

  • UPSTREAM: loop: menambahkan ioctl untuk mengubah ukuran blok logis (4.4)
  • BACKPORT: block/loop: set hw_sectors (4.4)
  • UPSTREAM: loop: Menambahkan LOOP_SET_BLOCK_SIZE di ioctl compat (4.4)
  • ANDROID: mnt: Memperbaiki next_descendent (4.4)
  • ANDROID: mnt: remount harus diterapkan ke slave dari slave (4.4)
  • ANDROID: mnt: Memperluas pemasangan ulang dengan benar (4.4)
  • Mengembalikan "ANDROID: dm verity: add minimum prefetch size" (4.4)
  • UPSTREAM: loop: drop cache if offset or block_size are changed (4.4)

Versi kernel 4.9/4.14/4.19

Untuk mendapatkan patch yang diperlukan untuk versi kernel 4.9/4.14/4.19, lakukan penggabungan turun 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 ada dari Android 9 dan yang lebih lama.

(*) 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 ditetapkan
  • loop.max_part harus <= 8

Mem-build APEX

Bagian ini menjelaskan cara mem-build 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)
File yang dapat dieksekusi /bin
Library Java /javalib
Aplikasi bawaan /etc

Dependensi transitif

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

Menangani beberapa ABI

Instal properti native_shared_libs untuk antarmuka biner aplikasi (ABI) utama 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 setelan 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, cocokkan dengan ABI 64-bit.
  • both: Mencocokkan kedua ABI. Ini adalah setelan 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 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

Tanda tangani setiap APEX dengan kunci yang berbeda. Jika 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 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 kunci. ID kunci yang digunakan untuk menandatangani APEX ditulis di 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. Tanda tangani 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 ditetapkan: Jika tidak ada nilai yang ditetapkan, APEX ditandatangani dengan sertifikat yang terletak di 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> di direktori yang sama dengan PRODUCT_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, layanan apa pun yang dikandungnya telah dihentikan), APEX baru dapat diinstal tanpa memulai ulang dengan flag --force-non-staged.

adb install --force-non-staged apex_file_name

Menggunakan APEX

Setelah dimulai ulang, APEX akan dipasang di direktori /apex/<apex_name>@<version>. Beberapa versi APEX yang sama dapat dipasang secara bersamaan. Di antara jalur pemasangan, jalur yang sesuai dengan versi terbaru dipasang dengan pengikatan di /apex/<apex_name>.

Klien dapat menggunakan jalur yang dipasang dengan bind untuk membaca atau mengeksekusi file dari APEX.

APEX biasanya digunakan sebagai berikut:

  1. OEM atau ODM memuat APEX secara default di /system/apex saat perangkat dikirim.
  2. File di APEX diakses melalui jalur /apex/<apex_name>/.
  3. Saat versi APEX yang diupdate diinstal di /data/apex, jalur akan mengarah ke APEX baru setelah dimulai ulang.

Memperbarui layanan dengan APEX

Untuk mengupdate layanan menggunakan APEX:

  1. 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
    
  2. Buat file .rc baru untuk layanan yang diperbarui. Gunakan opsi override untuk menentukan 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, 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 di-flatten

Untuk perangkat lama, terkadang tidak mungkin atau tidak dapat dilakukan untuk mengupdate kernel lama agar sepenuhnya mendukung APEX. Misalnya, kernel mungkin telah di-build tanpa CONFIG_BLK_DEV_LOOP=Y, yang sangat penting untuk memasang image sistem file di dalam APEX.

APEX yang di-flatten adalah APEX yang dibuat khusus yang dapat diaktifkan di perangkat dengan kernel lama. File dalam APEX yang diratakan langsung diinstal ke direktori di bagian partisi bawaan. Misalnya, lib/libFoo.so dalam my.apex APEX yang diratakan diinstal ke /system/apex/my.apex/lib/libFoo.so.

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

APEX yang diratakan tidak dapat diperbarui dengan mendownload versi APEX yang diperbarui 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 secara default diratakan 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 di-flatten dan tidak di-flatten di perangkat TIDAK didukung. APEX di perangkat harus semuanya tidak di-flatten atau semuanya di-flatten. Hal ini sangat penting saat mengirimkan prebuilt APEX yang ditandatangani sebelumnya untuk project seperti Mainline. APEX yang tidak ditandatangani sebelumnya (yaitu, dibuat dari sumber) juga tidak boleh diratakan dan ditandatangani dengan kunci yang sesuai. Perangkat harus mewarisi dari updatable_apex.mk seperti yang dijelaskan dalam Memperbarui layanan dengan APEX.

APEX yang Dikompresi

Android 12 dan yang lebih baru menampilkan kompresi APEX untuk mengurangi dampak penyimpanan paket APEX yang dapat diupdate. Setelah update untuk APEX diinstal, meskipun versi yang diinstal sebelumnya tidak digunakan lagi, versi tersebut masih menempati jumlah ruang yang sama. Ruang yang ditempati tersebut tetap tidak tersedia.

Kompresi APEX meminimalkan dampak penyimpanan ini dengan menggunakan kumpulan file APEX yang dikompresi secara maksimal 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:

  • APEX Bootstrap yang harus dipasang sangat awal dalam urutan booting.

  • APEX yang tidak dapat diupdate. Kompresi hanya bermanfaat jika versi APEX yang diupdate diinstal di partisi /data. Daftar lengkap APEX yang dapat diupdate tersedia di halaman Modular System Components.

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

Format file APEX yang dikompresi

Ini adalah format file APEX yang dikompresi.

Diagram menunjukkan format file APEX yang dikompresi

Gambar 2. Format file APEX yang dikompresi

Di tingkat teratas, file APEX yang dikompresi adalah file zip yang berisi file apex asli dalam bentuk yang di-deflate dengan tingkat kompresi 9, dan dengan file lain yang disimpan tanpa dikompresi.

Empat file terdiri dari file APEX:

  • original_apex: dikempiskan 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 adalah salinan file yang sesuai di original_apex.

Mem-build APEX yang dikompresi

APEX yang dikompresi dapat dibuat menggunakan alat apex_compression_tool.py yang terletak di system/apex/tools.

Beberapa parameter yang terkait dengan kompresi APEX tersedia di 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,
}

Flag produk PRODUCT_COMPRESSED_APEX mengontrol apakah image sistem yang di-build dari sumber harus berisi file APEX yang dikompresi.

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

File APEX yang dikompresi yang dihasilkan oleh sistem build memiliki ekstensi .capex. Ekstensi ini memudahkan untuk membedakan 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 akan didekompresi ke direktori /data/apex/decompressed. File APEX yang didekompresi akan ditautkan secara hard 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.

  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 memverifikasi bahwa aplikasi 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 kunci tersebut sama dengan yang dipaketkan dalam /system/apex/com.android.foo.capex.
  4. File /data/apex/decompressed/com.android.foo@37.apex ditautkan secara hard 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 penerapan OTA. Karena update OTA mungkin berisi file APEX yang dikompresi dengan level versi yang lebih tinggi dari yang aktif di perangkat, sejumlah ruang kosong harus dicadangkan sebelum perangkat dimulai ulang untuk menerapkan update OTA.

Untuk mendukung sistem OTA, apexd mengekspos dua binder API 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 digunakan pada masa mendatang oleh apexd untuk mendekompresi file APEX yang dikompresi di dalam paket OTA.

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

Alternatif yang dipertimbangkan saat mengembangkan APEX

Berikut adalah 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, keduanya tidak diadopsi untuk APEX karena tidak dapat melindungi paket setelah penginstalan. Verifikasi hanya dilakukan saat paket diinstal. Penyerang dapat merusak integritas paket yang diinstal, tanpa diketahui. Ini adalah regresi untuk Android, tempat semua komponen sistem disimpan dalam sistem file hanya baca yang integritasnya dilindungi oleh dm-verity untuk setiap I/O. Setiap perubahan pada 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, dengan modifikasi apa pun pada file dilarang bahkan setelah partisi dipasang. Untuk memberikan tingkat keamanan yang sama pada file, semua file di APEX disimpan dalam image sistem file yang disambungkan dengan hierarki hash dan deskripsi vbmeta. Tanpa dm-verity, APEX di partisi /data rentan terhadap perubahan yang tidak disengaja yang dilakukan setelah diverifikasi dan diinstal.

Bahkan, partisi /data juga dilindungi oleh lapisan enkripsi seperti dm-crypt. Meskipun memberikan beberapa tingkat perlindungan terhadap modifikasi tidak sah, tujuan utama dari tindakan ini adalah privasi, bukan integritas. Saat penyerang mendapatkan akses ke partisi /data, tidak akan ada perlindungan lebih lanjut, dan ini lagi-lagi merupakan regresi dibandingkan dengan setiap komponen sistem yang berada di partisi /system. Hierarki 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. Saat file 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 karena perubahan jalur.

Meskipun salah satu cara untuk menghindari perubahan jalur adalah dengan menempatkan konten file dalam file APEX ke partisi /system, tim Android memutuskan untuk tidak menempatkan file di partisi /system karena hal ini dapat memengaruhi performa seiring peningkatan jumlah file yang ditempatkan (mungkin bahkan ditumpuk satu per 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 bagian /apex. Tim Android menghapus opsi ini karena tidak mungkin mengubah semua fungsi yang menerima jalur. Misalnya, beberapa aplikasi menautkan Bionic secara statis, yang mengimplementasikan fungsi tersebut. Dalam kasus tersebut, aplikasi tersebut tidak akan dialihkan.