Каноническая причина загрузки

В Android 9 внесены следующие изменения в спецификацию причины загрузки загрузчика.

Причины загрузки

Загрузчик использует уникальные доступные аппаратные и оперативные ресурсы для определения причины перезагрузки устройства, а затем передает это определение, добавляя androidboot.bootreason=<reason> в командную строку ядра Android для своего запуска. Затем init преобразует эту командную строку для передачи в свойство Android ` bootloader_boot_reason_prop ( ro.boot.bootreason ). Для устройств, запускаемых с Android 12 или выше, использующих ядро ​​версии 5.10 или выше, androidboot.bootreason=<reason> добавляется в `bootconfig` вместо командной строки ядра.

спецификации причины загрузки

В предыдущих версиях Android был указан формат причины загрузки, который не содержал пробелов, был написан строчными буквами, включал мало требований (например, для сообщения о kernel_panic , watchdog , cold / warm / hard ) и допускал другие уникальные причины. Эта нестрогая спецификация привела к появлению сотен пользовательских (и иногда бессмысленных) строк с причинами загрузки, что, в свою очередь, создало неуправляемую ситуацию. Начиная с текущей версии Android, огромное количество практически не поддающегося анализу или бессмысленного контента, отправляемого загрузчиком, создало проблемы с соответствием для bootloader_boot_reason_prop .

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

  • Взаимодействие с разработчиками загрузчиков с целью побудить их к следующему:
    • Предоставьте функции bootloader_boot_reason_prop канонические, разборчивые и распознаваемые причины.
    • Примите участие в списке kBootReasonMap созданном в system/core/bootstat/bootstat.cpp .
  • Добавление контролируемого и перезаписываемого во время выполнения источника свойства system_boot_reason_prop ( sys.boot.reason ). Ограниченный набор системных приложений (таких как bootstat и init ) может перезаписывать это свойство, но всем приложениям могут быть предоставлены права sepolicy для его чтения.
  • Информирование пользователей о причине загрузки с указанием необходимости дождаться монтирования пользовательских данных, прежде чем доверять содержимому свойства причины загрузки системы system_boot_reason_prop .

Почему так поздно? Хотя bootloader_boot_reason_prop доступен на раннем этапе загрузки, политика безопасности Android блокирует его по мере необходимости, поскольку он содержит неточную, не поддающуюся анализу и неканоническую информацию. В большинстве случаев доступ к этой информации необходим только разработчикам, обладающим глубокими знаниями системы загрузки. Усовершенствованный, поддающийся анализу и канонический API для определения причины загрузки с помощью system_boot_reason_prop может быть надежно и точно получен только после монтирования пользовательских данных. В частности:

  • До монтирования пользовательских данных значение в переменной system_boot_reason_prop будет содержаться в переменной bootloader_boot_reason_prop .
  • После монтирования пользовательских данных параметр system_boot_reason_prop может быть обновлен для обеспечения соответствия требованиям или для предоставления более точной информации.

По этой причине Android 9 увеличивает период времени до официального получения причины загрузки, изменяя её значение с немедленного получения при загрузке (с помощью bootloader_boot_reason_prop ) на доступное только после монтирования пользовательских данных (с помощью system_boot_reason_prop ).

Логика Bootstat зависит от более информативного и соответствующего стандарту bootloader_boot_reason_prop . Когда этот параметр использует предсказуемый формат, это повышает точность всех контролируемых сценариев перезагрузки и выключения, что, в свою очередь, уточняет и расширяет точность и смысл параметра system_boot_reason_prop .

Канонический формат причины загрузки

В Android 9 для параметра bootloader_boot_reason_prop используется следующий синтаксис:

<reason>,<subreason>,<detail>…

Правила форматирования:

  • Нижний регистр
  • Пробелов нет (используйте подчеркивание)
  • Все символы, доступные для печати
  • reason , subreason и одно или несколько detail описаний, разделённые запятыми.
    • Обязательная reason , представляющая собой наиболее приоритетную причину перезагрузки или выключения устройства.
    • Дополнительная subreason необязательная и представляющая собой краткое описание того, почему устройство пришлось перезагрузить или выключить (или кто перезагрузил или выключил устройство).
    • Одно или несколько необязательных значений detail . detail может указывать на подсистему, чтобы помочь определить, какая именно система привела к subreason . Вы можете указать несколько значений detail , которые, как правило, должны следовать иерархии важности. Однако также допустимо указывать несколько значений detail одинаковой важности.

Пустое значение параметра bootloader_boot_reason_prop считается недопустимым (поскольку это позволяет другим агентам внедрять причину загрузки постфактум).

Обоснование требований

Значение, указанное в reason (первый фрагмент, перед завершающей запятой), должно принадлежать к следующему набору, разделенному на основные, веские и грубые причины:

  • набор ядер:
    • « watchdog"
    • "kernel_panic"
  • сильное множество:
    • "recovery"
    • "bootloader"
  • набор для курения:
    • "cold" . Обычно означает полную перезагрузку всех устройств, включая память.
    • "hard" . Обычно это означает, что состояние оборудования было сброшено, и ramoops должен сохранять постоянное содержимое.
    • "warm" . Обычно это означает, что память и устройства сохраняют некоторое состояние, а хранилище ramoops (см. драйвер pstore в ядре) содержит постоянное содержимое.
    • "shutdown"
    • "reboot" . Обычно это означает, что состояние ramoops и состояние оборудования неизвестны. Это значение является общим, поскольку значения " cold , hard " и warm перезагрузки дают представление о степени сброса устройства.

Загрузчики должны указывать причину, заданную ядром или упрощенную reason , и настоятельно рекомендуется указывать subreason если ее можно определить. Например, длительное нажатие кнопки питания, которое может иметь или не иметь резервную копию ramoops , будет иметь причину загрузки "reboot,longkey" .

Ни одна reason первого порядка не может быть частью какой-либо subreason или detail . Однако, поскольку причины, заданные ядром, не могут быть получены из пользовательского пространства, "watchdog" может быть повторно использован после упрощенной причины, вместе с подробной информацией об источнике (например, "reboot,watchdog,service_manager_unresponsive" или "reboot,software,watchdog" ).

Причины загрузки не должны требовать специальных знаний для расшифровки и/или должны быть понятны человеку и представлять собой интуитивно понятный отчет. Примеры: "shutdown,vbxd" (плохо), "shutdown,uv" (лучше), "shutdown,undervoltage" (предпочтительно).

Сочетания причин и подпричин

Android резервирует набор комбинаций reasonsubreason , которые не следует перегружать при обычном использовании, но которые можно использовать в каждом конкретном случае, если комбинация точно отражает соответствующее условие. Примеры зарезервированных комбинаций включают:

  • "reboot,userrequested"
  • "shutdown,userrequested"
  • "shutdown,thermal" (из thermald )
  • "shutdown,battery"
  • "shutdown,battery,thermal" (из BatteryStatsService )
  • "reboot,adb"
  • "reboot,shell"
  • "reboot,bootloader"
  • "reboot,recovery"

Для получения более подробной информации обратитесь к kBootReasonMap в system/core/bootstat/bootstat.cpp и соответствующей истории изменений в репозитории исходного кода Android.

Сообщить о причинах загрузки

Все причины загрузки, как из загрузчика, так и записанные в канонической причине загрузки, должны быть указаны в разделе kBootReasonMap файла system/core/bootstat/bootstat.cpp . Список kBootReasonMap содержит как соответствующие требованиям, так и устаревшие несоответствующие требованиям причины. Разработчики загрузчиков должны регистрировать здесь только новые соответствующие требованиям причины (и не должны регистрировать несоответствующие требованиям причины, если продукт еще не выпущен и его нельзя изменить).

Мы настоятельно рекомендуем использовать существующие, соответствующие требованиям записи в system/core/bootstat/bootstat.cpp и проявлять сдержанность, прежде чем использовать несовместимую строку. В качестве ориентира можно привести следующее:

  • Можно сообщать о "kernel_panic" от загрузчика, поскольку bootstat может проверить ramoops на наличие kernel_panic signatures чтобы уточнить подпричины и определить каноническую причину system_boot_reason_prop .
  • Недопустимо сообщать о несоответствующей строке в kBootReasonMap (например, "panic") от загрузчика, поскольку это в конечном итоге нарушит возможность уточнения reason .

Например, если kBootReasonMap содержит "wdog_bark" , разработчик загрузчика должен:

  • Измените значение на "watchdog,bark" и добавьте его в список в kBootReasonMap .
  • Подумайте, что означает слово "bark" для тех, кто не знаком с этой технологией, и определите, существует ли более осмысленная subreason .

Проверьте соответствие причины загрузки.

В настоящее время Android не предоставляет активного теста CTS, который мог бы точно инициировать или проверить все возможные причины загрузки, которые может вызвать загрузчик; партнеры по-прежнему могут попытаться запустить пассивный тест для определения совместимости.

В результате, соответствие загрузчика требованиям требует от разработчиков загрузчиков добровольного соблюдения духа правил и рекомендаций, описанных выше. Мы призываем таких разработчиков внести свой вклад в AOSP (в частности, в system/core/bootstat/bootstat.cpp ) и использовать эту возможность в качестве форума для обсуждения вопросов, связанных с причинами загрузки.