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

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

На этой странице рассказывается, как клиенты 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
        • Другие разделы, обновленные Bard
    • Метаданные 1 (не используются)
  • Физическое блочное устройство system_b
    • Метаданные 0 (не используются)
    • Метаданные 1
      • Group foo_b
        • Логический (динамический) раздел system_b
        • Логический (динамический) раздел product_services_b
        • Другие разделы, обновленные пользователем Foo
      • Группа bar_b
        • Логический (динамический) раздел vendor_b
        • Логический (динамический) раздел product_b
        • Другие разделы, обновленные Bard

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