Внедрение виртуальных A/B-патчей

Выберите следующие исправления для устранения следующих известных проблем.

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

Загрузка полного пакета OTA на виртуальное устройство A/B, имеющее суперраздел размером меньше *2 * sum(размер групп обновлений)*, может завершиться неудачно из-за следующей записи в журнале восстановления /tmp/recovery.log :

The maximum size of all groups with suffix _b (...) has exceeded half of allocatable space for dynamic partitions ...

Вот пример журнала:

[INFO:dynamic_partition_control_android.cc(1020)] Will overwrite existing partitions. Slot A may be unbootable until update finishes!
[...]
[ERROR:dynamic_partition_control_android.cc(803)] The maximum size of all groups with suffix _b (2147483648) has exceeded half of allocatable space for dynamic partitions 1073741824.

Если вы столкнулись с этой проблемой, выберите CL 1399393 , перестройте и прошейте загрузочный раздел или раздел восстановления, если устройство не использует восстановление в качестве загрузки.

Исправить ошибку сегментации во время слияния

После применения OTA-обновления во время процесса слияния VAB вызов update_engine_client --cancel приводит к сбою CleanupPreviousUpdateAction . Потенциальная ошибка дикого указателя также возникает, когда markSlotSuccessful приходит с опозданием.

Проблема была решена путем добавления функции StopActionInternal . CleanupPreviousUpdateAction отменяет ожидающие задачи при уничтожении. Он поддерживает переменную, которая отслеживает идентификатор ожидающей задачи в цикле сообщений. При уничтожении ожидающая задача отменяется, чтобы избежать сбоя.

Убедитесь, что в вашем дереве исходного кода Android 11 есть следующие изменения, чтобы исправить сбои SIGSEGV в update_engine во время слияния:

  • CL 1439792 (предварительное условие для CL 1439372)
  • CL 1439372 ( CleanupPreviousUpdateAction : отменить ожидающие задачи при уничтожении)
  • CL 1663460 (исправлена ​​потенциальная ошибка дикого указателя, когда markSlotSuccessful приходит с опозданием)

Исправьте неправильное переключение слотов VAB, опубликуйте OTA-обновление.

В Android 11 и более поздних версиях сбой в синхронизации слот-переключателя на устройстве после OTA-обновления может привести устройство в непригодное для использования состояние. Если реализация переключения слотов вашего IBootControl HAL выполняет запись, вы должны немедленно сбросить эти записи. Если записи не сбрасываются и устройство перезагружается после начала слияния, но до того, как оборудование сможет сбросить запись в переключатель слота, устройство может вернуться к предыдущему слоту и не загрузиться.

Пример решения кода см. в этом CL: CL 1535570 .

Предотвратить преждевременное слияние update_engine

Когда устройство загружается (Android 11 и выше) и загрузка завершается, update_engine вызывает ScheduleWaitMarkBootSuccessful() и WaitForMergeOrSchedule() . Это запустит процесс слияния. Однако устройство перезагружается в старый слот. Поскольку слияние уже началось, устройство не загружается и становится неработоспособным.

Добавьте следующие изменения в дерево исходного кода. Обратите внимание, что CL 1664859 является необязательным.

  • CL 1439792 (предварительное условие для CL 1439372)
  • CL 1439372 ( CleanupPreviousUpdateAction : отменить ожидающие задачи при уничтожении)
  • CL 1663460 (исправлена ​​потенциальная ошибка дикого указателя, когда markSlotSuccessful приходит с опозданием)
  • CL 1664859 (необязательно — добавьте unittest для CleanupPreviousUpdateAction )

Предотвратите потерю или повреждение данных из-за пропущенных метаданных.

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

Условия:

  1. После завершения операции слияния одного набора исключений была вызвана merge_callback() .
  2. Метаданные были обновлены на устройстве COW, которое отслеживает завершение слияния. (Это обновление для устройства COW сбрасывается без ошибок.)

Результат: произошел сбой системы из-за того, что кэш устройства хранения данных недавнего слияния не был очищен.

См. следующее, чтобы реализовать решение:

Убедитесь в правильной конфигурации dm-verity.

В Android 11 и более поздних версиях устройства могут быть случайно настроены со следующими параметрами dm-verity:

  • CONFIG_DM_VERITY_AVB=y в ядре
  • Загрузчик настроен на использование любого режима достоверности (например, AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE ), без AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO .

При такой конфигурации устройства любая ошибка достоверности приводит к повреждению раздела vbmeta и делает устройства, отличные от A/B, неработоспособными. Аналогично, если началось слияние, устройства A/B также могут стать неработоспособными. Используйте только режим достоверности AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO .

  1. Установите CONFIG_DM_VERITY_AVB=n в ядре.
  2. Настройте устройства на использование режима AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO .

Для получения дополнительной информации и практических рекомендаций обратитесь к документации verity: Обработка ошибок dm-verity .

Пропустить проверку достоверности в ответ на ошибку ввода-вывода во время аварийного отключения системы.

В Android 11 и более поздних версиях, если вызывается аварийное отключение системы (как в случае теплового отключения), устройство dm может работать, в то время как блочное устройство больше не может обрабатывать запросы ввода-вывода. В этом состоянии ошибки ввода-вывода, обрабатываемые новыми запросами ввода-вывода dm или уже выполняемыми запросами, могут привести к состоянию искажения достоверности, что является ошибочным суждением.

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

CL 1847875 (Пропускает проверку подлинности в ответ на ошибку ввода-вывода во время завершения работы)

Убедитесь, что DM_ANDROID_VERITY_AT_MOST_ONCE_DEFAULT_ENABLED выключен.

Устройства Android Go с ядром 4.19 или более ранней версии могут иметь DM_ANDROID_VERITY_AT_MOST_ONCE_DEFAULT_ENABLED=y в конфигурации ядра. Этот параметр несовместим с Virtual A/B и, как известно, вызывает редкие проблемы с повреждением страниц, когда оба включены вместе.

Для ядер версии 4.19 и более ранних отключите его, установив CONFIG_DM_ANDROID_VERITY_AT_MOST_ONCE_DEFAULT_ENABLED=n в конфигурации ядра.

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

Убедитесь, что объединенный файл правильно настроен.

Если вы создаете образы системы и образы поставщиков отдельно, а затем используете merge_target_files для их объединения, конфигурации Virtual A/B могут быть неправильно удалены в процессе слияния. Чтобы проверить правильность конфигураций Virtual A/B в объединенном целевом файле, примените следующие исправления: CL 2084183 (объедините идентичные пары ключ/значение в информации о динамическом разделе).

Обновите необходимые компоненты

Начиная с Android 13, snapuserd был перенесен с виртуального диска поставщика на универсальный виртуальный диск. Если ваше устройство обновляется до Android 13, возможно, что виртуальный диск поставщика и общий виртуальный диск содержат копию snapuserd . В этой ситуации Virtual A/B требует системную копию snapuserd . Чтобы убедиться, что установлена ​​правильная копия snapuserd , примените CL 2031243 (скопируйте snapuserd в first_stage_ramdisk).