Mengimplementasikan A/B Virtual

Untuk mengimplementasikan A/B virtual pada perangkat baru, atau untuk retrofit perangkat yang diluncurkan, Anda harus membuat perubahan pada kode khusus perangkat.

Flag build

Perangkat yang menggunakan A/B virtual harus dikonfigurasi sebagai A/B perangkat dan harus diluncurkan dengan dinamis partisi.

Untuk perangkat yang diluncurkan dengan A/B virtual, setel perangkat tersebut untuk mewarisi A/B virtual konfigurasi dasar perangkat:

$(call inherit-product, \
    $(SRC_TARGET_DIR)/product/virtual_ab_ota.mk)

Perangkat yang diluncurkan dengan A/B virtual hanya membutuhkan ukuran papan setengah dari BOARD_SUPER_PARTITION_SIZE karena slot B tidak lagi di super. Yaitu, BOARD_SUPER_PARTITION_SIZE harus lebih besar dari atau sama dengan sum(ukuran grup update) + overhead, yang pada gilirannya harus lebih besar dari atau sama dengan jumlah(ukuran partisi) + overhead.

Untuk Android 13 dan yang lebih baru, untuk mengaktifkan fitur dengan Virtual A/B, mewarisi konfigurasi dasar berikut:

$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_ramdisk.mk)
$(call inherit-product, \
    $(SRC_TARGET_DIR)/product/virtual_ab_ota/android_t_baseline.mk)

Hal ini memungkinkan snapshot ruang pengguna dengan A/B Virtual saat menggunakan pengoperasian tanpa pengoperasian metode kompresi. Anda kemudian dapat mengkonfigurasi metode kompresi ke salah satu metode yang didukung, yaitu gz, zstd, dan lz4.

PRODUCT_VIRTUAL_AB_COMPRESSION_METHOD := lz4

Untuk Android 12, guna mengaktifkan snapshot terkompresi dengan A/B virtual, mewarisi konfigurasi dasar berikut:

$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_ramdisk.mk)
$(call inherit-product, \
    $(SRC_TARGET_DIR)/product/virtual_ab_ota/compression.mk)

Kompresi XOR

Untuk perangkat yang diupgrade ke Android 13 dan yang lebih baru, Fitur kompresi XOR tidak diaktifkan secara default. Untuk mengaktifkan kompresi XOR, tambahkan kode berikut ke metode File .mk.

PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.compression.xor.enabled=true

Kompresi XOR diaktifkan secara default untuk perangkat yang mewarisi android_t_baseline.mk.

Penggabungan userspace

Untuk perangkat yang diupgrade ke Android 13 dan yang lebih baru, proses penggabungan userspace seperti yang dijelaskan di Device-mapper {i>layering<i} tidak diaktifkan oleh secara default. Untuk mengaktifkan penggabungan ruang pengguna, tambahkan baris berikut ke .mk perangkat file:

PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.userspace.snapshots.enabled=true

Penggabungan ruang pengguna diaktifkan secara default pada perangkat yang diluncurkan dengan 13 dan lebih tinggi.

HAL kontrol booting

Kontrol booting HAL menyediakan antarmuka bagi klien OTA untuk mengontrol slot {i>boot<i}. A/B Virtual memerlukan peningkatan versi minor dari HAL kontrol booting karena API tambahan diperlukan untuk memastikan bootloader terlindungi selama melakukan flash atau reset ke setelan pabrik. Lihat IBootControl.hal dan types.hal untuk versi terbaru definisi HAL.

// hardware/interfaces/boot/1.1/types.hal
enum MergeStatus : uint8_t {
    NONE, UNKNOWN, SNAPSHOTTED, MERGING, CANCELLED };

// hardware/interfaces/boot/1.1/IBootControl.hal
package android.hardware.boot@1.1;
interface IBootControl extends @1.0::IBootControl {
    setSnapshotMergeStatus(MergeStatus status)
        generates (bool success);
    getSnapshotMergeStatus()
        generates (MergeStatus status);
}
// Recommended implementation

Return<bool> BootControl::setSnapshotMergeStatus(MergeStatus v) {
    // Write value to persistent storage
    // e.g. misc partition (using libbootloader_message)
    // bootloader rejects wipe when status is SNAPSHOTTED
    // or MERGING
}

Perubahan Fstab

Integritas partisi metadata sangat penting untuk proses {i>boot<i}, terutama tepat setelah pembaruan OTA diterapkan. Jadi, partisi {i>metadata<i} harus diperiksa sebelum first_stage_init memasangnya. Untuk memastikan hal ini terjadi, tambahkan check flag fs_mgr ke entri untuk /metadata. Berikut ini adalah contoh:

/dev/block/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard,sync wait,formattable,first_stage_mount,check

Persyaratan kernel

Untuk mengaktifkan pembuatan snapshot, tetapkan CONFIG_DM_SNAPSHOT ke true.

Untuk perangkat yang menggunakan F2FS, sertakan tanda f2fs: ekspor FS_NOCOW_FL ke patch kernel user untuk memperbaiki penyematan file. Sertakan f2fs: dukungan selaras disematkan patch kernel file.

A/B virtual mengandalkan fitur yang ditambahkan dalam kernel versi 4.3: overflow bit status di target snapshot dan snapshot-merge. Semua perangkat diluncurkan di Android 9 dan yang lebih baru seharusnya sudah memiliki kernel versi 4.4 atau yang lebih baru.

Untuk mengaktifkan snapshot terkompresi, versi kernel minimum yang didukung adalah 4.19. Tetapkan CONFIG_DM_USER=m atau CONFIG_DM_USER=y. Jika menggunakan modul sebelumnya (modul), modul harus dimuat di ramdisk tahap pertama. Hal ini dapat dicapai dengan tambahkan baris berikut ke Makefile perangkat:

BOARD_GENERIC_RAMDISK_KERNEL_MODULES_LOAD := dm-user.ko

Retrofit pada perangkat yang diupgrade ke Android 11

Saat mengupgrade ke Android 11, perangkat yang diluncurkan dengan partisi dinamis dapat untuk retrofit A/B virtual. Sebagian besar proses pembaruan sama dengan untuk perangkat yang diluncurkan dengan A/B virtual, dengan beberapa perbedaan kecil:

  • Lokasi file COW — Untuk perangkat peluncuran, klien OTA menggunakan semua ruang kosong yang tersedia di partisi super sebelum menggunakan ruang di /data. Untuk perangkat retrofit, selalu ada cukup ruang di bagian partisi sehingga file COW tidak pernah dibuat di /data.

  • Tanda fitur waktu build — Untuk perangkat yang retrofit A/B virtual, PRODUCT_VIRTUAL_AB_OTA dan PRODUCT_VIRTUAL_AB_OTA_RETROFIT disetel ke true, seperti yang ditunjukkan di bawah ini:

    (call inherit-product, \
      (SRC_TARGET_DIR)/product/virtual_ab_ota_retrofit.mk)
    
  • Ukuran partisi super — Perangkat yang diluncurkan dengan A/B virtual dapat memotong BOARD_SUPER_PARTITION_SIZE menjadi dua karena slot B tidak berada di super partisi. Perangkat yang retrofit A/B virtual mempertahankan partisi super lama ukuran, jadi BOARD_SUPER_PARTITION_SIZE lebih besar dari atau sama dengan 2 * sum(ukuran grup pembaruan) + overhead, yang kemudian lebih besar dari atau sama dengan 2 * sum(ukuran partisi) + overhead.

Perubahan bootloader

Selama langkah penggabungan update, /data menyimpan satu-satunya instance Android OS. Setelah migrasi dimulai, system, vendor, dan Partisi product tidak lengkap sampai penyalinannya selesai. Jika perangkat dikembalikan ke setelan pabrik selama proses ini, baik melalui pemulihan atau melalui Sistem dialog setelan, maka perangkat tidak akan dapat di-booting.

Sebelum menghapus /data, selesaikan penggabungan dalam pemulihan atau rollback bergantung pada status perangkat:

  • Jika build yang baru berhasil di-booting sebelumnya, selesaikan migrasi.
  • Jika tidak, rollback ke slot lama:
    • Untuk partisi dinamis, roll back ke status sebelumnya.
    • Untuk partisi statis, setel slot aktif ke slot lama.

Bootloader maupun fastbootd dapat menghapus partisi /data jika perangkat tidak terkunci. Meskipun fastbootd dapat memaksa migrasi selesai, bootloader tidak bisa. {i>Bootloader<i} tidak dapat mengetahui apakah ada penggabungan progres, atau blok di /data yang membentuk partisi OS. Perangkat harus mencegah pengguna secara tidak sadar membuat perangkat tidak dapat dioperasikan (bricking) dengan dengan melakukan hal berikut:

  1. Mengimplementasikan HAL kontrol booting sehingga bootloader dapat membaca nilai yang ditetapkan dengan metode setSnapshotMergeStatus().
  2. Jika status penggabungan adalah MERGING, atau jika status penggabungan adalah SNAPSHOTTED dan slot telah berubah ke slot yang baru diperbarui, kemudian meminta untuk menghapus userdata, metadata, atau partisi yang menyimpan status penggabungan harus ditolak di {i>bootloader<i}.
  3. Terapkan perintah fastboot snapshot-update cancel sehingga pengguna dapat memberi sinyal ke {i>bootloader<i} bahwa mereka ingin melewati mekanisme perlindungan ini.
  4. Ubah skrip atau alat flash kustom untuk mengeluarkan fastboot snapshot-update cancel saat melakukan flash seluruh perangkat. Ini aman untuk masalah karena mem-flash seluruh perangkat akan menghapus OTA. Alat dapat mendeteksi perintah ini pada runtime dengan menerapkan fastboot getvar snapshot-update-status. Ini membantu membedakan antara kondisi {i>error<i}.

Contoh

struct VirtualAbState {
    uint8_t StructVersion;
    uint8_t MergeStatus;
    uint8_t SourceSlot;
};

bool ShouldPreventUserdataWipe() {
    VirtualAbState state;
    if (!ReadVirtualAbState(&state)) ...
    return state.MergeStatus == MergeStatus::MERGING ||
           (state.MergeStatus == MergeStatus::SNAPSHOTTED &&
            state.SourceSlot != CurrentSlot()));
}

Perubahan alat fastboot

Android 11 membuat perubahan berikut pada fastboot protokol:

  • getvar snapshot-update-status — Menampilkan nilai yang diperlukan kontrol HAL yang dikomunikasikan ke bootloader:
    • Jika statusnya adalah MERGING, bootloader harus menampilkan merging.
    • Jika statusnya adalah SNAPSHOTTED, bootloader harus menampilkan snapshotted.
    • Jika tidak, bootloader harus menampilkan none.
  • snapshot-update merge — Menyelesaikan operasi penggabungan, melakukan booting ke pemulihan/Fastbootd jika perlu. Perintah ini hanya valid jika snapshot-update-status adalah merging, dan hanya didukung dalam mode fastbooting.
  • snapshot-update cancel — Menetapkan status penggabungan HAL kontrol booting ke CANCELLED. Perintah ini tidak valid saat perangkat terkunci.
  • erase atau wipeerase atau wipe dari metadata, userdata, atau partisi yang menyimpan status penggabungan untuk HAL kontrol {i>boot<i} harus diperiksa status penggabungan snapshot. Jika statusnya adalah MERGING atau SNAPSHOTTED, perangkat akan membatalkan operasi.
  • set_active — Perintah set_active yang mengubah slot aktif harus memeriksa status penggabungan snapshot. Jika statusnya adalah MERGING, perangkat akan membatalkan operasi. Slot dapat diubah dengan aman di status SNAPSHOTTED.

Perubahan ini dirancang untuk mencegah secara tidak sengaja membuat perangkat tidak bisa di-{i>boot<i}, tetapi dapat mengganggu alat otomatis. Ketika perintah digunakan sebagai mem-flash semua partisi, seperti menjalankan fastboot flashall, akan diperlukan disarankan untuk menggunakan alur berikut:

  1. Kueri getvar snapshot-update-status.
  2. Jika merging atau snapshotted, terbitkan snapshot-update cancel.
  3. Lanjutkan dengan melakukan flash.

Mengurangi persyaratan penyimpanan

Perangkat yang tidak memiliki penyimpanan A/B penuh yang dialokasikan di super, dan mengharapkan untuk menggunakan /data seperlunya, sangat disarankan untuk menggunakan pemetaan blok menyediakan alat command line gcloud. Alat pemetaan blok menjaga alokasi blok tetap konsisten di antara build, mengurangi penulisan yang tidak perlu pada snapshot. Hal ini didokumentasikan dalam Mengurangi Ukuran OTA.

Metode kompresi OTA

Paket OTA dapat disesuaikan untuk metrik performa yang berbeda. Android menyediakan beberapa metode kompresi yang didukung (gz, lz4, zstd, dan none) yang memiliki konsekuensi antara waktu penginstalan, penggunaan ruang COW, waktu booting, dan snapshot waktu penggabungan. Opsi default yang diaktifkan untuk ab virtual dengan kompresi adalah gz compression method. (Catatan: performa relatif antarmetode kompresi bervariasi tergantung pada kecepatan CPU dan throughput penyimpanan yang dapat berubah tergantung di perangkat. Semua paket OTA yang dihasilkan di bawah ini adalah dengan PostInstall dinonaktifkan, yang akan sedikit memperlambat waktu {i>booting<i}. Total ukuran partisi dinamis ota penuh tanpa kompresi adalah 4,81 GB).

OTA inkremental di Pixel 6 Pro

Waktu penginstalan tanpa fase pasca-penginstalan Penggunaan ruang COW Posting waktu booting OTA Waktu penggabungan snapshot
gz 24 mnt 1,18 GB 40,2 dtk 45,5 dtk
lz4 13 mnt 1,49 GB 37,4 dtk 37,1 dtk
none 13 mnt 2,90 GB 37,6 dtk 40,7 dtk

OTA penuh di Pixel 6 Pro

Waktu penginstalan tanpa fase pasca-penginstalan Penggunaan Ruang COW Posting waktu booting OTA Waktu penggabungan snapshot
gz 23 menit 2,79 GB 24,9 dtk 41,7 dtk
lz4 12 mnt 3,46 GB 20,0 dtk 25,3 dtk
none 10 mnt 4,85 GB 20,6 dtk 29,8 dtk