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:
- During initial boot if property a=b and property c=d.
- Any time that property a transitions to value b, while property c already equals d.
- Any time that property c transitions to value d, while property a already equals b.
在第一个示例中,on boot
触发器似乎是启动时执行操作的必要条件。但是在第二个示例中没有使用 on boot
触发器,但文档说该操作仍将在启动时执行。
所以似乎只有两个陈述中的一个是正确的:
property
触发器永远不会在启动时自动发生,在这种情况下,第二个示例描述关于案例 #1 是错误的
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=*
!
之前
来自 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:
- During initial boot if property a=b and property c=d.
- Any time that property a transitions to value b, while property c already equals d.
- Any time that property c transitions to value d, while property a already equals b.
在第一个示例中,on boot
触发器似乎是启动时执行操作的必要条件。但是在第二个示例中没有使用 on boot
触发器,但文档说该操作仍将在启动时执行。
所以似乎只有两个陈述中的一个是正确的:
property
触发器永远不会在启动时自动发生,在这种情况下,第二个示例描述关于案例 #1 是错误的
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=*
!