Обзор виртуального A/B

Virtual 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 предлагает возможность сжатия Virtual A/B для сжатия разделов моментальных снимков. Virtual A/B предлагает следующее

  • Виртуальные обновления A/B являются бесшовными (обновление происходит полностью в фоновом режиме, пока устройство работает), как и обновления A/B. Виртуальные обновления A/B минимизируют время, в течение которого устройство находится в автономном режиме и становится непригодным для использования.
  • Виртуальные обновления A/B можно откатить . Если новая ОС не загружается, устройства автоматически откатываются к предыдущей версии.
  • Виртуальные обновления A/B используют минимум дополнительного пространства, дублируя только те разделы, которые используются загрузчиком. Другие обновляемые разделы создаются в виде снимков .

Предыстория и терминология

В этом разделе определяется терминология и описывается технология, поддерживающая виртуальный A/B. Во время установки OTA новые данные операционной системы записываются либо в новый слот для физических разделов, либо в специальное COW-устройство Android. После перезагрузки устройства данные динамического раздела объединяются обратно в базовое устройство с помощью dm-user и демона snapuserd. Этот процесс происходит полностью в пользовательском пространстве.

Устройство-сопоставитель

Device-mapper — это уровень виртуальных блоков Linux, часто используемый в Android. При использовании динамических разделов такие разделы, как /system представляют собой стек многоуровневых устройств:

  • В нижней части стека находится физический суперраздел (например, /dev/block/by-name/super ).
  • В середине находится dm-linear устройство, определяющее, какие блоки суперраздела образуют данный динамический раздел. Это выглядит как /dev/block/mapper/system_[a|b] на устройстве A/B или /dev/block/mapper/system на устройстве, отличном от A/B.
  • Вверху находится устройство dm-verity , созданное для проверенных разделов. Это устройство проверяет правильность подписи блоков на устройстве dm-linear . Он выглядит как /dev/block/mapper/system-verity и является источником точки монтирования /system .

На рис. 1 показано, как выглядит стек под точкой монтирования /system .

Partition stacking underneath
system

Рис. 1. Стек под точкой монтирования /system

Сжатые снимки

В Android 12 и более поздних версиях, поскольку требования к пространству в разделе /data могут быть высокими, вы можете включить в сборке сжатые снимки, чтобы удовлетворить более высокие требования к пространству раздела /data .

Снимки со сжатием Virtual A/B создаются на основе следующих компонентов, доступных в Android 12 и более поздних версиях:

  • dm-user — модуль ядра, аналогичный FUSE, который позволяет пользовательскому пространству реализовывать блочные устройства.
  • snapuserd — демон пользовательского пространства для реализации нового формата моментальных снимков.

Эти компоненты обеспечивают сжатие. Другие необходимые изменения, внесенные для реализации возможностей сжатых снимков, приведены в следующих разделах: формат COW для сжатых снимков , dm-user и snapuserd .

Формат COW для сжатых снимков

В Android 12 и более поздних версиях сжатые снимки используют формат COW, специфичный для Android. Формат COW содержит метаданные об OTA и имеет отдельные буферы, содержащие операции COW и данные новой операционной системы. По сравнению с форматом снимка ядра, который допускал только операции замены (заменить блок X в базовом образе содержимым блока Y в снимке), формат COW сжатых снимков Android более выразителен и поддерживает следующие операции:

  • Копировать : Блок X в базовом устройстве должен быть заменен блоком Y в базовом устройстве.
  • Заменить : блок X в базовом устройстве должен быть заменен содержимым блока Y в снимке. Каждый из этих блоков сжат gz.
  • Ноль : блок X в базовом устройстве должен быть заменен всеми нулями.
  • XOR : Устройство COW сохраняет байты, сжатые XOR, между блоком X и блоком Y. (Доступно в Android 13 и более поздних версиях.)

Полные обновления OTA состоят только из операций замены и нуля . Дополнительные обновления OTA могут дополнительно содержать операции копирования .

Полный макет снимка на диске выглядит так:

cow format

Рис. 2. Формат Android COW на диске

пользователь dm

Модуль ядра dm-user позволяет userspace реализовывать блочные устройства устройства-сопоставителя. Запись таблицы dm-user создает другое устройство в /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-сжатие

Для устройств, запускаемых с Android 13 и более поздних версий, функция сжатия XOR, которая включена по умолчанию, позволяет снимкам пользовательского пространства хранить байты, сжатые XOR, между старыми и новыми блоками. Когда при обновлении Virtual A/B изменяются только несколько байтов в блоке, схема хранения со сжатием XOR использует меньше места, чем схема хранения по умолчанию, поскольку моментальные снимки не хранят полные 4 КБ. Такое уменьшение размера моментального снимка возможно, поскольку данные XOR содержат много нулей и их легче сжимать, чем необработанные блочные данные. На устройствах Pixel сжатие XOR уменьшает размер снимка на 25–40 %.

Для устройств, обновляющихся до Android 13 и выше, необходимо включить сжатие XOR. Подробности см. в разделе Сжатие XOR .

Объединение снимков

Для устройств, запускаемых с Android 13 и более поздних версий, процессы снимка и слияния снимков при виртуальном A/B-сжатии выполняются компонентом пользовательского пространства snapuserd . Для устройств, обновляющихся до Android 13 и выше, эта функция должна быть включена. Подробности см. в разделе «Слияние пользовательского пространства» .

Ниже описан процесс сжатия Virtual A/B:

  1. Платформа монтирует раздел /system устройства dm-verity , которое устанавливается поверх устройства dm-user . Это означает, что каждый ввод-вывод из корневой файловой системы направляется на dm-user .
  2. dm-user направляет ввод-вывод демону snapuserd пользовательского пространства, который обрабатывает запрос ввода-вывода.
  3. Когда операция слияния завершена, платформа сворачивает dm-verity поверх dm-linear ( system_base ) и удаляет dm-user .

Процесс виртуального сжатия A/B

Рисунок 3. Процесс виртуального A/B-сжатия

Процесс слияния снимков можно прервать. Если устройство перезагружается во время процесса слияния, процесс слияния возобновляется после перезагрузки.

Инициализация переходов

При загрузке со сжатыми снимками программа инициализации первого этапа должна запустить snapuserd для монтирования разделов. Это создает проблему: когда sepolicy загружается и применяется, snapuserd помещается в неправильный контекст, и его запросы на чтение завершаются неудачно с отказом selinux.

Чтобы решить эту проблему, переходы snapuserd синхронизируются с init следующим образом:

  1. Первый этап init запускает snapuserd с виртуального диска и сохраняет к нему открытый файловый дескриптор в переменной среды.
  2. Первый этап init переключает корневую файловую систему на системный раздел, затем выполняет системную копию init .
  3. Системная копия init считывает объединенную политику sepolicy в строку.
  4. Init вызывает mlock() на всех страницах, поддерживаемых ext4. Затем он деактивирует все таблицы сопоставителей устройств для устройств моментальных снимков и останавливает snapuserd . После этого чтение из разделов запрещено, так как это приводит к взаимоблокировке.
  5. Используя открытый дескриптор копии snapuserd на виртуальном диске, init перезапускает демон с правильным контекстом selinux. Таблицы сопоставления устройств для устройств моментальных снимков повторно активируются.
  6. Init вызывает munlockall() — можно безопасно снова выполнить ввод-вывод.

Использование пространства

В следующей таблице представлено сравнение использования пространства для различных механизмов OTA с использованием ОС Pixel и размеров OTA.

Влияние размера не А/Б А/Б Виртуальный А/Б Виртуальный A/B (сжатый)
Исходное заводское изображение 4,5 ГБ супер (3,8 ГБ образа + 700 МБ зарезервировано) 1 9ГБ супер (3,8Г + 700М зарезервировано, на два слота) 4,5 ГБ супер (изображение 3,8 ГБ + зарезервировано 700 МБ) 4,5 ГБ супер (изображение 3,8 ГБ + зарезервировано 700 МБ)
Другие статические разделы /кэш Никто Никто Никто
Дополнительное хранилище во время OTA (пространство возвращается после применения OTA) 1,4 ГБ в /data 0 3,8 ГБ 2 в /data 2,1 ГБ 2 в /data
Общий объем хранилища, необходимый для применения OTA 5,9 ГБ 3 (супер и данные) 9 ГБ (супер) 8,3 ГБ 3 (супер и данные) 6,6 ГБ 3 (супер и данные)

1 Указывает предполагаемую компоновку, основанную на сопоставлении пикселей.

2 Предполагается, что новый образ системы имеет тот же размер, что и исходный.

3 Требование к пространству является временным до перезагрузки.

Android 11 Виртуальный A/B

Android 11 Virtual A/B записывал в динамический раздел, используя формат Kernel COW. В конечном итоге это было признано устаревшим, поскольку формат Kernel COW не поддерживает сжатие.

Android 12 Виртуальный A/B

В Android 12 поддерживается сжатие в виде формата COW, специфичного для Android. Эта версия Virtual A/B требовала перевода COW, специфичного для Android, в формат Kernel COW. В конце концов это было заменено в Android 13, что устранило зависимость от формата Kernel COW, а также dm-snapshot .

Чтобы реализовать Virtual A/B или использовать возможности сжатых снимков, см. раздел «Реализация Virtual A/B».