Android init 属性 触发器是否总是在启动时发生,如果是,具体是什么时候?

Do Android init property triggers always happen on boot and if so when exactly?

来自 Google 关于 Android init at https://android.googlesource.com/platform/system/core/+/oreo-release/init/README.md 的文档说了以下内容

An Action can have multiple property triggers but may only have one event trigger.

For example: on boot && property:a=b defines an action that is only executed when the ‘boot’ event trigger happens and the property a equals b.

on property:a=b && property:c=d defines an action that is executed at three times:

  1. During initial boot if property a=b and property c=d.
  2. Any time that property a transitions to value b, while property c already equals d.
  3. Any time that property c transitions to value d, while property a already equals b.

在第一个示例中,on boot 触发器似乎是启动时执行操作的必要条件。但是在第二个示例中没有使用 on boot 触发器,但文档说该操作仍将在启动时执行。

所以似乎只有两个陈述中的一个是正确的:

  1. property 触发器永远不会在启动时自动发生,在这种情况下,第二个示例描述关于案例 #1
  2. 是错误的
  3. property 触发器总是在它们为真时在启动时执行,而不仅仅是在它们转换时执行,在这种情况下,第一个示例不需要包含 boot 触发器。

如果第二个陈述是正确的那么它是特定的 boot 阶段而不是说 late-init?

我决定继续 运行 一些测试。证据表明文档对发生的事情是正确的,但缺乏详细说明原因。

第一个示例 on boot && property:a=b 将在 init 触发 boot 事件时在引导期间执行。请注意,并非所有属性都同时初始化,因此这可能会影响它们在各种引导事件期间的可用性。另请注意,当 属性 更改时,此示例不会 运行。主要的混淆是 init 中的属性既是事件又是状态,而 init 阶段只是事件。

第二个例子运行s在启动过程中,但与boot事件无关!它 运行s 当 init 启用 属性 触发器时(详见下文)。也正如所描述的那样,当 属性 更改为声明值且另一个 属性 条件为真时,运行s。

测试结果:

on boot
    exec /system/bin/echo "Trigger test A"

运行 当 init 脚本触发 boot 事件时

on late-init
    exec /system/bin/echo "Trigger test B"

运行当init触发late-init事件

on property:persist.testing=1
    exec /system/bin/echo "Trigger test C"

运行 当 属性 从文件系统持久属性加载时(在测试时这是在 post-fs-data 完成之后),这也是 运行s 当 属性 以后随时转换到指定值

on boot && property:persist.testing=1
    exec /system/bin/echo "Trigger test D"

从不 运行,触发 boot 时持久属性不可用

on post-fs-data && property:persist.testing=1
    exec /system/bin/echo "Trigger test E"

从不运行,触发post-fs-data时坚持属性不可用,之后立即可用,但为时已晚!

on property:ro.build.type=eng
    exec /system/bin/echo "Trigger test F"

运行 当 属性 触发器启用时,在 late-init 完成触发后(请参阅下面的说明)

on boot && property:ro.build.type=eng
    exec /system/bin/echo "Trigger test G"

运行 在启动过程中,当 init 触发 boot 事件时,属性 当时可用

on post-fs-data && property:ro.build.type=eng
    exec /system/bin/echo "Trigger test H"

运行 在启动过程中两次当 init 触发 post-fs-data 事件时,一次是在解密之前加载数据,一次是在解密之后加载数据

on late-init && property:ro.build.type=eng
    exec /system/bin/echo "Trigger test I"

运行 当 init 触发时 late-init

历史证据:

01-25 23:26:25.605     0     0 W         : Trigger test B
01-25 23:26:25.605     0     0 W         : Trigger test I
01-25 23:26:26.892     0     0 W         : Trigger test H
01-25 23:26:28.475     0     0 I init    : processing action (early-boot) from (/vendor/etc/init/hw/init.target.rc:79)
01-25 23:26:28.537     0     0 I init    : processing action (boot) from (/init.rc:660)
01-25 23:26:28.745     0     0 I         : Trigger test A
01-25 23:26:28.778     0     0 I         : Trigger test G
01-25 23:26:28.939     0     0 I         : Trigger test F
01-25 23:26:31.070     0     0 I         : Trigger test H
01-25 23:26:34.871     0     0 I init    : processing action (post-fs-data) from (/system/etc/init/bootstat.rc:9)
01-25 15:26:35.284     0     0 I         : Trigger test C
01-25 15:26:42.468     0     0 I init    : processing action (sys.boot_completed=1) from (/init.rc:819)

2022 年更新:

我更新了一些之前的解释和测试结果

有人指出 属性-only 触发器发生在 late-init 之后。不清楚为什么 Google 选择这样做,但查看 init.cpp 您可以在 init.cpp 中看到以下代码:

// Don't mount filesystems or start core system services in charger mode.
std::string bootmode = GetProperty("ro.bootmode", "");
if (bootmode == "charger") {
    am.QueueEventTrigger("charger");
} else {
    am.QueueEventTrigger("late-init");
}

// Run all property triggers based on current state of the properties.
am.QueueBuiltinAction(queue_property_triggers_action, "queue_property_triggers");

这意味着所有 late-init 和更早的触发器 运行 在 属性-only 触发器之前。所以一个触发器比如on late-init && property:xyz=*运行s在触发器on property:xyz=*!

之前