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