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