Add update reboot metric to the update engine.

This change add the Installer.UpdateNumReboots metric.

This records the number of reboots that occurred while an update was being
attempted. It uses a marker file stored in tmp to discover whether or not
it's already recorded the reboot.

BUG=chromium:226766
TEST=Unittests | ran an update on a test machine and rebooted/resumed and
checked about:histograms to confirm numbers. Also restart update-engine to
verify it didn't double count that.

Change-Id: I5d2af9d5b62a9d974c7c6243a89cb3359051b650
Reviewed-on: https://gerrit.chromium.org/gerrit/47710
Tested-by: Chris Sosa <sosa@chromium.org>
Commit-Queue: Chris Sosa <sosa@chromium.org>
Reviewed-by: Chris Sosa <sosa@chromium.org>
diff --git a/payload_state.cc b/payload_state.cc
index 2a26722..bae21b9 100644
--- a/payload_state.cc
+++ b/payload_state.cc
@@ -58,6 +58,7 @@
     LoadCurrentBytesDownloaded(source);
     LoadTotalBytesDownloaded(source);
   }
+  LoadNumReboots();
   return true;
 }
 
@@ -124,9 +125,15 @@
   SetUrlFailureCount(0);
 }
 
+void PayloadState::UpdateResumed() {
+  LOG(INFO) << "Resuming an update that was previously started.";
+  UpdateNumReboots();
+}
+
 void PayloadState::UpdateRestarted() {
   LOG(INFO) << "Starting a new update";
   ResetDownloadSourcesOnNewUpdate();
+  SetNumReboots(0);
 }
 
 void PayloadState::UpdateSucceeded() {
@@ -135,6 +142,7 @@
   SetUpdateTimestampEnd(Time::Now());
   ReportBytesDownloadedMetrics();
   ReportUpdateUrlSwitchesMetric();
+  ReportRebootMetrics();
 }
 
 void PayloadState::UpdateFailed(ActionExitCode error) {
@@ -435,6 +443,39 @@
        kNumDefaultUmaBuckets);
 }
 
+void PayloadState::ReportRebootMetrics() {
+  // Report the number of num_reboots.
+  string metric = "Installer.UpdateNumReboots";
+  uint32_t num_reboots = GetNumReboots();
+  LOG(INFO) << "Uploading reboot count of " << num_reboots << " for metric "
+            <<  metric;
+  system_state_->metrics_lib()->SendToUMA(
+      metric,
+      static_cast<int>(num_reboots),  // sample
+      0,  // min = 0.
+      50,  // max
+      25);  // buckets
+  SetNumReboots(0);
+}
+
+void PayloadState::UpdateNumReboots() {
+  // We only update the reboot count when the system has been detected to have
+  // been rebooted.
+  if (!system_state_->system_rebooted()) {
+    return;
+  }
+
+  SetNumReboots(GetNumReboots() + 1);
+}
+
+void PayloadState::SetNumReboots(uint32_t num_reboots) {
+  CHECK(prefs_);
+  num_reboots_ = num_reboots;
+  prefs_->SetInt64(kPrefsNumReboots, num_reboots);
+  LOG(INFO) << "Number of Reboots during current update attempt = "
+            << num_reboots_;
+}
+
 void PayloadState::ResetPersistedState() {
   SetPayloadAttemptNumber(0);
   SetUrlIndex(0);
@@ -686,6 +727,10 @@
   SetUpdateDurationUptime(stored_delta);
 }
 
+void PayloadState::LoadNumReboots() {
+  SetNumReboots(GetPersistedValue(kPrefsNumReboots));
+}
+
 void PayloadState::SetUpdateDurationUptimeExtended(const TimeDelta& value,
                                                    const Time& timestamp,
                                                    bool use_logging) {