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

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

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

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

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

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

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

  • Взаимодействие с разработчиками загрузчика, чтобы побудить их:
    • Укажите канонические, анализируемые и узнаваемые причины для bootloader_boot_reason_prop .
    • Участвуйте в списке system/core/bootstat/bootstat.cpp kBootReasonMap .
  • Добавление контролируемого и перезаписываемого во время выполнения источника 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 .

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

Канонический формат причины загрузки для bootloader_boot_reason_prop в Android 9 использует следующий синтаксис:

<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 резервирует набор комбинаций reason и subreason , которые не следует перегружать при обычном использовании, но можно использовать в каждом конкретном случае, если комбинация точно отражает связанное условие. Примеры зарезервированных комбинаций включают в себя:

  • "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 и связанной с ним истории изменений git в репозитории исходного кода 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 ) и использовать эту возможность в качестве форума для обсуждения проблем, связанных с причинами загрузки.