Android 初始化属性触发器是否总是在启动时发生,如果是,确切地发生?



来自 Google 在 Android init at https://android.googlesource.com/platform/system/core/+/oreo-release/init/README.md 上的文档如下

一个操作可以有多个属性触发器,但只能有一个 事件触发器。

例如:on boot && property:a=b定义一个仅 当"boot"事件触发器发生并且属性 a 等于 b。

on property:a=b && property:c=d定义执行的操作 在三次:

  1. 在初始启动期间,如果属性 a=b 和属性 c=d。
  2. 每当属性 a 转换为值 b,而属性 c 已等于 d 时。
  3. 每当属性 c 转换为值 d,而属性 a 已经等于 b 时。

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

因此,似乎只有两种说法中的一种是正确的:

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

如果第二种说法是正确的,那么它是专门针对boot阶段而不是说late-init吗?

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

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

第二个示例在启动期间运行,但它与boot事件无关!它在 init 启用属性触发器时运行(有关详细信息,请参阅下文(。此外,如前所述,当任一属性更改为声明的值而另一个属性条件为 true 时,它将运行。

测试结果:

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

初始化脚本触发事件时运行boot

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

初始化触发事件时运行late-init

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

当从文件系统持久化属性加载属性时运行(在测试时这是在完成后post-fs-data(,这也会在以后任何时间属性转换为指定值时运行

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"

初始化触发器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 年更新:

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

有人指出,仅属性触发发生在late-init之后。不清楚为什么谷歌选择这样做,但看看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和更早版本的触发器都在仅属性触发器之前运行。因此,像on late-init && property:xyz=*这样的触发器在触发器on property:xyz=*之前运行!

最新更新