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
.
Рисунок 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 могут дополнительно иметь операции копирования .
Полная структура снимка на диске выглядит следующим образом:
Рисунок 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:
- Фреймворк монтирует раздел
/system
из устройстваdm-verity
, которое размещается поверх устройстваdm-user
. Это означает, что каждый ввод/вывод из корневой файловой системы направляется вdm-user
. -
dm-user
направляет ввод-вывод демонуsnapuserd
пользовательского пространства, который обрабатывает запрос ввода-вывода. - После завершения операции слияния фреймворк сворачивает
dm-verity
поверхdm-linear
(system_base
) и удаляетdm-user
.
Рисунок 3. Процесс виртуального сжатия A/B
Процесс слияния снимков может быть прерван. Если устройство перезагрузится во время процесса слияния, процесс слияния возобновится после перезагрузки.
Инициализация переходов
При загрузке с использованием сжатых снимков первый этап init должен запустить snapuserd
для монтирования разделов. Это создает проблему: когда sepolicy
загружается и применяется, snapuserd
попадает в неправильный контекст, и его запросы на чтение терпят неудачу с отказами selinux.
Чтобы решить эту проблему, snapuserd
выполняет переходы синхронно с init
следующим образом:
- На первом этапе
init
запускаетsnapuserd
с ramdisk и сохраняет открытый файловый дескриптор в переменной среды. - На первом этапе
init
переключает корневую файловую систему на системный раздел, а затем выполняет системную копиюinit
. - Системная копия
init
считывает объединенную sepolicy в строку. -
Init
вызываетmlock()
на всех страницах, поддерживаемых ext4. Затем он деактивирует все таблицы device-mapper для устройств моментальных снимков и останавливаетsnapuserd
. После этого запрещается читать из разделов, так как это приводит к взаимоблокировке. - Используя открытый дескриптор для копии ramdisk
snapuserd
,init
перезапускает демон с правильным контекстом selinux. Таблицы Device-mapper для устройств моментального снимка повторно активируются. - 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.