Android对重启原因的记录

发布时间 2023-11-27 16:14:31作者: Hello-World3

事后log中,可以在 prop.txt 中获取到他们:

./prop.txt:259:[persist.sys.boot.reason]: []
./prop.txt:260:[persist.sys.boot.reason.history]: [kernel_panic,bug,52663
./prop.txt:789:[sys.boot.reason]: [kernel_panic,bug]
./prop.txt:790:[sys.boot.reason.last]: [kernel_panic,bug]

 

一、原因记录

1. Android通过下面属性来确定启动原因:

(1) ro.boot.bootreason:系统启动过程中,Init进程会将内核启动命令行中的 androidboot.bootreason=<reason> 转化为 ro.boot.bootreason。启动命令行中的 bootreason 由一般芯片供应商提供,内核在断电前会将启动原因写入专用的硬件资源或约定的内存地址。下次启动时,Bootloader 就可以读取相应的资源来确定启动原因,然后添加到内核启动命令行中。如果芯片供应商不支持启动原因写入,androidboot.bootreason 就可能不存在。

(2) sys.boot.reason:系统启动时先将 ro.boot.bootreason 复制给 sys.boot.reason。因为 ro.boot.bootreason 可能不存在,或者可能提供不准确、不可解析或不合规范的信息,在启动完成后会进一步更新 sys.boot.reason。更新后的 sys.boot.reason 将提供准确可靠的、符合规范的启动原因。

(3) persist.sys.boot.reason:Android系统在重启前会将重启原因写入到 persist.sys.boot.reason 中。这个属性可以用来在 ro.boot.bootreason 不存在时,协助确定启动原因。

准确的启动原因应该通过属性 sys.boot.reason 来获取,并且只有在用户数据加载完成后才能提供可靠信息。该属性的更新通过命令 bootstat 完成,可以在 init.rc 中找到启动的过程。

//system/core/bootstat/bootstat.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


2. 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。

 

二、原因格式

1. 启动原因格式在 Android 9 中,ro.boot.bootreason 的规范化启动原因格式使用以下语法:

<reason>,<subreason>,<detail>…

格式设置规则如下:

(1) 小写
(2) 无空格(可使用下划线)
(3) 全部为可打印字符
(4) 以英文逗号分隔 reason、subreason,以及一个或多个 detail。
    reason 是必须的,表示设备为什么必须重启或关机,优先级最高的原因。
    subreason 为选用,表示设备为什么必须重启或关机的简短摘要(或重启/关闭设备的人员)。
    一个或多个选用的 detail 值。detail 可以指向某个子系统,以协助确定是哪个具体系统导致了 subreason。您可以指定多个 detail 值,这些值通常应按照重要程度排序。不过,也可以报告多个具有同等重要性的 detail 值。


2. reason分类

reason 值必须是以下集合(分为内核原因、强原因和弱原因)之一:

(1) 内核集:
"watchdog":通常表示触发了硬件 watchdog 引起重启。
"kernel_panic":表示系统发生了 kernel panic。

(2) 强集:
"recovery":通常为通过 reboot 接口或命令进入 recovery 模式。
"bootloader":通常为通过 reboot 接口或命令进入 bootloader。

(3) 弱集:
"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"(首选)。


3. eason-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"

 

三、实验

1. 触发重启

# echo c > /proc/sysrq-trigger //触发内核写0地址重启
# getprop | grep bootreason
[ro.boot.bootreason]: [kernel_panic,sysrq]
# getprop | grep boot.reason
[persist.sys.boot.reason]: []
[persist.sys.boot.reason.history]: [kernel_panic,sysrq,17241
[sys.boot.reason]: [kernel_panic,sysrq]  //主要!
[sys.boot.reason.last]: [kernel_panic,sysrq]

# reboot -p "ggg ddd mmm"
Done
# getprop | grep bootreason
[ro.boot.bootreason]: [shutdown,ggg_ddd_mmm]
# getprop | grep boot.reason
[persist.sys.boot.reason]: []
[persist.sys.boot.reason.history]: [shutdown,ggg_ddd_mmm,18739
[sys.boot.reason]: [shutdown,ggg_ddd_mmm]
[sys.boot.reason.last]: [shutdown,ggg_ddd_mmm]

 

 

 

参考:
Android 启动原因:https://segmentfault.com/a/1190000021582796?sort=votes
规范化启动原因: https://source.android.google.cn/docs/core/architecture/bootloader/boot-reason?hl=zh-cn //Android官网