Android 9 includes the following changes to the bootloader boot reason specification.
Boot reasons
A bootloader uses uniquely-available hardware and memory resources to
determine why a device rebooted, then communicates that determination by
adding androidboot.bootreason=<reason>
to the Android
kernel command line for its launch. init
then translates this
command line to propagate to the Android property
bootloader_boot_reason_prop
(ro.boot.bootreason
).
For devices launching with Android 12 or higher,
using kernel version 5.10 or greater, androidboot.bootreason=<reason>
is added to bootconfig instead of the kernel command line.
Boot reason specifications
Previous releases of Android specified a boot reason format that used no
spaces, was all lowercase, included few requirements (such as for reporting
kernel_panic
, watchdog
,
cold
/warm
/hard
), and which made
allowances for other unique reasons. This loose specification resulted in the
proliferation of hundreds of custom (and sometimes meaningless) boot reason
strings, which in turn led to an unmanageable situation. As of the current
Android release, the sheer momentum of near unparseable or meaningless content
filed by the bootloader has created compliance issues for
bootloader_boot_reason_prop
.
With the Android 9 release, the Android team
recognizes that the legacy bootloader_boot_reason_prop
has
substantial momentum and cannot be re-written at runtime. Any improvements to
the boot reason specification must therefore come from interactions with
bootloader developers and tweaks to the existing system. To that end the
Android team is:
- Engaging with bootloader developers to encourage them to:
- Provide canonical, parseable, and recognizable reasons to
bootloader_boot_reason_prop
. - Participate in the
system/core/bootstat/bootstat.cpp
kBootReasonMap
list.
- Provide canonical, parseable, and recognizable reasons to
- Adding a controlled and runtime-rewritable source of the
system_boot_reason_prop
(sys.boot.reason
). A limited set of system apps (such asbootstat
andinit
) can rewrite this property, but all apps can be granted sepolicy rights to read it. - Informing users of the boot reason to wait until after userdata is mounted
before trusting the content in the system boot reason property
system_boot_reason_prop
.
Why so late? While bootloader_boot_reason_prop
is available early
on in boot, it is blocked by the Android security policy on an as-need basis
because it represents inaccurate, unparseable, and noncanonical information.
In most situations, only developers with deep knowledge of the boot system
should need to access this information. A refined, parseable, and canonical
API for boot reason with system_boot_reason_prop
can be reliably
and accurately picked up only after userdata has mounted.
Specifically:
- Before userdata has mounted,
system_boot_reason_prop
will contain the value frombootloader_boot_reason_prop
. - After userdata has mounted,
system_boot_reason_prop
may be updated to be compliant or to report more accurate information.
For this reason, Android 9 extends the period of
time before the boot reason can be officially acquired, changing it from being
immediately accurate in boot (with bootloader_boot_reason_prop
)
to being available only after userdata has mounted (with
system_boot_reason_prop
).
Bootstat logic depends on a more informative and compliant
bootloader_boot_reason_prop
. When that property uses a
predictable format, it improves the accuracy of all controlled reboot and
shutdown scenarios, which in turn refines and expands the accuracy and meaning
of system_boot_reason_prop
.
Canonical boot reason format
The canonical boot reason format for bootloader_boot_reason_prop
in Android 9 uses the following syntax:
<reason>,<subreason>,<detail>…
Formatting rules:
- Lower case
- No blanks (use underline)
- All printable characters
- Comma-separated
reason
,subreason
, and one or moredetail
instances.- A required
reason
that represents the highest priority reason why the device had to reboot or shutdown. - An optional
subreason
that represents a short summary of why the device had to reboot or shutdown (or who rebooted or shutdown the device). - One or more optional
detail
values. Adetail
may point to a subsystem to aid in determining which specific system resulted in thesubreason
. You can specify multipledetail
values, which should generally follow a hierarchy of importance. However, it's also acceptable to report multipledetail
values of equal importance.
- A required
An empty value for bootloader_boot_reason_prop
is considered
illegal (as this allows other agents to inject a boot reason after the fact).
Reason requirements
The value given for reason
(first span, prior to termination or
comma) must be of the following set divided into kernel, strong, and blunt
reasons:
- kernel set:
- "
watchdog"
"kernel_panic"
- "
- strong set:
"recovery"
"bootloader"
- blunt set:
"cold"
. Generally indicates a full reset of all devices, including memory."hard"
. Generally indicates the hardware has its state reset andramoops
should retain persistent content."warm"
. Generally indicates the memory and the devices retain some state, and theramoops
(seepstore
driver in kernel) backing store contains persistent content."shutdown"
"reboot"
. Generally means theramoops
state is unknown and the hardware state is unknown. This value is a catchall as thecold
,hard
, andwarm
values provide clues as to the depth of the reset for the device.
Bootloaders must provide a kernel set or a blunt set reason
, and
are strongly encouraged to provide a subreason
if it can be
determined. For example, a power key long press that may or may not have
ramoops
backup would have the boot reason
"reboot,longkey"
.
No first-span reason
can be part of any subreason
or
detail
. However, because kernel set reasons cannot be produced by
user space, "watchdog"
may be reused after a blunt set reason,
along with a detail of the source (for example,
"reboot,watchdog,service_manager_unresponsive"
, or
"reboot,software,watchdog"
).
Boot reasons should not require expert internal knowledge to decipher and/or
should be human readable with an intuitive report. Examples:
"shutdown,vbxd"
(bad), "shutdown,uv"
(better),
"shutdown,undervoltage"
(preferred).
Reason-subreason combinations
Android reserves a set of reason
-subreason
combinations that should not be overloaded in normal usage but can be used on
a case-by-case basis if the combination accurately reflects the associated
condition. Examples of reserved combinations include:
"reboot,userrequested"
"shutdown,userrequested"
"shutdown,thermal"
(fromthermald
)"shutdown,battery"
"shutdown,battery,thermal"
(fromBatteryStatsService
)"reboot,adb"
"reboot,shell"
"reboot,bootloader"
"reboot,recovery"
For more details, refer to kBootReasonMap
in
system/core/bootstat/bootstat.cpp
and the associated git
changelog history in the Android source repository.
Report boot reasons
All boot reasons, either from the bootloader or recorded in the canonical boot
reason, must be recorded in the kBootReasonMap
section of
system/core/bootstat/bootstat.cpp
. The
kBootReasonMap
list is a mix of compliant and legacy
noncompliant reasons. Bootloader developers should register only new
compliant reasons here (and shouldn't register noncompliant reasons unless
the product has already shipped and cannot be changed).
We strongly recommend using existing, compliant entries in
system/core/bootstat/bootstat.cpp
and exercising restraint before
using a noncompliant string. As a guideline, it is:
- OK to report
"kernel_panic"
from the bootloader, asbootstat
may be able to inspectramoops
forkernel_panic signatures
to refine the subreasons into the canonicalsystem_boot_reason_prop
. - Not OK to report a noncompliant string in
kBootReasonMap
(such as"panic")
from the bootloader, as this will ultimately break the ability to refine thereason
.
For example, if kBootReasonMap
contains "wdog_bark"
,
a bootloader developer should:
- Change to
"watchdog,bark"
and add to the list inkBootReasonMap
. - Consider what
"bark"
means for those unfamiliar with the technology and determine if a more meaningfulsubreason
is available.
Verify boot reason compliance
At this time, Android does not provide an active CTS test that can accurately trigger or inspect all possible boot reasons a bootloader could provide; partners can still attempt to run a passive test to determine compatibility.
As a result, bootloader compliance requires bootloader developers to
voluntarily adhere to the spirit of the rules and guidelines described above.
We urge such developers to contribute to AOSP (specifically to
system/core/bootstat/bootstat.cpp
) and use this opportunity as a
forum for discussions about boot reason issues.