OTA для устройств A/B без динамических разделов

Android 10 поддерживает динамические разделы — систему разбиения пользовательского пространства, которая может создавать, изменять размер и удалять разделы во время беспроводных обновлений (OTA).

На этой странице описывается, как клиенты OTA изменяют размер динамических разделов во время обновления для устройств A/B, выпущенных без поддержки динамических разделов, а также как клиенты OTA обновляются до Android 10.

Фон

При обновлении устройства A/B для поддержки динамических разделов таблица разделов GUID (GPT) на устройстве сохраняется, поэтому super на устройстве отсутствует. Метаданные хранятся в system_a и system_b , но это можно настроить, изменив BOARD_SUPER_PARTITION_METADATA_DEVICE .

В каждом блочном устройстве есть два слота метаданных. Используется только один слот метаданных в каждом блочном устройстве. Например, метаданные 0 в system_a и метаданные 1 в system_b соответствуют разделам в слотах A и B соответственно. Во время выполнения неважно, какой слот обновляется.

На этой странице слоты метаданных называются Metadata S (источник) и Metadata T (цель). Аналогично, разделы называются system_s , vendor_t и т. д.

Дополнительную информацию о конфигурациях системы сборки см. в разделе Обновление устройств .

Дополнительные сведения о принадлежности разделов к группам обновлений см. в разделе Изменения конфигурации платы для новых устройств.

Пример метаданных на устройстве:

  • Физическое блочное устройство system_a
    • Метаданные 0
      • Группа foo_a
        • Логический (динамический) раздел system_a
        • Логический (динамический) раздел product_services_a
        • Другие разделы обновлены пользователем Foo
      • Группа bar_a
        • Логический (динамический) раздел vendor_a
        • Логический (динамический) раздел product_a
        • Другие разделы обновлены Баром
    • Метаданные 1 (не используются)
  • Физическое блочное устройство system_b
    • Метаданные 0 (не используются)
    • Метаданные 1
      • Группа foo_b
        • Логический (динамический) раздел system_b
        • Логический (динамический) раздел product_services_b
        • Другие разделы обновлены пользователем Foo
      • Группа bar_b
        • Логический (динамический) раздел vendor_b
        • Логический (динамический) раздел product_b
        • Другие разделы обновлены Баром

Вы можете использовать инструмент lpdump из папки system/extras/partition_tools для создания дампа метаданных на вашем устройстве. Например:

lpdump --slot 0 /dev/block/by-name/system_a
lpdump --slot 1 /dev/block/by-name/system_b

Модернизация обновления

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

Генератор OTA создаёт финальный файл super.img , содержащий содержимое всех динамических разделов, а затем разбивает образ на несколько образов, соответствующих размерам физических блочных устройств, соответствующих системе, поставщику и т. д. Эти образы называются super_system.img , super_vendor.img и т. д. Клиент OTA применяет эти образы к физическим разделам, а не к логическим (динамическим).

Поскольку OTA-клиент не умеет отображать динамические разделы, все действия после установки автоматически отключаются для этих разделов при создании пакета обновления. Подробнее см. в разделе «Настройка после установки» .

Процесс обновления такой же, как в Android 9.

До обновления:

ro.boot.dynamic_partitions=
ro.boot.dynamic_partitions_retrofit=

После обновления:

ro.boot.dynamic_partitions=true
ro.boot.dynamic_partitions_retrofit=true

Будущие обновления после модернизации

После ретрофит-обновления клиент OTA обновляется для работы с динамическими разделами. Экстенты исходных разделов никогда не перекрывают целевые физические разделы.

Обновление потока с использованием обычного пакета обновлений

  1. Инициализируйте метаданные super .
    1. Создать новые метаданные M из метаданных S (исходных метаданных). Например, если метаданные S используют [ system_s , vendor_s , product_s ] в качестве блочных устройств, то новые метаданные M используют [ system_t , vendor_t , product_t ] в качестве блочных устройств. Все группы и разделы в M удаляются.
    2. Добавьте целевые группы и разделы в соответствии с полем dynamic_partition_metadata в манифесте обновления. Размер каждого раздела можно узнать в new_partition_info .
    3. Записать M в метаданные T.
    4. Отобразите добавленные разделы на устройстве сопоставления как доступные для записи.
  2. Примените обновление на блочных устройствах.
    1. При необходимости отобразите исходные разделы в средстве сопоставления устройств как доступные только для чтения. Это необходимо для загрузки из сторонних источников, поскольку исходные разделы не отображаются до обновления.
    2. Применить полное или дельта-обновление ко всем блочным устройствам в целевом слоте.
    3. Смонтируйте разделы для запуска послеустановочного скрипта, а затем отмонтируйте разделы.
  3. Отменить сопоставление целевых разделов.

Обновление потока с использованием пакета обновлений для модернизации

Если пакет ретрофитного обновления применяется на устройстве, которое уже поддерживает динамические разделы, OTA-клиент напрямую применяет разделённый файл super.img на блочных устройствах. Процесс обновления аналогичен ретрофитному обновлению. Подробнее см. в разделе «Ретрофитинг обновления» .

Например, предположим следующее:

  • Слот A — активный слот.
  • system_a содержит активные метаданные в слоте 0.
  • system_a , vendor_a и product_a используются как блочные устройства.

Когда клиент OTA получает пакет обновления для модернизации, он применяет super_system.img к физической system_b , super_vendor.img к физической системе vendor_b и super_product.img к физической product_b . Физическое блочное устройство system_b содержит правильные метаданные для сопоставления логических system_b , vendor_b и product_b во время загрузки.

Генерация пакетов обновлений

Инкрементный OTA

При создании инкрементных OTA для модернизированных устройств обновления зависят от того, определены ли в базовой сборке PRODUCT_USE_DYNAMIC_PARTITIONS и PRODUCT_RETROFIT_DYNAMIC_PARTITIONS .

  • Если базовая сборка не определяет переменные, это ретрофитное обновление. Пакет обновления содержит разделённый файл super.img и отключает этап послеустановочной настройки.
  • Если базовая сборка определяет переменные, это аналогично типичному обновлению с динамическими разделами. Пакет обновления содержит образы для логических (динамических) разделов. Можно включить этап послеустановки.

Полный OTA

Для модернизированных устройств создаются два полных пакета OTA.

  • $(PRODUCT)-ota-retrofit-$(TAG).zip всегда содержит разделенный super.img и отключает шаг после установки для обновления ретрофита.
    • Он генерируется с помощью дополнительного аргумента --retrofit_dynamic_partitions в скрипте ota_from_target_files .
    • Его можно применять ко всем сборкам.
  • $(PRODUCT)-ota-$(TAG).zip содержит логические изображения для будущих обновлений.
    • Применяйте это только к сборкам с включёнными динамическими разделами. Подробности о применении этого правила см. ниже.

Отклонить неретрофитные обновления на старых сборках

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

Чтобы устройство не приняло полный пакет OTA, вы можете потребовать выполнить проверку текущей конфигурации устройства после установки. Например:

device/ device_name /dynamic_partitions/check_dynamic_partitions

#!/system/bin/sh
DP_PROPERTY_NAME="ro.boot.dynamic_partitions"
DP_RETROFIT_PROPERTY_NAME="ro.boot.dynamic_partitions_retrofit"

DP_PROPERTY=$(getprop ${DP_PROPERTY_NAME})
DP_RETROFIT_PROPERTY=$(getprop ${DP_RETROFIT_PROPERTY_NAME})

if [ "${DP_PROPERTY}" != "true" ] || [ "${DP_RETROFIT_PROPERTY}" != "true" ] ; then
    echo "Error: applied non-retrofit update on build without dynamic" \
         "partitions."
    echo "${DP_PROPERTY_NAME}=${DP_PROPERTY}"
    echo "${DP_RETROFIT_PROPERTY_NAME}=${DP_RETROFIT_PROPERTY}"
    exit 1
fi

device/ device_name /dynamic_partitions/Android.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:= check_dynamic_partitions
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := EXECUTABLES
LOCAL_SRC_FILES := check_dynamic_partitions
LOCAL_PRODUCT_MODULE := true
include $(BUILD_PREBUILT)

device/ device_name /device.mk

PRODUCT_PACKAGES += check_dynamic_partitions

# OPTIONAL=false so that the error in check_dynamic_partitions will be
# propagated to OTA client.
AB_OTA_POSTINSTALL_CONFIG += \
    RUN_POSTINSTALL_product=true \
    POSTINSTALL_PATH_product=bin/check_dynamic_partitions \
    FILESYSTEM_TYPE_product=ext4 \
    POSTINSTALL_OPTIONAL_product=false \

Когда обычный пакет OTA применяется на устройстве без включенных динамических разделов, клиент OTA запускает check_dynamic_partitions в качестве шага после установки и отклоняет обновление.