Android memiliki dua mekanisme pembaruan: pembaruan A/B (mulus) dan pembaruan non-A/B. Untuk mengurangi kerumitan kode dan menyempurnakan proses pembaruan, di Android 11 kedua mekanisme tersebut disatukan melalui A/B virtual untuk menghadirkan pembaruan tanpa hambatan ke semua perangkat dengan biaya penyimpanan yang diminimalkan. Android 12 menawarkan opsi kompresi A/B Virtual untuk mengompresi partisi yang di-snapshot. Di Android 11 dan Android 12, hal berikut ini berlaku:
- Pembaruan A/B virtual mulus seperti pembaruan A/B. Pembaruan A/B virtual meminimalkan waktu perangkat offline dan tidak dapat digunakan.
- Pembaruan A/B virtual dapat dibatalkan . Jika OS baru gagal untuk boot, perangkat secara otomatis memutar kembali ke versi sebelumnya.
- Pembaruan A/B virtual menggunakan ruang ekstra minimum dengan hanya menduplikasi partisi yang digunakan oleh bootloader. Partisi yang dapat diperbarui lainnya di- snapshot .
Latar belakang dan terminologi
Bagian ini mendefinisikan terminologi dan menjelaskan teknologi yang mendukung A/B virtual.
Pemeta perangkat
Device-mapper adalah lapisan blok virtual Linux yang sering digunakan di Android. Dengan partisi dinamis , partisi seperti /system
adalah tumpukan perangkat berlapis:
- Di bagian bawah tumpukan adalah partisi super fisik (misalnya,
/dev/block/by-name/super
). - Di tengah adalah perangkat
dm-linear
, menentukan blok mana dalam partisi super yang membentuk partisi yang diberikan. Ini muncul sebagai/dev/block/mapper/system_[a|b]
pada perangkat A/B, atau/dev/block/mapper/system
pada perangkat non-A/B. - Di bagian atas terdapat perangkat
dm-verity
, dibuat untuk partisi yang diverifikasi. Perangkat ini memverifikasi bahwa blok pada perangkatdm-linear
ditandatangani dengan benar. Itu muncul sebagai/dev/block/mapper/system-verity
dan merupakan sumber dari/system
mount point.
Gambar 1 menunjukkan seperti apa tumpukan di bawah /system
mount point.
Gambar 1. Tumpuk di bawah /system mount point
dm-snapshot
Virtual A/B bergantung pada dm-snapshot
, modul device-mapper untuk memotret status perangkat penyimpanan. Saat menggunakan dm-snapshot
, ada empat perangkat yang dimainkan:
- Perangkat dasar adalah perangkat yang di-snapshot. Pada halaman ini, perangkat dasar selalu merupakan partisi dinamis, seperti sistem atau vendor.
- Perangkat copy-on-write (COW), untuk mencatat perubahan ke perangkat dasar. Ukurannya bisa berapa saja, tetapi harus cukup besar untuk mengakomodasi semua perubahan pada perangkat dasar.
- Perangkat snapshot dibuat menggunakan target
snapshot
. Menulis ke perangkat snapshot ditulis ke perangkat COW. Membaca dari perangkat snapshot membaca baik dari perangkat dasar atau perangkat COW, tergantung pada apakah data yang diakses telah diubah oleh snapshot. - Perangkat asal dibuat menggunakan target
snapshot-origin
. Membaca ke perangkat asal membaca langsung dari perangkat dasar. Menulis ke perangkat asal menulis langsung ke perangkat dasar, tetapi data asli dicadangkan dengan menulis ke perangkat COW.
Gambar 2. Pemetaan perangkat untuk dm-snapshot
Snapshot terkompresi
Di Android 12, karena persyaratan ruang pada partisi /data
bisa tinggi, Anda dapat mengaktifkan snapshot terkompresi di build Anda untuk mengatasi persyaratan ruang yang lebih tinggi dari partisi /data
.
Snapshot terkompresi A/B virtual dibuat di atas dua komponen baru yang tersedia di Android 12:
-
dm-user
, modul kernel yang mirip dengan FUSE yang memungkinkan ruang pengguna untuk mengimplementasikan perangkat blok. -
snapuserd
, daemon userspace untuk mengimplementasikan format snapshot baru.
Komponen-komponen ini memungkinkan kompresi. Perubahan lain yang diperlukan untuk menerapkan kemampuan snapshot terkompresi diberikan di bagian berikutnya: format COW untuk snapshot terkompresi , dm-user , dan Snapuserd .
Format COW untuk snapshot terkompresi
Di Android 12, snapshot terkompresi menggunakan format COW baru. Mirip dengan format bawaan kernel yang digunakan untuk snapshot yang tidak terkompresi, format COW untuk snapshot terkompresi memiliki bagian metadata dan data yang bergantian. Metadata format asli hanya diperbolehkan untuk operasi "ganti": Ganti blok X di gambar dasar dengan konten blok Y di snapshot. Format COW snapshot terkompresi lebih ekspresif dan mendukung tiga operasi:
- Salin - Blok X di perangkat dasar harus diganti dengan blok Y di perangkat dasar.
- Ganti - Blok X di perangkat dasar harus diganti dengan konten blok Y di snapshot. Masing-masing blok ini dikompresi gz.
- Nol - Blok X di perangkat dasar harus diganti dengan semua nol.
Pembaruan OTA lengkap hanya terdiri dari penggantian dan operasi nol . Pembaruan OTA tambahan dapat memiliki operasi penyalinan .
pengguna dm di Android 12
Modul kernel dm-user memungkinkan userspace
untuk mengimplementasikan perangkat blok device-mapper. Entri tabel dm-user membuat perangkat lain-lain di bawah /dev/dm-user/<control-name>
. Proses userspace
dapat melakukan polling perangkat untuk menerima permintaan baca dan tulis dari kernel. Setiap permintaan memiliki buffer terkait untuk ruang pengguna untuk diisi (untuk dibaca) atau disebarkan (untuk ditulis).
Modul kernel dm-user
menyediakan antarmuka baru yang dapat dilihat pengguna ke kernel yang bukan bagian dari basis kode kernel.org upstream. Sampai saat ini, Google berhak untuk memodifikasi antarmuka dm-user
di Android.
pengguna snap
Komponen snapuserd
userspace ke dm-user
mengimplementasikan Virtual A/B Compression.
Dalam versi Virtual A/B yang tidak terkompresi, (baik di Android 11 dan yang lebih rendah, atau di Android 12 tanpa opsi snapshot terkompresi), perangkat COW adalah file mentah. Saat kompresi diaktifkan, COW berfungsi sebagai perangkat dm-user
, yang terhubung ke instance daemon snapuserd
.
Kernel tidak menggunakan format COW baru. Jadi komponen snapuserd
menerjemahkan permintaan antara format Android COW dan format bawaan kernel:
Gambar 3. Diagram alir snapuserd sebagai penerjemah antara format Android dan Kernel COW
Terjemahan dan dekompresi ini tidak pernah terjadi pada disk. Komponen snapuserd
mencegat pembacaan dan penulisan COW yang terjadi di kernel, dan mengimplementasikannya menggunakan format Android COW.
Proses kompresi A/B virtual
Bagian ini memberikan detail mengenai proses yang digunakan dalam kompresi A/B Virtual: membaca metadata, menggabungkan, dan melakukan transisi init.
Membaca metadata
Metadata dibangun oleh daemon snapuserd
. Metadata utamanya adalah pemetaan 2 ID, masing-masing 8 byte, yang mewakili sektor yang akan digabungkan. Dalam dm-snapshot
itu disebut sebagai disk_exception
.
struct disk_exception {
uint64_t old_chunk;
uint64_t new_chunk;
};
Pengecualian disk digunakan ketika sepotong data lama diganti dengan yang baru.
Daemon Snapuserd
membaca file KK internal melalui perpustakaan KK dan menyusun metadata untuk setiap operasi KK yang ada dalam file KK.
Pembacaan metadata dimulai dari dm-snapshot
di kernel saat perangkat dm- dm- snapshot
dibuat.
Gambar di bawah memberikan diagram urutan untuk jalur IO untuk konstruksi metadata.
Gambar 4. Alur urutan untuk jalur IO dalam konstruksi metadata
Penggabungan
Setelah proses boot selesai, mesin pembaruan menandai slot sebagai boot berhasil dan memulai penggabungan dengan mengalihkan target dm-snapshot
ke target dm-snapshot-merge
.
dm-snapshot
menelusuri metadata dan memulai penggabungan IO untuk setiap pengecualian disk. Ikhtisar tingkat tinggi dari jalur gabungan IO ditunjukkan di bawah ini.
Gambar 5. Menggabungkan ikhtisar jalur IO
Jika perangkat di-boot ulang selama proses penggabungan, penggabungan dilanjutkan pada reboot berikutnya, dan penggabungan selesai.
Init transisi
Saat mem-boot dengan snapshot terkompresi, init tahap pertama harus memulai snapuserd
untuk memasang partisi. Ini menimbulkan masalah: Ketika sepolicy
dimuat dan ditegakkan, snapuserd
dimasukkan ke dalam konteks yang salah, dan permintaan bacanya gagal, dengan penolakan selinux.
Untuk mengatasinya, snapuserd
transisi dalam lock-step dengan init
, sebagai berikut:
-
init
tahap pertama meluncurkansnapuserd
dari ramdisk, dan menyimpan deskriptor file yang terbuka ke dalamnya dalam variabel lingkungan. -
init
tahap pertama mengalihkan sistem file root ke partisi sistem, lalu mengeksekusi salinan sisteminit
. - Salinan sistem
init
membaca kebijakan gabungan menjadi string. -
Init
memanggilmlock()
pada semua halaman yang didukung ext4. Ini kemudian menonaktifkan semua tabel device-mapper untuk perangkat snapshot, dan menghentikansnapuserd
. Setelah ini dilarang membaca dari partisi, karena hal itu menyebabkan kebuntuan. - Menggunakan deskriptor terbuka ke salinan ramdisk dari
snapuserd
,init
meluncurkan kembali daemon dengan konteks selinux yang benar. Tabel device-mapper untuk perangkat snapshot diaktifkan kembali. - Init memanggil
munlockall()
- aman untuk melakukan IO lagi.
Penggunaan ruang
Tabel berikut memberikan perbandingan penggunaan ruang untuk mekanisme OTA yang berbeda menggunakan OS Pixel dan ukuran OTA.
Dampak Ukuran | non-A/B | A/B | Virtual A/B | Virtual A/B (terkompresi) |
---|---|---|---|---|
Gambar Pabrik Asli | 4.5GB super (gambar 3.8G + 700 juta dicadangkan) 1 | 9GB super (3.8G + 700M dicadangkan, untuk dua slot) | 4.5GB super (gambar 3.8G + 700 juta dicadangkan) | 4.5GB super (gambar 3.8G + 700 juta dicadangkan) |
Partisi statis lainnya | /cache | Tidak ada | Tidak ada | Tidak ada |
Penyimpanan tambahan Selama OTA (ruang dikembalikan setelah menerapkan OTA) | 1.4GB di /data | 0 | 3,8 GB 2 pada / data | 2.1GB 2 di /data |
Total penyimpanan yang diperlukan untuk menerapkan OTA | 5.9GB 3 (super dan data) | 9GB (super) | 8.3GB 3 (super dan data) | 6.6GB 3 (super dan data) |
1 Menunjukkan tata letak yang diasumsikan berdasarkan pemetaan Piksel.
2 Diasumsikan citra sistem baru berukuran sama dengan aslinya.
3 Kebutuhan ruang bersifat sementara hingga reboot.
Untuk menerapkan A/B Virtual, atau untuk menggunakan kemampuan snapshot terkompresi, lihat Menerapkan A/B Virtual