На этой странице описаны изменения, добавленные в AOSP, чтобы уменьшить количество ненужных изменений файлов между сборками. Разработчики устройств, которые поддерживают свои собственные системы сборки, могут использовать эту информацию в качестве руководства по уменьшению размера своих беспроводных (OTA) обновлений.
Обновления Android OTA иногда содержат измененные файлы, которые не соответствуют изменениям кода. На самом деле это системные артефакты сборки. Это может произойти, когда один и тот же код, созданный в разное время, из разных каталогов или на разных машинах, создает большое количество измененных файлов. Такие лишние файлы увеличивают размер патча OTA и затрудняют определение того, какой код изменился.
Чтобы сделать содержимое OTA более прозрачным, AOSP включает изменения системы сборки, предназначенные для уменьшения размера патчей OTA. Ненужные изменения файлов между сборками были устранены, и в обновлениях OTA содержатся только файлы, связанные с исправлениями. AOSP также включает в себя средство сравнения сборок , которое отфильтровывает общие изменения файлов, связанные со сборкой, чтобы обеспечить более четкое различие файлов сборки, и средство сопоставления блоков , помогающее поддерживать согласованное распределение блоков.
Система сборки может создавать излишне большие исправления несколькими способами. Чтобы смягчить это, в Android 8.0 и более поздних версиях были реализованы новые функции для уменьшения размера патча для каждого различия файлов. Улучшения, которые уменьшили размеры пакетов OTA-обновлений, включают следующее:
- Использование Brotli — универсального алгоритма сжатия без потерь для полных изображений при обновлениях устройств, отличных от A/B. Brotli можно настроить для оптимизации сжатия. Для более крупных обновлений, состоящих из двух или более блоков в файловой системе (например,
system.img
), производители устройств или партнеры могут добавлять свои собственные алгоритмы сжатия и могут использовать разные алгоритмы сжатия для разных блоков одного и того же обновления. - Использование повторного сжатия Puffin , детерминированного инструмента исправления для потоков deflate, который обрабатывает функции сжатия и сравнения для генерации обновлений 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-файлах). Для получения подробной информации см. следующее:
- https://android.googlesource.com/platform/build/+/4d66adfd0e6d599d8502007e4ea9aaf82e95569f
- https://android.googlesource.com/platform/build/+/379f9f9cec4fe1c66b6d60a6c19fecb81b9eb410
- https://android.googlesource.com/platform/build/+/7c3e3f8314eec2c053012dd97d2ae649ebeb5653
- https://android.googlesource.com/platform/build/+/5c64b4e81c1331cab56d8a8c201f26bb263b630c
Каталог сборки
Проблема: изменение каталога, в котором создаются вещи, может привести к тому, что двоичные файлы будут другими. Большинство путей в сборке 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++
Эти макросы всегда производят разные выходные данные для разных сборок, поэтому не используйте их. Вот несколько вариантов устранения этих макросов:
- Удалить их. Пример см. на странице https://android.googlesource.com/platform/system/core/+/30622bbb209db187f6851e4cf0cdaa147c2fca9f .
- Чтобы однозначно идентифицировать работающий двоичный файл, считайте идентификатор сборки из заголовка ELF.
- Чтобы узнать, когда была собрана ОС, прочитайте
ro.build.date
(это работает для всего, кроме инкрементных сборок, которые могут не обновлять эту дату). Пример см. на странице https://android.googlesource.com/platform/external/libchrome/+/8b7977eccc94f6b3a3896cd13b4aeacbfa1e0f84 .
Встроенные метки времени в архивах (zip, jar)
Android 7.0 устранил проблему встроенных временных меток в zip-архивах, добавив -X
ко всем использованиям команды zip
. Это удалило UID/GID сборщика и расширенную временную метку Unix из zip-файла.
Новый инструмент ziptime
(расположенный в /platform/build/+/master/tools/ziptime/
) сбрасывает нормальные метки времени в заголовках zip. Подробности смотрите в файле README .
Инструмент signapk
устанавливает метки времени для файлов APK, которые могут различаться в зависимости от часового пояса сервера. Подробнее см. в CL https://android.googlesource.com/platform/build/+/6c41036bcf35fe39162b50d27533f0f3bfab3028 .
Строки версий
Проблема: к строкам версии APK часто BUILD_NUMBER
к их жестко заданным версиям. Даже если в APK больше ничего не изменилось, в результате APK все равно будет другим.
Решение: удалите номер сборки из строки версии APK.
Решение: удалите номер сборки из строки версии APK.
Примеры:
- https://android.googlesource.com/platform/packages/apps/Camera2/+/5e0f4cf699a4c7c95e2c38ae3babe6f20c258d27
- https://android.googlesource.com/platform/build/+/d75d893da8f97a5c7781142aaa7a16cf1dbb669c
Включить вычисление достоверности на устройстве
Если на вашем устройстве включена функция dm-verity , инструменты OTA автоматически подберут вашу конфигурацию проверки подлинности и активируют вычисление проверки подлинности на устройстве. Это позволяет вычислять блоки истинности на устройствах Android вместо того, чтобы хранить их в виде необработанных байтов в вашем пакете OTA. Блоки Verity могут использовать примерно 16 МБ для раздела размером 2 ГБ.
Однако вычисление правды на устройстве может занять много времени. В частности, код прямого исправления ошибок может занять много времени. На пиксельных устройствах это обычно занимает до 10 минут. На недорогих устройствах это может занять больше времени. Если вы хотите отключить вычисление истинности на устройстве, но при этом включить dm-verity, вы можете сделать это, передав --disable_fec_computation
инструменту ota_from_target_files
при создании обновления OTA. Этот флаг отключает вычисление достоверности на устройстве во время обновлений OTA. Это уменьшает время установки OTA, но увеличивает размер пакета OTA. Если на вашем устройстве не включена dm-verity, передача этого флага не имеет никакого эффекта.
Согласованные инструменты сборки
Проблема: Инструменты, которые генерируют установленные файлы, должны быть согласованы (данные входные данные всегда должны давать один и тот же результат).
Решения/примеры: Требовались изменения в следующих инструментах сборки:
- ВНИМАНИЕ создатель файла . Создатель файла NOTICE был изменен для создания воспроизводимых коллекций NOTICE. См. CL: https://android.googlesource.com/platform/build/+/8ae4984c2c8009e7a08e2a76b1762c2837ad4f64 .
- Комплект компилятора Java для Android (Jack) . Инструментарий Jack требовал обновления для обработки случайных изменений порядка сгенерированных конструкторов. В набор инструментов добавлены детерминированные средства доступа для конструкторов: https://android.googlesource.com/toolchain/jack/+/056a5425b3ef57935206c19ecb198a89221ca64b .
- Компилятор ART AOT (dex2oat) . Бинарный файл компилятора ART получил обновление, которое добавило возможность создания детерминированного изображения: https://android.googlesource.com/platform/art/+/ace0dc1dd5480ad458e622085e51583653853fb9 .
- Файл libpac.so (V8) . Каждая сборка создает отдельный файл
/system/lib/libpac.so
, поскольку моментальный снимок V8 меняется для каждой сборки. Решение состояло в том, чтобы удалить снимок: https://android.googlesource.com/platform/external/v8/+/e537f38c36600fd0f3026adba6b3f4cbcee1fb29 . - Предварительно дефрагментированные файлы приложения (.odex) . Файлы pre-dexopt (.odex) содержали неинициализированные отступы в 64-битных системах. Это было исправлено: https://android.googlesource.com/platform/art/+/34ed3afc41820c72a3c0ab9770be66b6668aa029 .
Использование инструмента сборки различий
Для случаев, когда невозможно исключить изменения файлов, связанные со сборкой, 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, у них уже может быть обновленное приложение или даже более новая версия, полученная непосредственно из магазинов приложений.