Virtual A/B – основной механизм обновления Android. Виртуальные A/B-обновления основаны на A/B-обновлениях системы и обновлениях, не связанных с A/B, которые больше не поддерживаются в Android 15, чтобы уменьшить объем памяти, необходимый для обновлений.
В виртуальной системе A/B нет дополнительного слота для динамических разделов. Подробнее о динамических разделах… Вместо этого разница записывается в снимок, а затем объединяется с базовым разделом после подтверждения успешной загрузки. В Virtual A/B используется формат снимков, характерный для Android. Подробнее о формате COW для сжатых моментальных снимков, который позволяет сжимать моментальные снимки и минимизирует использование места на диске. При полном обновлении размер снимка уменьшается примерно на 45 %, а при частичном – на 55%.
В Android 12 можно использовать виртуальное сжатие A/B для сжатия разделов, созданных на основе моментальных снимков. Виртуальное A/B-тестирование позволяет:
- Виртуальные обновления A/B не мешают работе (обновление выполняется в фоновом режиме, пока устройство работает), как и обновления A/B. Виртуальные обновления A/B сокращают время, в течение которого устройство находится в офлайн-режиме и недоступно.
- Обновления Virtual A/B можно откатить. Если новая ОС не загружается, устройства автоматически возвращаются к предыдущей версии.
- При виртуальном обновлении A/B используется минимальный объем дополнительного пространства, поскольку дублируются только разделы, используемые загрузчиком. Для других обновляемых разделов создаются снимки.
Общие сведения и терминология
В этом разделе приведены определения терминов и описана технология, лежащая в основе виртуального тестирования A/B. Во время установки беспроводного обновления новые данные операционной системы записываются либо в новый слот для физических разделов, либо на устройство COW, предназначенное для Android. После перезагрузки устройства данные динамического раздела объединяются с базовым устройством с помощью dm-user и демона snapuserd. Этот процесс выполняется полностью в пространстве пользователя.
Device-mapper
Device-mapper – это виртуальный блочный уровень Linux, который часто используется в Android. Динамические разделы, такие как /system, представляют собой стопку устройств, расположенных слоями:
- Внизу стека находится физический раздел super (например,
/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.
На рисунке 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 и новые данные операционной системы. По сравнению с форматом снимков ядра, который позволял выполнять только операции replace (заменить блок X в базовом образе содержимым блока Y в снимке), формат COW сжатых снимков Android более выразителен и поддерживает следующие операции:
- Копирование. Блок X в базовом устройстве должен быть заменен блоком Y в базовом устройстве.
- Заменить. Блок X в базовом устройстве должен быть заменен содержимым блока Y в снимке. Каждый из этих блоков сжат с помощью gzip.
- Zero. Блок X на базовом устройстве должен быть заменен нулями.
- XOR. Устройство COW хранит сжатые с помощью XOR байты между блоками X и Y. Доступно в Android 13 и более поздних версиях.
Полные беспроводные обновления состоят только из операций replace и zero. При добавочных обновлениях OTA также могут выполняться операции копирования.
Полный макет снимка на диске выглядит следующим образом:
Рисунок 2. Формат COW для Android на диске
dm-user
Модуль ядра dm-user позволяет userspace реализовать блочные устройства device-mapper. Запись в таблице dm-user создает устройство типа "Разное" в разделе /dev/dm-user/<control-name>. Процесс userspace может опрашивать устройство, чтобы получать запросы на чтение и запись от ядра. С каждым запросом связан буфер для пространства пользователя, который нужно заполнить (для чтения) или распространить (для записи).
Модуль ядра dm-user предоставляет новый видимый пользователю интерфейс ядра, который не входит в основную базу кода 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 или более поздняя версия, эта функция должна быть включена. Подробнее о слиянии в пространстве пользователя…
Ниже описан процесс сжатия Virtual 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из RAM-диска и сохраняет в нем дескриптор открытого файла в переменной среды. - На первом этапе
initпереключает корневую файловую систему на системный раздел, а затем выполняет системную копиюinit. - Системная копия
initсчитывает объединенный файл sepolicy в строку. Initвызываетmlock()на всех страницах, поддерживаемых ext4. Затем он деактивирует все таблицы device-mapper для устройств моментальных снимков и останавливаетsnapuserd. После этого чтение из разделов запрещено, так как это приводит к взаимоблокировке.- Используя открытый дескриптор для копии
snapuserdв RAM-диске,initперезапускает демон с правильным контекстом SELinux. Таблицы device-mapper для устройств моментальных снимков повторно активируются. - Init вызывает
munlockall(), поэтому можно снова выполнять операции ввода-вывода.
Использование чат-групп
В таблице ниже сравнивается использование пространства для разных механизмов OTA с использованием ОС и размеров OTA Pixel.
| Влияние размера | не A/B; | A/B-тестирование | Виртуальное A/B-тестирование | Virtual A/B (сжатый) |
|---|---|---|---|---|
| Оригинальный заводской образ | 4,5 ГБ (3,8 ГБ для образа + 700 МБ зарезервировано)1 | 9 ГБ (3, 8 ГБ + 700 МБ зарезервировано для двух слотов) | 4,5 ГБ (3,8 ГБ для образа + 700 МБ зарезервировано) | 4,5 ГБ (3,8 ГБ для образа + 700 МБ зарезервировано) |
| Другие статические разделы | /cache | Нет | Нет | Нет |
| Дополнительное хранилище во время обновления по беспроводной сети (место освобождается после обновления) | 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 Требования к свободному пространству действуют до перезагрузки.
Виртуальная система A/B в Android 11
В Android 11 виртуальные A/B-разделы записывались в динамический раздел с использованием формата Kernel COW. Впоследствии от него отказались, поскольку формат Kernel COW не поддерживает сжатие.
Виртуальная система A/B в Android 12
В Android 12 поддерживается сжатие в виде формата COW, разработанного специально для Android. В этой версии Virtual A/B требовался перевод COW, относящегося к Android, в формат Kernel COW. В Android 13 этот механизм был заменен на другой, который не зависит от формата COW ядра и dm-snapshot.
Чтобы реализовать Virtual A/B или использовать сжатые снимки, ознакомьтесь с разделом Реализация Virtual A/B.