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