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

Virtual A/B — это основной механизм обновления Android. Virtual A/B строится поверх устаревших обновлений A/B (см. Обновления системы A/B ) и non-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 .

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

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

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

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

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

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

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

Полная структура снимка на диске выглядит следующим образом:

cow format

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

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

Модуль ядра dm-user позволяет userspace реализовывать блочные устройства device-mapper. Запись таблицы dm-user создает разное устройство в /dev/dm-user/<control-name> . Процесс userspace может опрашивать устройство для получения запросов на чтение и запись от ядра. Каждый запрос имеет связанный буфер для пользовательского пространства, который можно либо заполнить (для чтения), либо распространить (для записи).

Модуль ядра dm-user предоставляет новый видимый пользователю интерфейс для ядра, который не является частью кодовой базы upstream kernel.org. Пока это не так, Google оставляет за собой право изменять интерфейс dm-user в Android.

snapuserd

Компонент пользовательского пространства snapuserd для dm-user реализует сжатие Virtual 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 и выше, процессы снимка и слияния снимков в сжатии Virtual A/B выполняются компонентом пользовательского пространства snapuserd . Для устройств, обновляющихся до Android 13 и выше, эта функция должна быть включена. Подробности см. в разделе Слияние пользовательского пространства .

Ниже описывается процесс виртуального сжатия 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

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

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

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

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

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

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

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

Размер воздействия не-A/B А/Б Виртуальный А/Б Виртуальный 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 сжатие поддерживается в форме специфичного для android формата COW. Эта версия Virtual A/B требовала перевода специфичного для android формата COW в формат Kernel COW. В конечном итоге это было заменено в android 13, что устранило зависимость от формата Kernel COW, а также dm-snapshot .

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