Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1bfcaec1 authored by James Hawkins's avatar James Hawkins
Browse files

bootstat: Calculate and log the absolute device boot time.

Bug: 38345538
Test: None
Change-Id: I76a4b831cc3809d37b7edfcf1b5657cdf363832a
parent 62db5fce
Loading
Loading
Loading
Loading
+52 −14
Original line number Diff line number Diff line
@@ -221,19 +221,24 @@ void RecordInitBootTimeProp(
  }
}

// Parses and records the set of bootloader stages and associated boot times
// from the ro.boot.boottime system property.
void RecordBootloaderTimings(BootEventRecordStore* boot_event_store) {
  // |ro.boot.boottime| is of the form 'stage1:time1,...,stageN:timeN'.
// A map from bootloader timing stage to the time that stage took during boot.
typedef std::map<std::string, int32_t> BootloaderTimingMap;

// Returns a mapping from bootloader stage names to the time those stages
// took to boot.
const BootloaderTimingMap GetBootLoaderTimings() {
  BootloaderTimingMap timings;

  // |ro.boot.boottime| is of the form 'stage1:time1,...,stageN:timeN',
  // where timeN is in milliseconds.
  std::string value = GetProperty("ro.boot.boottime");
  if (value.empty()) {
    // ro.boot.boottime is not reported on all devices.
    return;
    return BootloaderTimingMap();
  }

  int32_t total_time = 0;
  auto stages = android::base::Split(value, ",");
  for (auto const &stageTiming : stages) {
  for (const auto& stageTiming : stages) {
    // |stageTiming| is of the form 'stage:time'.
    auto stageTimingValues = android::base::Split(stageTiming, ":");
    DCHECK_EQ(2, stageTimingValues.size());
@@ -241,23 +246,53 @@ void RecordBootloaderTimings(BootEventRecordStore* boot_event_store) {
    std::string stageName = stageTimingValues[0];
    int32_t time_ms;
    if (android::base::ParseInt(stageTimingValues[1], &time_ms)) {
      total_time += time_ms;
      boot_event_store->AddBootEventWithValue(
          "boottime.bootloader." + stageName, time_ms);
      timings[stageName] = time_ms;
    }
  }

  return timings;
}

// Parses and records the set of bootloader stages and associated boot times
// from the ro.boot.boottime system property.
void RecordBootloaderTimings(BootEventRecordStore* boot_event_store,
                             const BootloaderTimingMap& bootloader_timings) {
  int32_t total_time = 0;
  for (const auto& timing : bootloader_timings) {
    total_time += timing.second;
    boot_event_store->AddBootEventWithValue("boottime.bootloader." + timing.first, timing.second);
  }

  boot_event_store->AddBootEventWithValue("boottime.bootloader.total", total_time);
}

// Records the closest estimation to the absolute device boot time, i.e.,
// from power on to boot_complete, including bootloader times.
void RecordAbsoluteBootTime(BootEventRecordStore* boot_event_store,
                            const BootloaderTimingMap& bootloader_timings,
                            std::chrono::milliseconds uptime) {
  int32_t bootloader_time_ms = 0;

  for (const auto& timing : bootloader_timings) {
    if (timing.first.compare("SW") != 0) {
      bootloader_time_ms += timing.second;
    }
  }

  auto bootloader_duration = std::chrono::milliseconds(bootloader_time_ms);
  auto absolute_total =
      std::chrono::duration_cast<std::chrono::seconds>(bootloader_duration + uptime);
  boot_event_store->AddBootEventWithValue("absolute_boot_time", absolute_total.count());
}

// Records several metrics related to the time it takes to boot the device,
// including disambiguating boot time on encrypted or non-encrypted devices.
void RecordBootComplete() {
  BootEventRecordStore boot_event_store;
  BootEventRecordStore::BootEventRecord record;

  auto uptime = std::chrono::duration_cast<std::chrono::seconds>(
      android::base::boot_clock::now().time_since_epoch());
  auto time_since_epoch = android::base::boot_clock::now().time_since_epoch();
  auto uptime = std::chrono::duration_cast<std::chrono::seconds>(time_since_epoch);
  time_t current_time_utc = time(nullptr);

  if (boot_event_store.GetBootEvent("last_boot_time_utc", &record)) {
@@ -290,7 +325,6 @@ void RecordBootComplete() {
    std::chrono::seconds boot_complete = std::chrono::seconds(uptime.count() - record.second);
    boot_event_store.AddBootEventWithValue(boot_complete_prefix + "_post_decrypt",
                                           boot_complete.count());

  } else {
      boot_event_store.AddBootEventWithValue(boot_complete_prefix + "_no_encryption",
                                             uptime.count());
@@ -304,7 +338,11 @@ void RecordBootComplete() {
  RecordInitBootTimeProp(&boot_event_store, "ro.boottime.init.selinux");
  RecordInitBootTimeProp(&boot_event_store, "ro.boottime.init.cold_boot_wait");

  RecordBootloaderTimings(&boot_event_store);
  const BootloaderTimingMap bootloader_timings = GetBootLoaderTimings();
  RecordBootloaderTimings(&boot_event_store, bootloader_timings);

  auto uptime_ms = std::chrono::duration_cast<std::chrono::milliseconds>(time_since_epoch);
  RecordAbsoluteBootTime(&boot_event_store, bootloader_timings, uptime_ms);
}

// Records the boot_reason metric by querying the ro.boot.bootreason system