init: ro.boottime.init.first_stage
Add a property ro.boottime.init.first_stage to provide us a
first stage init duration from start to exec completed in
nanoseconds.
For consistency, report nanoseconds duration for
ro.boottime.init.selinux as well instead of milliseconds.
Now also report consistently from start to exec completed
instead of just the selinux load time.
SideEffects: ro.boottime.init.selinux is reported to TRON and
may alarm with the millionfold increase in precision.
ro.boottime.init is now also consistent with ns
precision.
Test: inspect
Bug: 124491153
Bug: 129780532
Change-Id: Iff4f1a3a1ab7ff0a309c278724c92da0832b9a69
diff --git a/init/init.cpp b/init/init.cpp
index c79e459..a18c2c8 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -35,6 +35,7 @@
#include <android-base/chrono_utils.h>
#include <android-base/file.h>
#include <android-base/logging.h>
+#include <android-base/parseint.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
@@ -627,11 +628,40 @@
}
}
+static void RecordStageBoottimes(const boot_clock::time_point& second_stage_start_time) {
+ int64_t first_stage_start_time_ns = -1;
+ static constexpr char first_stage_started_at[] = "FIRST_STAGE_STARTED_AT";
+ if (auto first_stage_start_time_str = getenv(first_stage_started_at);
+ first_stage_start_time_str) {
+ property_set("ro.boottime.init", first_stage_start_time_str);
+ android::base::ParseInt(first_stage_start_time_str, &first_stage_start_time_ns);
+ }
+ unsetenv(first_stage_started_at);
+
+ int64_t selinux_start_time_ns = -1;
+ static constexpr char selinux_started_at[] = "SELINUX_STARTED_AT";
+ if (auto selinux_start_time_str = getenv(selinux_started_at); selinux_start_time_str) {
+ android::base::ParseInt(selinux_start_time_str, &selinux_start_time_ns);
+ }
+ unsetenv(selinux_started_at);
+
+ if (selinux_start_time_ns == -1) return;
+ if (first_stage_start_time_ns == -1) return;
+
+ property_set("ro.boottime.init.first_stage",
+ std::to_string(selinux_start_time_ns - first_stage_start_time_ns));
+ property_set("ro.boottime.init.selinux",
+ std::to_string(second_stage_start_time.time_since_epoch().count() -
+ selinux_start_time_ns));
+}
+
int SecondStageMain(int argc, char** argv) {
if (REBOOT_BOOTLOADER_ON_PANIC) {
InstallRebootSignalHandlers();
}
+ boot_clock::time_point start_time = boot_clock::now();
+
// We need to set up stdin/stdout/stderr again now that we're running in init's context.
InitKernelLogging(argv, InitAborter);
LOG(INFO) << "init second stage started!";
@@ -663,9 +693,8 @@
// used by init as well as the current required properties.
export_kernel_boot_props();
- // Make the time that init started available for bootstat to log.
- property_set("ro.boottime.init", getenv("INIT_STARTED_AT"));
- property_set("ro.boottime.init.selinux", getenv("INIT_SELINUX_TOOK"));
+ // Make the time that init stages started available for bootstat to log.
+ RecordStageBoottimes(start_time);
// Set libavb version for Framework-only OTA match in Treble build.
const char* avb_version = getenv("INIT_AVB_VERSION");
@@ -678,8 +707,6 @@
}
// Clean up our environment.
- unsetenv("INIT_STARTED_AT");
- unsetenv("INIT_SELINUX_TOOK");
unsetenv("INIT_AVB_VERSION");
unsetenv("INIT_FORCE_DEBUGGABLE");