Динамические и модульные обновления Android

android

Эта статья рассказывает о ряде технологий, которые были интегрированы в Android в последние несколько лет и приблизили решение проблемы фрагментации, отсутствия обновлений и существенно упростили создание кастомных прошивок.

A/B-разметка

Большой проблемой с обновлениями является отказ пользователей. Как показывает практика, многие владельцы смартфонов не хотят обновлять свои устройства, потому что: а) это отнимает время, в течение которого смартфон будет недоступен для использования; б) после обновления смартфон может работать некорректно или не включится вообще.

В свое время разработчики Chrome OS также столкнулись с этой проблемой и создали надежную и незаметную пользователю систему бесшовного обновления (Seamless updates). Суть ее состоит в том, что вместо одного системного раздела, поверх которого накладывались бы обновления системы, Chrome OS использует два идентичных системных раздела, каждый из которых содержит свою копию операционной системы.

Обновление в Chrome OS происходит следующим образом: когда ОС обнаруживает наличие обновления, она скачивает его в фоне, устанавливает на второй (неактивный) системный раздел и помечает этот раздел как активный. После перезагрузки (не обязательно сразу после обновления) ОС запускается уже с этого раздела.

РЕКОМЕНДУЕМ:
Инструменты для анализа Android-приложений на Android

Благодаря такой схеме пользователь даже не подозревает, что система обновилась, он просто попадает в обновленную ОС после перезагрузки или включения ноутбука. При этом Chrome OS способна гарантировать, что после обновления пользователь не получит кирпич: если во время загрузки с обновленного раздела произойдет сбой — система пометит текущий раздел флагом unbootable, сделает активным «старый» системный раздел и загрузит заведомо рабочую версию ОС.

Начиная с седьмой версии Android также поддерживает бесшовные обновления и так называемую A/B-разметку разделов. Однако, так как системных разделов в устройствах с Android намного больше, чем в хромбуках, сама раскладка разделов получается более запутанной. Вот только часть разделов, которые пришлось дублировать:

  • boot — содержит ядро и RAM-диск, на устройствах с A/B-разметкой также консоль восстановления (recovery);
  • system — содержит Android, системные библиотеки, системные приложения, стандартные рингтоны, обои и так далее;
  • vendor — драйверы и все необходимые прослойки для работы с железом (Project Treble);
  • userdata — настройки, приложения и данные пользователя;
  • radio — прошивка радиомодуля (поддержка сотовых сетей);
  • vbmeta — раздел Android Verified Boot 2.0 (механизм доверенной загрузки), содержащий контрольные суммы компонентов системы.

Всего дублированных разделов может быть несколько десятков. Например, на OnePlus 6 с A/B-разметкой общее количество разделов — 72 и несколько десятков из них используются только загрузчиком.

От других разделов, наоборот, стало возможным отказаться. Устройства с A/B-разметкой не включают в себя отдельный раздел recovery (консоль восстановления, нужна для установки обновления и сброса до заводских настроек) и раздел cache, который использовался для хранения файлов обновлений (теперь обновление скачивается напрямую в неактивный раздел).

Двойные разделы на смартфоне OnePlus 6
Двойные разделы на смартфоне OnePlus 6

A/B-разметка также позволила вдвое сократить размер раздела system, что вкупе с удалением разделов recovery и cache сделало переход на новую схему разметки менее болезненным. Например, на смартфонах Pixel потеря пространства составила всего несколько сотен мегабайт.

Раздел Размер A/B Размер A-only
Bootloader 50 Мбайт × 2 50 Мбайт
Boot 32 Мбайт × 2 32 Мбайт
Recovery 0 32 Мбайт
Cache 0 100 Мбайт
Radio 70 Мбайт × 2 70 Мбайт
Vendor 300 Мбайт × 2 300 Мбайт
System 2048 Мбайт × 2 4096 Мбайт
Всего 5000 Мбайт 4680 Мбайт

Еще одно достоинство A/B-разметки — отсутствие экрана «Android is upgrading…» после обновления. Система просто загружается как обычно. Также A/B-разметка упрощает тестирование кастомных прошивок: кастом можно поставить второй системой и откатиться на первую, если что-то пойдет не так.

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

Проверить, поддерживает ли твой смартфон A/B-разметку, можно с помощью все того же приложения Treble Check из предыдущего раздела или прочитав переменную ro.build.ab_update с помощью ADB:

Шпаргалка по управлению A/B-разделами с помощью fastboot

Узнать, какой слот (группа разделов) теперь активен:

Сделать неактивный в данный момент слот активным:

Сделать активным указанный слот (a или b):

Прошить указанный раздел:

Динамические обновления

Project Treble открыл дорогу для еще одной весьма полезной функции — Dynamic System Updates (DSU). Этот механизм появился в Android 10 специально для пользователей и разработчиков, которые хотят протестировать новую (бета) версию Android, но не желают жертвовать для этого установленной системой и своими данными.

DSU базируется на технологии Dynamic Partitions, которая должна быть реализована во всех устройствах, выпущенных на рынок с Android 10. При использовании Dynamic Partitions в смартфоне, по сути, есть только один суперраздел, в котором система может создавать динамические разделы, удалять их и менять размеры (такое возможно благодаря модулю ядра Linux dm-linear).

Все системные разделы в таком смартфоне тоже динамические (кроме загрузочных разделов: boot, dtbo и vbmeta). Поэтому при необходимости система может сдвинуть их, чтобы освободить место для дополнительных разделов. Именно так делает функция DSU. Она уменьшает размер системных разделов, создает в освободившемся пространстве еще один набор системных разделов и устанавливает в него образ GSI. Далее смартфон перезагружается в эту свежеустановленную систему, а следующая перезагрузка выполняется вновь со стандартных разделов.

Чтобы установить образ GSI, используя DSU, для начала необходимо разблокировать загрузчик смартфона. Затем активировать DSU с помощью ADB:

Затем нужно скачать сам образ, распаковать и закинуть его на внутреннюю карту памяти смартфона:

Затем можно запустить установку:

После окончания установки в шторке появится уведомление с предложением перезагрузиться.

Предложение перезагрузить смартфон после установки GSI
Предложение перезагрузить смартфон после установки GSI

Сложно, не правда ли? Именно поэтому в Android 11 появилась функция под названием DSU Loader. Она позволяет автоматически загрузить и установить образ GSI в пару кликов.

В текущих сборках Android 11 DSU Loader требует разблокированный загрузчик. Однако к релизу стабильной версии Google планирует убрать это ограничение.

DSU Loader
DSU Loader

Виртуальная A/B-разметка

Кроме возможности временной установки официальных сборок GSI, механизм DSU также позволил реализовать еще одну весьма интересную функцию — Virtual A/B.

Мы уже рассматривали преимущества новой A/B-разметки и то, какие проблемы она может решить. Однако ввиду потери пространства, которое может принести с собой A/B-разметка на устройствах с ограниченным объемом NAND-памяти, а также проблем с миграцией Google не спешит заставлять производителей смартфонов использовать новую разметку.

РЕКОМЕНДУЕМ:
Как устроена операционная система Андроид

Вместо этого они создали виртуальную A/B-разметку. Работает она примерно так же, как динамические обновления, только без отката на ранее установленную прошивку: когда смартфон обнаруживает новое OTA-обновление, он создает несколько дополнительных системных разделов для новой прошивки, скачивает в них обновление, а затем делает эти разделы активными (как и в случае с A/B-разметкой). После следующей перезагрузки смартфон загружается уже с новых разделов; если загрузка проходит успешно, то старые разделы удаляются, а освобожденное ими место отдается разделу userdata.

Виртуальная A/B-разметка будет обязательной для всех устройств, вышедших на рынок с Android 11.

Модульные обновления

Еще один шаг в решении проблемы с обновлениями — Project Mainline. Это внедренная в Android 10 подсистема, позволяющая обновлять куски Android в обход производителя устройства.

В центре новой подсистемы — пакетный менеджер APEX, очень похожий на тот, что используется в дистрибутивах Linux и новой операционке Google Fuchsia. Работает он примерно так: допустим, по очередному указу правительства в России вновь меняют часовые пояса. Команда разработчиков Android формирует новую версию пакета с часовыми поясами и выкладывает ее в Google Play. Пользователи получают обновление — все счастливы.

Содержимое пакета APEX
Содержимое пакета APEX

Таким же образом могут быть обновлены библиотеки и целые подсистемы. Уже сейчас в AOSP доступны пакеты с рантаймом ART («виртуальная машина», ответственная за запуск приложений), библиотека криптографических алгоритмов Conscrypt, набор мультимедийных кодеков, мультимедийный фреймворк, DNS-резолвер, интерфейс Documents UI, Permission Controller, ExtServices, данные часовых поясов, ANGLE (прослойка для трансляции вызовов OpenGL ES в OpenGL, Direct3D 9/11, Desktop GL и Vulkan) и Captive Portal Login. В теории в пакет APEX можно упаковать практически любой компонент системы, и пользователи смогут обновить его независимо от производителя смартфона.

Интересно, что APEX не производит обновление «на живую», когда старый компонент заменяется новым. Раздел /system в Android недоступен для записи, поэтому APEX использует трюк с монтированием. Все обновляемые файлы внутри пакета APEX находятся в образе файловой системы ext4. Когда пакет «устанавливается», система монтирует этот образ поверх раздела /system в режиме bind. В результате файлы пакета как бы заменяют оригинальные файлы Android, хотя в реальности все остается на своих местах.

Такой же трюк использует Magisk для установки модификаций Android без изменения раздела /system. И его автор уже сказал, что APEX станет проблемой для Magisk.

«Установка» пакета APEX
«Установка» пакета APEX

Трюк с сохранением пространства

Внимательно прочитав раздел «A/B-разметка», ты мог заметить, что экономия пространства при такой разметке в основном достигается за счет сокращения размера раздела system в два раза. И дело здесь вовсе не в том, что при A/B-разметке используется какая-то специализированная сборка Android, а в отказе от «лишних» файлов.

В классическом варианте разметки системный раздел содержит в себе не только саму операционную систему, но и так называемые файлы odex. Они представляют собой оптимизированные (пропущенные через AOT-компилятор) версии dex-файлов, которые, в свою очередь, содержат код приложения.

Файлы odex позволяют сократить время старта приложения и повысить его производительность. Они могут быть созданы тремя путями:

  • преинсталлированы на устройство (в классическом варианте разметки — в раздел system);
  • сгенерированы динамически во время использования приложения или простоя устройства;
  • загружены из Google Play вместе с самим приложением.

Отсутствие файлов odex может серьезно испортить пользовательский экспириенс от первого запуска смартфона (время загрузки может составить несколько минут вместо десятков секунд), поэтому они необходимы сразу. С другой стороны, они занимают примерно половину всего пространства раздела system, а если этот раздел продублировать, то потеря пространства станет существенной.

Именно поэтому разработчики отказались от предустановки файлов odex в активный системный раздел, а вместо этого залили их в неактивный системный раздел вместо копии операционной системы. Так что жизненный цикл смартфона с A/B-разметкой выглядит так:

  1. При выпуске с конвейера раздел system_a активный, содержит файлы операционной системы, раздел system_b неактивный, содержит файлы odex.
  2. Во время первого запуска система копирует файлы odex в раздел userdata.
  3. После получения первого OTA-обновления система записывает обновление в раздел system_b, далее запускает генерацию файлов odex (инструмент dex2oat) для новой версии ОС (они также записываются в userdata) и после ее завершения помечает раздел system_b (все разделы слота B) как активный.
  4. После перезагрузки смартфон загружает операционную систему с раздела system_b, используя сгенерированные на третьем этапе файлы odex.

Выводы

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

РЕКОМЕНДУЕМ:
12 советов разработчику Андроид приложений

APEX, с другой стороны, в теории может решить большинство проблем с обновлением смартфонов. Однако, в отличие от дистрибутивов Linux и ОС Fuchsia, пакеты APEX больше напоминают костыль, чем уместное инженерное решение. С другой стороны — лучше так, чем никак.

Понравилась статья? Поделиться с друзьями:
Добавить комментарий