Виртуальный A/B — это основной механизм обновления Android. Виртуальный A/B основан на устаревших обновлениях A/B (см. Системные обновления A/B ) и обновлениях, не использующих A/B, которые были устарели в версии 15 для уменьшения объема занимаемого места при обновлениях.
В режиме Virtual A/B фактически нет дополнительного слота для динамических разделов (см. раздел «Динамические разделы») . Вместо этого дельта-изменение записывается в снимок, а затем объединяется с базовым разделом после подтверждения успешной загрузки. Virtual A/B использует формат снимков, специфичный для Android. См. формат COW для сжатых снимков , который позволяет сжимать снимки и минимизировать использование дискового пространства. При полной OTA-обновлении размер снимка уменьшается примерно на 45% за счет сжатия, а размер инкрементального OTA-снимка уменьшается примерно на 55%.
В Android 12 доступна опция виртуального A/B-сжатия для сжатия разделов, созданных на основе снимков. Виртуальное A/B-сжатие предлагает следующие возможности:
- Виртуальные A/B-обновления выполняются незаметно (обновление происходит полностью в фоновом режиме, пока устройство работает), как и обычные A/B-обновления. Виртуальные A/B-обновления минимизируют время, в течение которого устройство находится в автономном режиме и не может быть использовано.
- Виртуальные обновления A/B можно откатить . Если новая ОС не загружается, устройства автоматически откатываются к предыдущей версии.
- Виртуальные обновления A/B используют минимум дополнительного места , дублируя только те разделы, которые используются загрузчиком. Другие обновляемые разделы сохраняются в виде снимков .
Предпосылки и терминология
В этом разделе определяется терминология и описывается технология, поддерживающая виртуальное A/B-тестирование. Во время OTA-установки новые данные операционной системы записываются либо в новый слот для физических разделов, либо на устройство COW, специфичное для Android. После перезагрузки устройства данные динамических разделов объединяются обратно в базовое устройство с помощью демонов dm-user и snapuserd. Этот процесс происходит полностью в пользовательском пространстве.
Device-mapper
Device-mapper — это виртуальный блочный слой Linux, часто используемый в Android. При использовании динамических разделов , такие разделы, как /system представляют собой стек многоуровневых устройств:
- At the bottom of the stack is the physical super partition (for example,
/dev/block/by-name/super). - В центре находится
dm-linear, указывающее, какие блоки в суперразделе образуют данный динамический раздел. На устройстве A/B это отображается как/dev/block/mapper/system_[a|b], а на устройстве без A/B — как/dev/block/mapper/system. - В самом верху находится устройство
dm-verity, созданное для проверки разделов. Это устройство проверяет правильность подписи блоков на устройствеdm-linear. Оно отображается как/dev/block/mapper/system-verityи является источником точки монтирования/system.
Figure 1 shows what the stack under the /system mount point looks like.

Figure 1. Stack under the /system mount point
Сжатые снимки
В Android 12 и более поздних версиях, поскольку требования к объему памяти в разделе /data могут быть высокими, вы можете включить сжатые снимки в своей сборке, чтобы решить проблему повышенных требований к объему памяти в разделе /data .
Virtual A/B compressed snapshots are built on top of the following components that are available in Android 12 and higher:
-
dm-user— модуль ядра, аналогичный FUSE, который позволяет пользовательскому пространству реализовывать блочные устройства. -
snapuserd, a userspace daemon to implement a new snapshot format.
Эти компоненты обеспечивают сжатие. Другие необходимые изменения, внесенные для реализации возможностей сжатых снимков, описаны в следующих разделах: формат COW для сжатых снимков , dm-user и snapuserd .
COW format for compressed snapshots
В Android 12 и более поздних версиях сжатые снимки используют специфический для Android формат COW. Формат COW содержит метаданные об обновлении по воздуху (OTA) и имеет отдельные буферы, содержащие операции COW и новые данные операционной системы. По сравнению с форматом снимков ядра, который допускал только операции замены (замена блока X в базовом образе содержимым блока Y в снимке), формат COW сжатых снимков Android является более выразительным и поддерживает следующие операции:
- Copy : Block X in the base device should be replaced with block Y in the base device.
- Replace : Block X in the base device should be replaced with the contents of block Y in the snapshot. Each of these blocks is gz compressed.
- Zero : Block X in the base device should be replaced with all zeroes.
- XOR : The COW device stores XOR compressed bytes between block X and block Y . (Available in Android 13 and higher.)
Полные обновления по воздуху (OTA) включают только операции замены и обнуления . Инкрементальные обновления по воздуху (OTA) могут дополнительно включать операции копирования .
The full snapshot layout on disk looks like this:

Рисунок 2. Форматирование Android COW на диске.
dm-user
Модуль ядра dm-user позволяет userspace реализовывать блочные устройства device-mapper. Запись в таблице dm-user создает устройство типа miscellaneous в каталоге /dev/dm-user/<control-name> . Процесс userspace может опрашивать устройство для получения запросов на чтение и запись от ядра. Каждый запрос имеет связанный с ним буфер, который пользовательское пространство может либо заполнить (для чтения), либо распространить (для записи).
Модуль ядра dm-user предоставляет новый видимый пользователю интерфейс для ядра, который не является частью исходной кодовой базы kernel.org. До тех пор, пока он не будет включен в нее, Google оставляет за собой право изменять интерфейс dm-user в Android.
snapuserd
Компонент пользовательского пространства snapuserd для dm-user реализует виртуальное A/B-сжатие. Snapuserd — это демон пользовательского пространства, отвечающий за запись и чтение данных с устройств Android COW. Все операции ввода-вывода со снимком должны проходить через этот сервис. Во время OTA-установки новые данные операционной системы записываются в снимок с помощью snapuserd (с сжатием). Здесь же обрабатывается анализ метаданных и распаковка новых блочных данных.
XOR compression
Для устройств, выпущенных с Android 13 и выше, функция сжатия XOR, включенная по умолчанию, позволяет сохранять в снимках пользовательского пространства сжатые по XOR байты между старыми и новыми блоками. Когда в виртуальном обновлении A/B изменяется всего несколько байтов в блоке, схема хранения сжатых по XOR байтов занимает меньше места, чем схема хранения по умолчанию, поскольку снимки не хранят полные 4 КБ. Такое уменьшение размера снимка возможно благодаря тому, что данные XOR содержат много нулей и их проще сжимать, чем необработанные данные блока. На устройствах Pixel сжатие XOR уменьшает размер снимка на 25–40%.
For devices upgrading to Android 13 and higher, XOR compression must be enabled. For details, see XOR compression .
Snapshot merge
Для устройств, запускаемых с Android 13 и выше, процессы создания и слияния снимков в режиме виртуального A/B-сжатия выполняются компонентом пользовательского пространства snapuserd . Для устройств, обновляемых до Android 13 и выше, эту функцию необходимо включить. Подробности см. в разделе «Слияние пользовательского пространства» .
The following describes the Virtual A/B compression process:
- The framework mounts the
/systempartition off of adm-veritydevice, which is stacked on top of adm-userdevice. This means that every I/O from the root file system is routed todm-user. -
dm-userroutes the I/O to the userspacesnapuserddaemon, which handles the I/O request. - When the merge operation is complete, the framework collapses
dm-verityon top ofdm-linear(system_base) and removesdm-user.

Рисунок 3. Виртуальный процесс A/B-сжатия.
The snapshot merge process can be interrupted. If the device is rebooted during the merge process, the merge process resumes after reboot.
Init transitions
При загрузке со сжатыми снимками, на первом этапе инициализации необходимо запустить snapuserd для монтирования разделов. Это создает проблему: когда загружается и применяется sepolicy , snapuserd оказывается в неправильном контексте, и его запросы на чтение завершаются с ошибкой SELinux.
To address this, snapuserd transitions in lock-step with init , as follows:
- First-stage
initlaunchessnapuserdfrom the ramdisk, and saves an open file-descriptor to it in an environment variable. - First-stage
initswitches the root filesystem to the system partition, then executes the system copy ofinit. - The system copy of
initreads the combined sepolicy into a string. -
Initвызываетmlock()для всех страниц, использующих файловую систему ext4. Затем он деактивирует все таблицы device-mapper для устройств, созданных на основе снимков, и останавливаетsnapuserd. После этого чтение из разделов запрещается, поскольку это приводит к взаимоблокировке. - Using the open descriptor to the ramdisk copy of
snapuserd,initrelaunches the daemon with the correct selinux context. Device-mapper tables for snapshot devices are re-activated. - Init invokes
munlockall()- it's safe to perform IO again.
Использование пространства
The following table provides a comparison of space usage for different OTA mechanisms using Pixel's OS and OTA sizes.
| Влияние размера | не-А/В | А/Б | Виртуальный A/B | Virtual A/B (compressed) |
|---|---|---|---|---|
| Оригинальное заводское изображение | 4,5 ГБ супер (3,8 ГБ изображения + 700 МБ зарезервировано) 1 | 9 ГБ Super (3,8 ГБ + 700 МБ зарезервировано, для двух слотов) | 4,5 ГБ супер (3,8 ГБ изображения + 700 МБ зарезервировано) | 4.5GB super (3.8G image + 700M reserved) |
| Другие статические разделы | /кэш | Никто | Никто | Никто |
| Additional storage During OTA (space returned after applying OTA) | 1,4 ГБ на /data | 0 | 3,8 ГБ 2 на /данные | 2.1GB 2 on /data |
| Total storage required to apply OTA | 5,9 ГБ 3 (супер и данные) | 9GB (super) | 8,3 ГБ 3 (супер и данные) | 6.6GB 3 (super and data) |
1 Indicates assumed layout based on Pixel mapping.
2 Assumes new system image is the same size as original.
3. Требование к объему памяти носит временный характер и действует до перезагрузки.
Android 11 Виртуальный A/B
The android 11 of Virtual A/B wrote to dynamic partition using the Kernel COW format. This was eventually deprecated as the Kernel COW format does not support compression.
Android 12 Virtual A/B
В Android 12 сжатие поддерживалось в виде специфичного для Android формата COW. Эта версия Virtual A/B требовала преобразования специфичного для Android формата COW в формат COW ядра. Впоследствии это было заменено в Android 13, что устранило зависимость от формата COW ядра, а также dm-snapshot .
To implement Virtual A/B, or to use compressed snapshot capabilities, see Implementing Virtual A/B