Add Installer.TimeToRebootMinutes metric

This patch introduces a new metric for tracking the duration between
when an update has successfully completed (and the user is presented
with the "reboot arrow" in the panel) and when the system has booted
into the new update.

BUG=chromium:248800
TEST=New unit test + Unit tests pass + Manual tested

Change-Id: Ia22cedc3b70f1d9c2598bed9469b34a257546a64
Reviewed-on: https://gerrit.chromium.org/gerrit/59132
Reviewed-by: Don Garrett <dgarrett@chromium.org>
Reviewed-by: Chris Sosa <sosa@chromium.org>
Tested-by: David Zeuthen <zeuthen@chromium.org>
Commit-Queue: David Zeuthen <zeuthen@chromium.org>
diff --git a/payload_state_unittest.cc b/payload_state_unittest.cc
index 13052ef..c935178 100644
--- a/payload_state_unittest.cc
+++ b/payload_state_unittest.cc
@@ -851,6 +851,56 @@
   EXPECT_TRUE(utils::RecursiveUnlinkDir(temp_dir));
 }
 
+TEST(PayloadStateTest, RebootAfterSuccessfulUpdateTest) {
+  OmahaResponse response;
+  PayloadState payload_state;
+  MockSystemState mock_system_state;
+  FakeClock fake_clock;
+  Prefs prefs;
+  string temp_dir;
+
+  // Set the clock to a well-known time (t = 30 seconds).
+  fake_clock.SetWallclockTime(Time::FromInternalValue(
+      30 * Time::kMicrosecondsPerSecond));
+
+  // We need persistent preferences for this test
+  EXPECT_TRUE(utils::MakeTempDirectory(
+      "/tmp/RebootAfterSuccessfulUpdateTest.XXXXXX", &temp_dir));
+  prefs.Init(FilePath(temp_dir));
+
+  mock_system_state.set_clock(&fake_clock);
+  mock_system_state.set_prefs(&prefs);
+  EXPECT_TRUE(payload_state.Initialize(&mock_system_state));
+
+  // Make the update succeed.
+  SetupPayloadStateWith2Urls("Hash8593", true, &payload_state, &response);
+  payload_state.UpdateSucceeded();
+
+  // Check that the marker was written.
+  EXPECT_TRUE(prefs.Exists(kPrefsSystemUpdatedMarker));
+
+  // Now simulate a reboot and set the wallclock time to a later point
+  // (t = 500 seconds). We do this by using a new PayloadState object
+  // and checking that it emits the right UMA metric with the right
+  // value.
+  fake_clock.SetWallclockTime(Time::FromInternalValue(
+      500 * Time::kMicrosecondsPerSecond));
+  PayloadState payload_state2;
+  EXPECT_TRUE(payload_state2.Initialize(&mock_system_state));
+
+  // Expect 500 - 30 seconds = 470 seconds ~= 7 min 50 sec
+  EXPECT_CALL(*mock_system_state.mock_metrics_lib(), SendToUMA(
+      "Installer.TimeToRebootMinutes",
+      7, _, _, _));
+
+  payload_state2.UpdateEngineStarted();
+
+  // Check that the marker was nuked.
+  EXPECT_FALSE(prefs.Exists(kPrefsSystemUpdatedMarker));
+
+  EXPECT_TRUE(utils::RecursiveUnlinkDir(temp_dir));
+}
+
 TEST(PayloadStateTest, CandidateUrlsComputedCorrectly) {
   OmahaResponse response;
   MockSystemState mock_system_state;