启动原因确定
Android通过三个属性来确定启动原因。
-
ro.boot.bootreason
:系统启动过程中,Init进程会将内核启动命令行中的androidboot.bootreason=<reason>
转化为ro.boot.bootreason
。启动命令行中的bootreason由一般芯片供应商提供,内核在断电前会将启动原因写入专用的硬件资源或约定的内存地址。下次启动时,Bootloader就可以读取相应的资源来确定启动原因,然后添加到内核启动命令行中。如果芯片供应商不支持启动原因写入,androidboot.bootreason
就可能不存在。 -
sys.boot.reason
:系统启动时先将ro.boot.bootreason
复制给sys.boot.reason
。因为ro.boot.bootreason
可能不存在,或者可能提供不准确、不可解析或不合规范的信息,在启动完成后会进一步更新sys.boot.reason
。更新后的sys.boot.reason
将提供准确可靠的、符合规范的启动原因。 -
persist.sys.boot.reason
:Android系统在重启前会将重启原因写入到persist.sys.boot.reason
中。这个属性可以用来在ro.boot.bootreason
不存在时,协助确定启动原因。
准确的启动原因应该通过属性sys.boot.reason
来获取,并且只有在用户数据加载完成后才能提供可靠信息。该属性的更新通过命令bootstat完成,可以在init.rc中找到启动的过程。
# Record boot complete metrics.
on property:sys.boot_completed=1 && property:sys.logbootcomplete=1
# Converts bootloader boot reason to system boot reason
# Record boot_complete and related stats (decryption, etc).
# Record the boot reason.
# Record time since factory reset.
# Log all boot events.
exec_background - system log -- /system/bin/bootstat --set_system_boot_reason --record_boot_complete --record_boot_reason --record_time_since_factory_reset -l
Bootstat对sys.boot.reason
处理的简单流程如下,
- 读取
ro.boot.bootreason
,将其转化为符合规范的reason。 - 如果reason是watchdog,检查是否需要增加security标签。
- 如果reason是kernel_panic,从
last klog
中查找详细信息。 - 如果reason属于弱集(包含空值),从
last klog
中查找信息,检查是否电池耗尽引起死机,根据persist.sys.boot.reason
修正reason。 - 如果上述操作依然无法确定reason,将值设置为
reboot,<boot_reason>
。 - 如果reason属于内核集,重写
persist.sys.boot.reason
。
启动原因格式
在 Android 9 中,ro.boot.bootreason
的规范化启动原因格式使用以下语法:
<reason>,<subreason>,<detail>…
格式设置规则如下:
- 小写
- 无空格(可使用下划线)
- 全部为可打印字符
-
以英文逗号分隔reason、subreason,以及一个或多个detail。
-
reason
是必须的,表示设备为什么必须重启或关机,优先级最高的原因。 -
subreason
为选用,表示设备为什么必须重启或关机的简短摘要(或重启/关闭设备的人员)。 - 一个或多个选用的
detail
值。detail
可以指向某个子系统,以协助确定是哪个具体系统导致了subreason
。您可以指定多个detail
值,这些值通常应按照重要程度排序。不过,也可以报告多个具有同等重要性的detail
值。
-
Reason分类
reason
值必须是以下集合(分为内核原因、强原因和弱原因)之一:
-
内核集:
- "
watchdog"
:通常表示触发了硬件watchdog引起重启。 -
"kernel_panic"
:表示系统发生了kernel panic。
- "
-
强集:
-
"recovery"
:通常为通过reboot接口或命令进入recovery模式。 -
"bootloader"
:通常为通过reboot接口或命令进入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"
(首选)。
Reason-Subreason组合
Android 保留了一组 reason
-subreason
组合,在正常使用情况下不应过量使用这些组合;不过,如果组合能准确反映相关状况,则可根据具体情况加以使用。保留组合的示例包括:
"reboot,userrequested"
"shutdown,userrequested"
-
"shutdown,thermal"
(来自thermald
) "shutdown,battery"
-
"shutdown,battery,thermal"
(来自BatteryStatsService
) "reboot,adb"
"reboot,shell"
"reboot,bootloader"
"reboot,recovery"
参考文档:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。