Уменьшить размер OTA

На этой странице описаны изменения, внесённые в AOSP для сокращения количества ненужных изменений файлов между сборками. Разработчики устройств, использующие собственные системы сборки, могут использовать эту информацию в качестве руководства по уменьшению размера своих беспроводных (OTA) обновлений.

OTA-обновления Android иногда содержат изменённые файлы, не соответствующие изменениям кода. Фактически, это артефакты системы сборки. Это может происходить, когда один и тот же код, собранный в разное время, из разных каталогов или на разных машинах, создаёт большое количество изменённых файлов. Такие избыточные файлы увеличивают размер OTA-патча и затрудняют определение того, какой именно код был изменён.

Чтобы сделать содержимое OTA-патчей более прозрачным, AOSP вносит изменения в систему сборки, призванные уменьшить размер OTA-патчей. Ненужные изменения файлов между сборками были устранены, и в OTA-обновлениях содержатся только файлы, связанные с патчами. AOSP также включает инструмент сравнения сборок , который отфильтровывает общие изменения файлов, связанных со сборкой, обеспечивая более чистый файл сравнения сборок, и инструмент сопоставления блоков , который помогает поддерживать единообразное распределение блоков.

Система сборки может создавать неоправданно большие патчи несколькими способами. Чтобы снизить эту проблему, в Android 8.0 и более поздних версиях были реализованы новые функции, уменьшающие размер патча для каждого файла diff. Улучшения, которые уменьшили размер пакетов OTA-обновлений, включают в себя следующие:

  • Использование ZSTD — универсального алгоритма сжатия без потерь для полных изображений при обновлениях устройств, отличных от A/B. ZSTD можно настроить для более высокой степени сжатия, увеличив уровень сжатия. Уровень сжатия задаётся во время генерации OTA и может быть задан с помощью флага --vabc_compression_param=zstd,$COMPRESSION_LEVEL
  • Увеличение размера окна сжатия, используемого во время OTA. Максимальный размер окна сжатия можно задать, настроив параметр сборки в .mk файле устройства. Эта переменная задаётся как PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR := 262144
  • Использование повторного сжатия Puffin , детерминированного инструмента исправления для потоков Deflate, который обрабатывает функции сжатия и сравнения для генерации обновлений A/B OTA.
  • Изменения в использовании инструмента дельта-генерации, например, в использовании библиотеки bsdiff для сжатия патчей. В Android 9 и выше инструмент bsdiff выбирает алгоритм сжатия, обеспечивающий наилучшие результаты сжатия для патча.
  • Улучшения в update_engine привели к уменьшению потребления памяти при применении исправлений для обновлений устройств A/B.

В следующих разделах обсуждаются различные проблемы, влияющие на размеры OTA-обновлений, их решения и примеры реализации в AOSP.

Порядок файлов

Проблема : Файловые системы не гарантируют порядок файлов при запросе списка файлов в каталоге, хотя для одного и того же извлечения он обычно одинаков. Такие инструменты, как ls сортируют результаты по умолчанию, но подстановочные функции, используемые такими командами, как find и make , не сортируют. Перед использованием этих инструментов необходимо отсортировать выходные данные.

Решение : При использовании таких инструментов, как find и make , с функцией wildcard, отсортируйте вывод этих команд перед их использованием. При использовании $(wildcard) или $(shell find) в файлах Android.mk также отсортируйте их. Некоторые инструменты, например Java, сортируют входные данные, поэтому перед сортировкой файлов убедитесь, что используемая вами программа ещё не сделала этого.

Примеры: Многие ошибки были исправлены в основной системе сборки с помощью встроенного макроса all-*-files-under , который включает all-cpp-files-under (поскольку некоторые определения были разнесены по другим make-файлам). Подробнее см. ниже:

Каталог сборки

Проблема: Изменение каталога, в котором собираются файлы, может привести к изменению двоичных файлов. Большинство путей в сборке Android являются относительными, поэтому __FILE__ в C/C++ не является проблемой. Однако отладочные символы по умолчанию кодируют полный путь, а .note.gnu.build-id генерируется путём хеширования предварительно очищенного двоичного файла, поэтому он изменится при изменении отладочных символов.

Решение: AOSP теперь делает пути отладки относительными. Подробнее см. в CL: https://android.googlesource.com/platform/build/+/6a66a887baadc9eb3d0d60e26f748b8453e27a02 .

Временные метки

Проблема: временные метки в результатах сборки приводят к ненужным изменениям файлов. Это может произойти в следующих местах:

  • Макросы __DATE__/__TIME__/__TIMESTAMP__ в коде C или C++.
  • Временные метки, встроенные в zip-архивы.

Решения/Примеры: Чтобы удалить временные метки из выходных данных сборки, воспользуйтесь инструкциями, приведенными ниже в разделах __DATE__/__TIME__/__TIMESTAMP__ в C/C++ и Встроенные временные метки в архивах .

__ДАТА__/__ВРЕМЯ__/__МЕТКА__ в C/C++

Эти макросы всегда создают разные результаты для разных сборок, поэтому не используйте их. Вот несколько вариантов удаления этих макросов:

Встроенные временные метки в архивах (zip, jar)

В Android 7.0 проблема встроенных временных меток в zip-архивах была исправлена ​​путём добавления -X ко всем использованиям команды zip . Это удалило UID/GID сборщика и расширенную временную метку Unix из zip-файла.

Новый инструмент ziptime (расположен в /platform/build/+/android16-release/tools/ziptime/ ) сбрасывает стандартные временные метки в заголовках ZIP-архивов. Подробности см. в файле README .

Инструмент signapk устанавливает временные метки для APK-файлов, которые могут различаться в зависимости от часового пояса сервера. Подробнее см. в CL: https://android.googlesource.com/platform/build/+/6c41036bcf35fe39162b50d27533f0f3bfab3028 .

Инструмент signapk устанавливает временные метки для APK-файлов, которые могут различаться в зависимости от часового пояса сервера. Подробнее см. в CL: https://android.googlesource.com/platform/build/+/6c41036bcf35fe39162b50d27533f0f3bfab3028 .

Строки версий

Проблема: к строкам версии APK часто добавлялся BUILD_NUMBER , жёстко заданный в коде. Даже если в APK ничего не менялось, APK всё равно был другим.

Решение: Удалить номер сборки из строки версии APK.

Примеры:

Включить вычисление верности на устройстве

Если на вашем устройстве включена опция dm-verity , инструменты OTA автоматически подхватят вашу конфигурацию verity и активируют вычисление verity на устройстве. Это позволяет вычислять блоки verity на устройствах Android, а не хранить их в виде сырых байтов в пакете OTA. Блоки verity могут занимать около 16 МБ для раздела объёмом 2 ГБ.

Однако вычисление достоверности на устройстве может занять много времени. В частности, обработка кода прямой коррекции ошибок может занять много времени. На устройствах Pixel это обычно занимает до 10 минут. На устройствах начального уровня это может занять больше времени. Если вы хотите отключить вычисление достоверности на устройстве, но при этом включить dm-verity, вы можете сделать это, передав --disable_fec_computation инструменту ota_from_target_files при создании обновления OTA. Этот флаг отключает вычисление достоверности на устройстве во время обновлений OTA. Он сокращает время установки OTA, но увеличивает размер пакета OTA. Если на вашем устройстве не включена функция dm-verity, передача этого флага не даст никакого эффекта.

Последовательные инструменты сборки

Проблема: Инструменты, генерирующие установленные файлы, должны быть единообразными (заданные входные данные всегда должны давать одинаковый результат).

Решения/Примеры: Изменения потребовались в следующих инструментах сборки:

Используйте инструмент сравнения сборок

Для случаев, когда невозможно исключить изменения файлов, связанные со сборкой, AOSP включает инструмент сравнения сборок target_files_diff.py для сравнения двух пакетов файлов. Этот инструмент выполняет рекурсивное сравнение двух сборок, исключая распространённые изменения файлов, связанные со сборкой, такие как

  • Ожидаемые изменения в результатах сборки (например, из-за изменения номера сборки).
  • Изменения вызваны известными проблемами в текущей системе сборки.

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

target_files_diff.py dir1 dir2

dir1 и dir2 — базовые каталоги, содержащие извлеченные целевые файлы для каждой сборки.

Поддерживайте единообразие распределения блоков

Хотя содержимое файла остаётся неизменным между двумя сборками, фактические блоки, содержащие данные, могли измениться. В результате программа обновления вынуждена выполнять ненужные операции ввода-вывода для перемещения блоков при обновлении OTA.

При обновлении OTA в режиме Virtual A/B ненужные операции ввода-вывода могут значительно увеличить объём хранилища, необходимый для хранения снимка, создаваемого при копировании при записи. При обновлении OTA без использования A/B перемещение блоков для обновления OTA увеличивает время обновления, поскольку перемещение блоков приводит к увеличению количества операций ввода-вывода.

Чтобы решить эту проблему в Android 7.0, Google расширила возможности инструмента make_ext4fs для обеспечения единообразного распределения блоков между сборками. Инструмент make_ext4fs принимает необязательный флаг -d base_fs , который пытается распределить файлы по тем же блокам при создании образа ext4 . Вы можете извлечь файлы сопоставления блоков (например, файлы сопоставления base_fs ) из zip-файла с целевыми файлами предыдущей сборки. Для каждого раздела ext4 существует файл .map в каталоге IMAGES (например, IMAGES/system.map соответствует system разделу). Эти файлы base_fs затем можно зарегистрировать и указать через PRODUCT_<partition>_BASE_FS_PATH , как в этом примере:

  PRODUCT_SYSTEM_BASE_FS_PATH := path/to/base_fs_files/base_system.map
  PRODUCT_SYSTEM_EXT_BASE_FS_PATH := path/to/base_fs_files/base_system_ext.map
  PRODUCT_VENDOR_BASE_FS_PATH := path/to/base_fs_files/base_vendor.map
  PRODUCT_PRODUCT_BASE_FS_PATH := path/to/base_fs_files/base_product.map
  PRODUCT_ODM_BASE_FS_PATH := path/to/base_fs_files/base_odm.map

Хотя это не помогает уменьшить общий размер пакета OTA, это повышает производительность обновления OTA за счёт сокращения количества операций ввода-вывода. Для обновлений Virtual A/B это значительно сокращает объём хранилища, необходимый для применения OTA.

Избегайте обновления приложений

Помимо минимизации различий в сборках, вы можете уменьшить размер OTA-обновлений, исключив обновления для приложений, которые обновляются через магазины приложений. APK-файлы часто занимают значительную часть различных разделов на устройстве. Включение последних версий приложений, обновляемых через магазины приложений, в OTA-обновление может существенно повлиять на размер OTA-пакетов и принести мало пользы пользователям. К моменту получения OTA-пакета пользователи могут уже получить обновлённое приложение или даже более новую версию, полученную непосредственно из магазинов приложений.