Format file APEX

Format container Android Pony EXpress (APEX) diperkenalkan di Android 10 dan digunakan dalam alur instalasi untuk modul sistem tingkat rendah. Format ini memfasilitasi pembaruan komponen sistem yang tidak sesuai dengan model aplikasi Android standar. Beberapa contoh komponen adalah layanan dan pustaka asli, lapisan abstraksi perangkat keras ( HAL ), waktu proses ( ART ), dan pustaka kelas.

Istilah "APEX" juga bisa merujuk pada file APEX.

Latar belakang

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

  • Modul berbasis APK tidak dapat digunakan di awal urutan booting. Manajer paket adalah pusat penyimpanan informasi tentang aplikasi dan hanya dapat dimulai dari manajer aktivitas, yang akan siap pada tahap selanjutnya dari prosedur booting.
  • Format APK (khususnya manifes) dirancang untuk aplikasi Android dan modul sistem tidak selalu cocok.

Desain

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

Untuk informasi lebih lanjut tentang mengapa desain 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

Di tingkat atas, file APEX adalah file zip tempat file disimpan tanpa terkompresi dan terletak pada 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 paket dan versi, 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 sudah ada seperti aapt untuk memeriksa metadata dasar dari file tersebut. File tersebut 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 berhubungan dengan APEX. AndroidManifest.xml mungkin berisi informasi penargetan tambahan yang dapat digunakan oleh alat penerbitan aplikasi yang ada.

apex_payload.img adalah image sistem file ext4 yang didukung oleh dm-verity. Gambar dipasang saat runtime melalui perangkat loopback. Secara khusus, pohon hash dan blok metadata dibuat menggunakan perpustakaan libavb . Payload sistem file tidak diuraikan (karena gambar harus dapat dipasang di tempatnya). File biasa 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 diunduh ditandatangani dengan entitas yang sama yang menandatangani APEX yang sama di partisi bawaan.

Pedoman penamaan APEX

Untuk membantu mencegah konflik penamaan antar APEX baru seiring kemajuan platform, gunakan pedoman penamaan berikut:

  • com.android.*
    • Dicadangkan untuk AOSP APEX. Tidak unik untuk perusahaan atau perangkat mana pun.
  • com.<companyname>.*
    • Dicadangkan untuk perusahaan. Berpotensi digunakan oleh beberapa perangkat dari perusahaan tersebut.
  • com.<companyname>.<devicename>.*
    • Dicadangkan untuk APEX yang unik untuk perangkat tertentu (atau subkumpulan perangkat).

Manajer APEX

Manajer APEX (atau apexd ) adalah proses asli mandiri yang bertanggung jawab untuk memverifikasi, menginstal, dan menghapus instalasi file APEX. Proses ini diluncurkan dan siap di awal urutan boot. File APEX biasanya sudah diinstal sebelumnya pada perangkat di bawah /system/apex . Manajer APEX secara default menggunakan paket ini jika tidak ada pembaruan yang tersedia.

Urutan pembaruan APEX menggunakan kelas PackageManager dan adalah sebagai berikut.

  1. File APEX diunduh melalui aplikasi penginstal paket, ADB, atau sumber lain.
  2. Manajer paket memulai prosedur instalasi. Setelah mengenali bahwa file tersebut adalah APEX, manajer paket mentransfer kendali ke manajer APEX.
  3. Manajer APEX memverifikasi file APEX.
  4. Jika file APEX diverifikasi, database internal manajer APEX diperbarui untuk mencerminkan bahwa file APEX diaktifkan pada boot berikutnya.
  5. Pemohon instalasi menerima siaran setelah verifikasi paket berhasil.
  6. Untuk melanjutkan instalasi, sistem harus di-boot ulang.
  7. Pada boot berikutnya, manajer APEX memulai, membaca database internal, dan melakukan hal berikut untuk setiap file APEX yang terdaftar:

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

Ketika semua file APEX yang tercantum dalam database internal dipasang, manajer APEX menyediakan layanan pengikat untuk komponen sistem lainnya untuk menanyakan informasi tentang file APEX yang diinstal. Misalnya, komponen sistem lainnya dapat menanyakan daftar file APEX yang diinstal di perangkat atau menanyakan jalur pasti di mana 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 manajer paket.

File AndroidManifest.xml di dalam file APEX berukuran minimal, terdiri dari name paket , versionCode , dan targetSdkVersion opsional, minSdkVersion , dan maxSdkVersion untuk penargetan yang lebih detail. Informasi ini memungkinkan file APEX dikirimkan melalui saluran yang ada seperti aplikasi penginstal paket dan ADB.

Jenis file didukung

Format APEX mendukung jenis file berikut:

  • Lib bersama asli
  • Eksekusi asli
  • file JAR
  • File data
  • File konfigurasi

Ini tidak berarti APEX dapat memperbarui semua jenis file ini. Apakah suatu 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 ) file ditandatangani dengan kunci. Kemudian, seluruh APEX ditandatangani menggunakan skema tanda tangan APK v3 . Dua kunci berbeda digunakan dalam proses ini.

Di sisi perangkat, kunci publik yang sesuai dengan kunci pribadi yang digunakan untuk menandatangani deskriptor vbmeta dipasang. Manajer APEX menggunakan kunci publik untuk memverifikasi APEX yang diminta untuk dipasang. Setiap APEX harus ditandatangani dengan kunci yang berbeda dan diterapkan pada waktu build dan runtime.

APEX di partisi bawaan

File APEX dapat ditemukan 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 diperbarui dengan menyediakan paket APEX dengan nama paket yang sama dan kode versi yang lebih besar atau sama dengan. APEX baru disimpan di /data dan, mirip dengan APK, versi yang baru diinstal membayangi versi yang sudah ada di partisi bawaan. Namun tidak seperti APK, versi APEX yang baru diinstal hanya diaktifkan setelah reboot.

Persyaratan kernel

Untuk mendukung modul jalur utama APEX pada perangkat Android, diperlukan fitur kernel Linux berikut: 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 jalur utama APEX didukung pada perangkat yang menggunakan kernel versi 4.4 atau lebih tinggi. Perangkat baru yang diluncurkan dengan Android 10 atau lebih tinggi harus menggunakan kernel versi 4.9 atau lebih tinggi untuk mendukung modul APEX.

Patch kernel yang diperlukan

Patch kernel yang diperlukan untuk mendukung modul APEX disertakan dalam pohon umum Android. Untuk mendapatkan patch yang mendukung APEX, gunakan pohon umum Android versi terbaru.

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 down-merge dari cabang android-4.4 . Berikut ini adalah daftar patch individual yang diperlukan untuk kernel versi 4.4.

  • UPSTREAM: loop: tambahkan ioctl untuk mengubah ukuran blok logis ( 4.4 )
  • BACKPORT: blok/loop: setel hw_sectors ( 4.4 )
  • UPSTREAM: loop: Tambahkan LOOP_SET_BLOCK_SIZE di compat ioctl ( 4.4 )
  • ANDROID: mnt: Perbaiki next_descendent ( 4.4 )
  • ANDROID: mnt: remount harus disebarkan ke budak dari budak ( 4.4 )
  • ANDROID: mnt: Sebarkan remount dengan benar ( 4.4 )
  • Kembalikan "ANDROID: dm verity: tambahkan ukuran prefetch minimum" ( 4.4 )
  • UPSTREAM: loop: hapus 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, gabungkan ke bawah 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 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 baris perintah kernel

Untuk mendukung APEX, pastikan parameter baris perintah kernel memenuhi persyaratan berikut:

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

Bangun APEX

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

Jenis berkas Lokasi di APEX
Perpustakaan bersama /lib dan /lib64 ( /lib/arm untuk lengan yang diterjemahkan di x86)
Dapat dieksekusi /bin
perpustakaan Jawa /javalib
Bawaan /etc

Ketergantungan transitif

File APEX secara otomatis menyertakan dependensi transitif dari lib atau executable asli yang dibagikan. Misalnya, jika libFoo bergantung pada libBar , kedua lib tersebut disertakan ketika hanya libFoo yang terdaftar 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 ABI tunggal (yaitu, hanya 32 bit atau 64 bit saja), hanya perpustakaan dengan ABI terkait yang diinstal.

Instal properti binaries hanya untuk ABI utama perangkat seperti dijelaskan di bawah:

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

Untuk menambahkan kontrol menyeluruh atas ABI perpustakaan dan binari asli, 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 didukungnya.
  • prefer32 : Cocok dengan ABI 32-bit perangkat, jika didukung. Jika ABI 32-bit tidak didukung, cocokkan dengan ABI 64-bit.
  • both : Cocok dengan kedua ABI. Ini adalah default untuk native_shared_libraries .

Properti java , libraries , dan prebuilts bersifat ABI-agnostic.

Contoh ini untuk perangkat yang mendukung 32/64 dan tidak menyukai 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. Ketika kunci baru diperlukan, buat pasangan kunci publik-pribadi dan buat modul apex_key . Gunakan properti key untuk menandatangani APEX menggunakan kunci. 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",
}

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

Menandatangani 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, atur properti certificate dengan salah satu dari tiga cara berikut:

  • Tidak disetel: Jika tidak ada nilai yang disetel, APEX ditandatangani dengan sertifikat yang terletak di PRODUCT_DEFAULT_DEV_CERTIFICATE . Jika tidak ada tanda yang disetel, jalur defaultnya adalah 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 didefinisikan 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)
}

Instal 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 diinstal saat ini tidak digunakan (misalnya, layanan apa pun yang ada di dalamnya telah dihentikan), maka APEX baru dapat diinstal tanpa reboot dengan flag --force-non-staged .

adb install --force-non-staged apex_file_name

Gunakan APEX

Setelah reboot, APEX 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 di /apex/<apex_name> .

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

APEX biasanya digunakan sebagai berikut:

  1. OEM atau ODM memuat APEX di bawah /system/apex saat perangkat dikirimkan.
  2. File di APEX diakses melalui jalur /apex/<apex_name>/ .
  3. Ketika versi APEX yang diperbarui diinstal di /data/apex , jalurnya menunjuk ke APEX baru setelah reboot.

Perbarui layanan dengan APEX

Untuk memperbarui layanan menggunakan APEX:

  1. Tandai layanan di partisi sistem sebagai dapat diperbarui. 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 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 diperbarui dimulai sebelum APEX diaktifkan, permulaannya ditunda hingga aktivasi APEX selesai.

Konfigurasikan sistem untuk mendukung pembaruan APEX

Atur 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 mungkin untuk memperbarui kernel lama agar mendukung APEX sepenuhnya. Misalnya, kernel mungkin dibuat 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 pada perangkat dengan kernel lama. File dalam APEX yang diratakan langsung diinstal ke direktori di bawah partisi bawaan. Misalnya, lib/libFoo.so dalam 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 secara langsung diikat ke /apex/name@ver .

APEX yang diratakan tidak dapat diperbarui dengan mengunduh versi APEX yang diperbarui dari jaringan karena APEX yang diunduh tidak dapat diratakan. APEX yang diratakan hanya dapat diperbarui melalui OTA biasa.

APEX yang diratakan adalah konfigurasi default. Ini berarti bahwa semua APEX secara default diratakan kecuali Anda secara eksplisit mengonfigurasi perangkat Anda untuk membuat APEX yang tidak diratakan untuk mendukung pembaruan APEX (seperti dijelaskan di atas).

Mencampur APEX yang diratakan dan tidak diratakan dalam perangkat TIDAK didukung. APEX di perangkat harus semuanya tidak rata atau semuanya rata. Hal ini sangat penting ketika mengirimkan pra-bangun APEX yang telah ditandatangani sebelumnya untuk proyek seperti Mainline. APEX yang tidak ditentukan sebelumnya (yaitu, dibuat dari sumbernya) juga harus tidak diratakan dan ditandatangani dengan kunci yang sesuai. Perangkat harus mewarisi dari updatable_apex.mk seperti yang dijelaskan dalam Memperbarui layanan dengan APEX .

APEX terkompresi

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

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

Kompresi tidak memberikan optimalisasi pada hal berikut:

  • Bootstrap APEX yang perlu dipasang di awal urutan boot.

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

  • APEX lib bersama yang dinamis. Karena apexd selalu mengaktifkan kedua versi APEX tersebut (pra-instal dan upgrade), mengompresi keduanya tidak menambah nilai.

Format file APEX terkompresi

Ini adalah format file APEX terkompresi.

Diagram shows the format of a compressed APEX file

Gambar 2. Format file APEX terkompresi

Pada tingkat atas, file APEX terkompresi adalah file zip yang berisi file apex asli dalam bentuk kempes dengan tingkat kompresi 9, dan dengan file lain disimpan tanpa terkompresi.

Empat file terdiri dari file APEX:

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

File apex_manifest.pb , AndroidManifest.xml , dan apex_pubkey adalah salinan dari file terkait di original_apex .

Bangun APEX terkompresi

APEX terkompresi 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 dikompres atau tidak, dikontrol oleh properti compressible :

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

Bendera produk PRODUCT_COMPRESSED_APEX mengontrol apakah citra sistem yang dibuat dari sumber harus berisi file APEX terkompresi.

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

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

Algoritma kompresi yang didukung

Android 12 hanya mendukung kompresi deflate-zip.

Aktifkan file APEX terkompresi saat boot

Sebelum APEX terkompresi dapat diaktifkan, file original_apex di dalamnya didekompresi ke dalam direktori /data/apex/decompressed . File APEX hasil dekompresi ditautkan 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 ia 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 disertakan dalam /data/apex/decompressed/com.android.foo@37.apex untuk verifikasi bahwa itu sama dengan yang disertakan dalam /system/apex/com.android.foo.capex .
  4. File /data/apex/decompressed/com.android.foo@37.apex ditautkan ke direktori /data/apex/active/com.android.foo@37.apex .
  5. Logika aktivasi reguler untuk file APEX yang tidak terkompresi dilakukan di /data/apex/active/com.android.foo@37.apex .

Interaksi dengan OTA

File APEX terkompresi mempunyai implikasi pada pengiriman dan aplikasi OTA. Karena pembaruan OTA mungkin berisi file APEX terkompresi dengan tingkat versi yang lebih tinggi daripada yang aktif pada perangkat, sejumlah ruang kosong harus dicadangkan sebelum perangkat di-boot ulang untuk menerapkan pembaruan OTA.

Untuk mendukung sistem OTA, apexd memaparkan dua API pengikat berikut:

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

Dalam kasus pembaruan A/B OTA, apexd mencoba melakukan dekompresi di latar belakang sebagai bagian dari rutinitas OTA pasca-instal. Jika dekompresi gagal, apexd melakukan dekompresi selama boot yang menerapkan pembaruan OTA.

Alternatif dipertimbangkan ketika mengembangkan APEX

Berikut beberapa opsi yang dipertimbangkan AOSP saat mendesain format file APEX, dan mengapa opsi tersebut disertakan atau dikecualikan.

Sistem manajemen paket reguler

Distribusi Linux memiliki sistem manajemen paket seperti dpkg dan rpm , yang kuat, matang, dan tangguh. Namun, mereka tidak diadopsi untuk APEX karena tidak dapat melindungi paket setelah instalasi. Verifikasi dilakukan hanya ketika paket sedang diinstal. Penyerang dapat merusak integritas paket yang diinstal tanpa disadari. Ini adalah regresi untuk Android di mana semua komponen sistem disimpan dalam sistem file read-only yang integritasnya dilindungi oleh dm-verity untuk setiap I/O. Segala gangguan pada komponen sistem harus dilarang, atau dapat dideteksi sehingga perangkat dapat menolak melakukan booting jika disusupi.

dm-crypt untuk integritas

Berkas dalam wadah APEX berasal dari partisi bawaan (misalnya, partisi /system ) yang dilindungi oleh dm-verity, sehingga modifikasi apa pun terhadap berkas dilarang bahkan setelah partisi dipasang. Untuk memberikan tingkat keamanan yang sama pada file, semua file di 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 disengaja yang dilakukan setelah diverifikasi dan diinstal.

Faktanya, partisi /data juga dilindungi oleh lapisan enkripsi seperti dm-crypt. Meskipun hal ini memberikan perlindungan pada tingkat tertentu terhadap gangguan, tujuan utamanya adalah privasi, bukan integritas. Ketika penyerang mendapatkan akses ke partisi /data , tidak ada perlindungan lebih lanjut, dan ini sekali lagi merupakan regresi dibandingkan dengan setiap komponen sistem yang ada di partisi /system . Pohon hash di dalam file APEX bersama dengan dm-verity memberikan tingkat perlindungan konten yang sama.

Alihkan jalur dari/sistem ke/apex

File komponen sistem yang dikemas dalam APEX dapat diakses melalui jalur baru seperti /apex/<name>/lib/libfoo.so . Ketika file-file tersebut merupakan bagian dari partisi /system , mereka 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 menghamparkan konten file dalam file APEX ke partisi /system , tim Android memutuskan untuk tidak menghamparkan file di partisi /system karena hal ini dapat memengaruhi kinerja karena jumlah file yang dilapis ( bahkan mungkin ditumpuk satu demi satu) meningkat.

Pilihan lainnya adalah membajak fungsi akses file seperti open , stat , dan readlink , sehingga jalur yang dimulai dengan /system dialihkan ke jalur terkait di bawah /apex . Tim Android membuang opsi ini karena tidak mungkin mengubah semua fungsi yang menerima jalur. Misalnya, beberapa aplikasi menghubungkan Bionic secara statis, yang mengimplementasikan fungsinya. Dalam kasus seperti itu, aplikasi tersebut tidak dialihkan.