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

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

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

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

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

  • Использование Brotli — универсального алгоритма сжатия без потерь для полных изображений при обновлениях устройств, отличных от A/B. Brotli можно настроить для оптимизации сжатия. В более крупные обновления, состоящие из двух или более блоков файловой системы (например, system.img ), производители устройств или партнеры могут добавлять свои собственные алгоритмы сжатия и использовать разные алгоритмы сжатия для разных блоков одного и того же обновления.
  • Использование рекомпрессии Puffin , инструмента детерминированного исправления для потоков дефляции, который обрабатывает функции сжатия и сравнения для генерации обновлений A/B OTA.
  • Изменения в использовании инструмента дельта-генерации, например, использование библиотеки bsdiff для сжатия исправлений. В Android 9 и более поздних версиях инструмент bsdiff выбирает алгоритм сжатия, который обеспечит наилучшие результаты сжатия для патча.
  • Улучшения в update_engine привели к уменьшению потребления памяти при применении исправлений для обновлений устройств A/B.
  • Улучшения в разделении больших zip-файлов для блочных OTA-обновлений. Режим в imgdiff разделяет файлы APK большого размера на основе имен записей. При этом получается меньший патч по сравнению с линейным разделением файлов и использованием инструмента bsdiff для их сжатия.

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

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

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

Решение . Когда вы используете такие инструменты, как find и make , с подстановочными знаками, отсортируйте вывод этих команд перед их использованием. При использовании $(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++. и встроенные временные метки в архивах .

__DATE__/__TIME__/__TIMESTAMP__ в C/C++

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

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

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

Новый инструмент ziptime (находится в /platform/build/+/main/tools/ziptime/ ) сбрасывает обычные временные метки в заголовках zip. Подробности смотрите в файле README .

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

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

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

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

Примеры:

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

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

Однако вычисление достоверности на устройстве может занять много времени. В частности, код прямого исправления ошибок может занять много времени. На пиксельных устройствах это обычно занимает до 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-обновления.

В обновлении Virtual A/B OTA ненужные операции ввода-вывода могут значительно увеличить объем памяти, необходимый для хранения моментального снимка копирования при записи. В 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, у них уже может быть обновленное приложение или даже более новая версия, полученная непосредственно из магазинов приложений.