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

Commit 8a97f88a authored by James Hawkins's avatar James Hawkins Committed by Gerrit Code Review
Browse files

Merge "bootstat: Record metrics for factory_reset and time_since_factory_reset."

parents 8c09555a 500d7156
Loading
Loading
Loading
Loading
+24 −9
Original line number Diff line number Diff line
@@ -50,7 +50,7 @@ BootEventRecordStore::BootEventRecordStore() {
  SetStorePath(BOOTSTAT_DATA_DIR);
}

void BootEventRecordStore::AddBootEvent(const std::string& name) {
void BootEventRecordStore::AddBootEvent(const std::string& event) {
  std::string uptime_str;
  if (!android::base::ReadFileToString("/proc/uptime", &uptime_str)) {
    LOG(ERROR) << "Failed to read /proc/uptime";
@@ -58,15 +58,15 @@ void BootEventRecordStore::AddBootEvent(const std::string& name) {

  // Cast intentionally rounds down.
  int32_t uptime = static_cast<int32_t>(strtod(uptime_str.c_str(), NULL));
  AddBootEventWithValue(name, uptime);
  AddBootEventWithValue(event, uptime);
}

// The implementation of AddBootEventValue makes use of the mtime file
// attribute to store the value associated with a boot event in order to
// optimize on-disk size requirements and small-file thrashing.
void BootEventRecordStore::AddBootEventWithValue(
    const std::string& name, int32_t value) {
  std::string record_path = GetBootEventPath(name);
    const std::string& event, int32_t value) {
  std::string record_path = GetBootEventPath(event);
  if (creat(record_path.c_str(), S_IRUSR | S_IWUSR) == -1) {
    PLOG(ERROR) << "Failed to create " << record_path;
  }
@@ -86,6 +86,22 @@ void BootEventRecordStore::AddBootEventWithValue(
  }
}

bool BootEventRecordStore::GetBootEvent(
    const std::string& event, BootEventRecord* record) const {
  CHECK_NE(static_cast<BootEventRecord*>(nullptr), record);
  CHECK(!event.empty());

  const std::string record_path = GetBootEventPath(event);
  int32_t uptime;
  if (!ParseRecordEventTime(record_path, &uptime)) {
    LOG(ERROR) << "Failed to parse boot time record: " << record_path;
    return false;
  }

  *record = std::make_pair(event, uptime);
  return true;
}

std::vector<BootEventRecordStore::BootEventRecord> BootEventRecordStore::
    GetAllBootEvents() const {
  std::vector<BootEventRecord> events;
@@ -104,14 +120,13 @@ std::vector<BootEventRecordStore::BootEventRecord> BootEventRecordStore::
    }

    const std::string event = entry->d_name;
    const std::string record_path = GetBootEventPath(event);
    int32_t uptime;
    if (!ParseRecordEventTime(record_path, &uptime)) {
      LOG(ERROR) << "Failed to parse boot time record: " << record_path;
    BootEventRecord record;
    if (!GetBootEvent(event, &record)) {
      LOG(ERROR) << "Failed to parse boot time event: " << event;
      continue;
    }

    events.push_back(std::make_pair(event, uptime));
    events.push_back(record);
  }

  return events;
+10 −5
Original line number Diff line number Diff line
@@ -34,12 +34,16 @@ class BootEventRecordStore {

  BootEventRecordStore();

  // Persists the boot event named |name| in the record store.
  void AddBootEvent(const std::string& name);
  // Persists the boot |event| in the record store.
  void AddBootEvent(const std::string& event);

  // Persists the boot event named |name| with the associated |value| in the
  // record store.
  void AddBootEventWithValue(const std::string& name, int32_t value);
  // Persists the boot |event| with the associated |value| in the record store.
  void AddBootEventWithValue(const std::string& event, int32_t value);

  // Queries the named boot |event|. |record| must be non-null. |record|
  // contains the boot event data on success. Returns true iff the query is
  // successful.
  bool GetBootEvent(const std::string& event, BootEventRecord* record) const;

  // Returns a list of all of the boot events persisted in the record store.
  std::vector<BootEventRecord> GetAllBootEvents() const;
@@ -50,6 +54,7 @@ class BootEventRecordStore {
  FRIEND_TEST(BootEventRecordStoreTest, AddSingleBootEvent);
  FRIEND_TEST(BootEventRecordStoreTest, AddMultipleBootEvents);
  FRIEND_TEST(BootEventRecordStoreTest, AddBootEventWithValue);
  FRIEND_TEST(BootEventRecordStoreTest, GetBootEvent);

  // Sets the filesystem path of the record store.
  void SetStorePath(const std::string& path);
+23 −0
Original line number Diff line number Diff line
@@ -166,3 +166,26 @@ TEST_F(BootEventRecordStoreTest, AddBootEventWithValue) {
  EXPECT_EQ("permian", events[0].first);
  EXPECT_EQ(42, events[0].second);
}

TEST_F(BootEventRecordStoreTest, GetBootEvent) {
  BootEventRecordStore store;
  store.SetStorePath(GetStorePathForTesting());

  // Event does not exist.
  BootEventRecordStore::BootEventRecord record;
  bool result = store.GetBootEvent("nonexistent", &record);
  EXPECT_EQ(false, result);

  // Empty path.
  EXPECT_DEATH(store.GetBootEvent(std::string(), &record), std::string());

  // Success case.
  store.AddBootEventWithValue("carboniferous", 314);
  result = store.GetBootEvent("carboniferous", &record);
  EXPECT_EQ(true, result);
  EXPECT_EQ("carboniferous", record.first);
  EXPECT_EQ(314, record.second);

  // Null |record|.
  EXPECT_DEATH(store.GetBootEvent("carboniferous", nullptr), std::string());
}
 No newline at end of file
+31 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include <unistd.h>
#include <cstddef>
#include <cstdio>
#include <ctime>
#include <map>
#include <memory>
#include <string>
@@ -155,6 +156,32 @@ void RecordBootReason() {
  boot_event_store.AddBootEventWithValue("boot_reason", boot_reason);
}

// Records two metrics related to the user resetting a device: the time at
// which the device is reset, and the time since the user last reset the
// device.  The former is only set once per-factory reset.
void RecordFactoryReset() {
  BootEventRecordStore boot_event_store;
  BootEventRecordStore::BootEventRecord record;

  time_t current_time_utc = time(nullptr);

  // The factory_reset boot event does not exist after the device is reset, so
  // use this signal to mark the time of the factory reset.
  if (!boot_event_store.GetBootEvent("factory_reset", &record)) {
    boot_event_store.AddBootEventWithValue("factory_reset", current_time_utc);
    boot_event_store.AddBootEventWithValue("time_since_factory_reset", 0);
    return;
  }

  // Calculate and record the difference in time between now and the
  // factory_reset time.
  time_t factory_reset_utc = record.second;
  time_t time_since_factory_reset = difftime(current_time_utc,
                                             factory_reset_utc);
  boot_event_store.AddBootEventWithValue("time_since_factory_reset",
                                         time_since_factory_reset);
}

}  // namespace

int main(int argc, char **argv) {
@@ -165,12 +192,14 @@ int main(int argc, char **argv) {

  int option_index = 0;
  static const char boot_reason_str[] = "record_boot_reason";
  static const char factory_reset_str[] = "record_factory_reset";
  static const struct option long_options[] = {
    { "help",            no_argument,       NULL,   'h' },
    { "log",             no_argument,       NULL,   'l' },
    { "print",           no_argument,       NULL,   'p' },
    { "record",          required_argument, NULL,   'r' },
    { boot_reason_str,   no_argument,       NULL,   0 },
    { factory_reset_str, no_argument,       NULL,   0 },
    { NULL,              0,                 NULL,   0 }
  };

@@ -182,6 +211,8 @@ int main(int argc, char **argv) {
        const std::string option_name = long_options[option_index].name;
        if (option_name == boot_reason_str) {
          RecordBootReason();
        } else if (option_name == factory_reset_str) {
          RecordFactoryReset();
        } else {
          LOG(ERROR) << "Invalid option: " << option_name;
        }