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