Как реализовать виртуальное A/B-обновление

Чтобы реализовать виртуальные A/B-обновления на новом устройстве или модернизировать запущенное устройство, необходимо внести изменения в код, зависящий от устройства.

Как создавать пометки

Устройства, использующие виртуальные разделы A/B, должны быть настроены как устройства A/B и запускаться с динамическими разделами.

Для устройств с виртуальной системой A/B задайте наследование базовой конфигурации виртуальной системы A/B:

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

Устройствам, которые выпускаются с виртуальными A/B-разделами, требуется вдвое меньше места на плате для BOARD_SUPER_PARTITION_SIZE, поскольку слоты B больше не находятся в суперразделе. То есть BOARD_SUPER_PARTITION_SIZE должно быть больше или равно sum(size of update groups) + overhead, которое, в свою очередь, должно быть больше или равно sum(size of partitions) + overhead.

Чтобы включить сжатые снимки с Virtual A/B на устройствах с Android 13 и более поздних версий, наследуйте следующую базовую конфигурацию:

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

Это позволяет создавать снимки пользовательского пространства с помощью Virtual A/B, используя метод сжатия no-op. Затем вы можете настроить метод сжатия на один из поддерживаемых методов,zstd и lz4. В Android 15 сжатие можно настроить в соответствии с потребностями устройства. Дополнительную информацию можно найти в разделе Настройка сжатия.

PRODUCT_VIRTUAL_AB_COMPRESSION_METHOD := lz4
PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR := 65536

Чтобы включить сжатые снимки с Virtual A/B в Android 12, наследуйте следующую базовую конфигурацию:

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

Сжатие XOR

На устройствах, на которых установлена ОС Android 13 или более поздняя версия, сжатие XOR по умолчанию отключено. Чтобы включить сжатие XOR, добавьте в файл .mk устройства следующие строки:

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

Сжатие XOR включено по умолчанию для устройств, которые наследуют настройки от android_t_baseline.mk.

Объединение пространств пользователей

В современной версии Virtual A/B (Android T и более поздних версиях) процесс объединения снимков происходит полностью в пространстве пользователя. Это изменение стало возможным благодаря snapuserd и dm-user. На устройствах с Android 13 и более поздних версий слияние пользовательского пространства включено по умолчанию. На более старых устройствах, которые были обновлены до Android 13 или более поздней версии, это свойство можно задать с помощью следующей команды:

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

HAL управления загрузкой

HAL управления загрузкой предоставляет клиентам OTA интерфейс для управления слотами загрузки. Для виртуального раздела A/B требуется обновить второстепенную версию HAL управления загрузкой, поскольку для защиты загрузчика во время прошивки или сброса настроек до заводских значений нужны дополнительные API. Последнюю версию определения HAL можно найти в файлах IBootControl.hal и types.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
}

Изменения в fstab

Целостность раздела метаданных имеет важное значение для процесса загрузки, особенно сразу после применения беспроводного обновления. Поэтому раздел метаданных должен быть проверен до того, как first_stage_init смонтирует его. Чтобы это произошло, добавьте флаг fs_mgr в запись для /metadata.check Пример:

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

Требования к ядру

Чтобы включить создание снимков, установите для параметра CONFIG_DM_SNAPSHOT значение true.

Для устройств, использующих F2FS, добавьте флаг f2fs: export FS_NOCOW_FL flag to user в патч ядра, чтобы исправить закрепление файлов. Также добавьте патч ядра f2fs: support aligned pinned file.

Для работы Virtual A/B требуются функции, добавленные в ядро версии 4.3: бит статуса overflow в целевых объектах snapshot и snapshot-merge. На всех устройствах с Android 9 и более поздних версий должна быть установлена версия ядра 4.4 или более поздняя.

Чтобы включить сжатые снимки, требуется ядро версии не ниже 4.19. Задайте значение CONFIG_DM_USER=m или CONFIG_DM_USER=y. Если вы используете модуль, он должен быть загружен в RAM-диск первого этапа. Для этого добавьте в файл Makefile устройства следующую строку:

BOARD_GENERIC_RAMDISK_KERNEL_MODULES_LOAD := dm-user.ko

Изменения в инструментах Fastboot

В Android 11 в протокол fastboot внесены следующие изменения:

  • getvar snapshot-update-status – возвращает значение, которое HAL bootcontrol передал загрузчику:
    • Если состояние равно MERGING, загрузчик должен вернуть значение merging.
    • Если состояние равно SNAPSHOTTED, загрузчик должен вернуть значение snapshotted.
    • В противном случае загрузчик должен вернуть значение none.
  • snapshot-update merge – завершает операцию слияния, при необходимости загружая recovery/fastbootd. Эта команда действительна, только если для snapshot-update-status задано значение merging, и поддерживается только в fastbootd.
  • snapshot-update cancel – устанавливает статус объединения HAL управления загрузкой на CANCELLED. Эта команда недействительна, когда устройство заблокировано.
  • erase или wipe – erase или wipe из metadata, userdata или раздела, в котором хранится статус слияния для HAL управления загрузкой, должны проверять статус слияния снимка. Если статус MERGING или SNAPSHOTTED, устройство должно прервать операцию.
  • set_active – команда set_active, которая меняет активный слот. Она должна проверять статус объединения снимков. Если статус MERGING, устройство должно прервать операцию. Слот можно безопасно изменить в состоянии SNAPSHOTTED.

Эти изменения призваны предотвратить случайное повреждение устройства, из-за которого оно не сможет загружаться, но могут нарушить работу автоматизированных инструментов. Если команды используются как компонент прошивки всех разделов, например при запуске fastboot flashall, рекомендуется использовать следующую последовательность:

  1. Запрос getvar snapshot-update-status.
  2. Если merging или snapshotted, выдать snapshot-update cancel.
  3. Перейдите к шагам по прошивке.

Как уменьшить требования к хранилищу

Если на устройстве нет полного хранилища A/B, выделенного в super, и при необходимости планируется использовать /data, настоятельно рекомендуется использовать инструмент сопоставления блоков. Инструмент сопоставления блоков обеспечивает согласованность распределения блоков между сборками, сокращая количество ненужных записей в снимок. Подробнее о том, как уменьшить размер OTA-обновления…

Алгоритмы сжатия OTA

Пакеты OTA можно настроить для разных показателей эффективности. Android поддерживает несколько методов сжатия (lz4, zstd и none), которые по-разному влияют на время установки, использование пространства COW, время загрузки и время объединения снимков. По умолчанию для виртуального АБ с компрессией включен вариант lz4 compression method.

Настройка сжатия

Алгоритмы сжатия можно дополнительно настраивать двумя способами: с помощью уровня сжатия (объем сжатия, достигаемый за счет скорости) и коэффициента сжатия (максимальный размер сжимаемого окна). Уровень сжатия доступен для некоторых алгоритмов, например zstd. Изменение уровня влияет на скорость и коэффициент сжатия. Коэффициент сжатия описывает максимальный размер окна сжатия, используемый во время установки по беспроводной сети. По умолчанию задано значение 64 000, но его можно переопределить, изменив параметр сборки PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR. Поддерживаемые коэффициенты сжатия: 4K, 8K, 16K, 32K, 64K, 128K и 256K.

PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR := 65536

Дополнительное беспроводное обновление на Pixel 8 Pro

Время установки без этапа после установки Использование пространства COW Время загрузки после беспроводного обновления Время объединения снимков
lz4 18 мин. 15 сек. 2,5 ГБ 32,7 сек. 98,6 сек.
zstd 24 мин. 49 сек. 2,05 ГБ 36,3 сек. 133,2 сек.
Нет 16 мин. 42 с 4,76 ГБ 28,7 сек. 76,6 сек.

Полный OTA-образ для Pixel 8 Pro

Время установки без этапа после установки Использование пространства COW Время загрузки после беспроводного обновления Время объединения снимков
lz4 15 мин. 11 с 4,16 ГБ 17,6 сек. 82,2 сек.
zstd 16 мин. 19 сек. 3,46 ГБ 21,0 сек. 106,3 сек.
Нет 13 мин. 33 сек. 6,39 ГБ 18,5 сек. 92,5 сек.