update_engine: add staging pref to payload_state

Add kPrefsWallClockStagingWaitPeriod as a new pref so that the staging
wait period persists accross reboots. Change the old
kPrefsWallClockWaitPeriod constant to
kPrefsWallClockScatteringWaitPeriod to differentiate more clearly
between the two.

BUG=chromium:858621
TEST=cros_workon_make update_engine --test

Change-Id: Ifc6aeb44271321cdd2f0d4cfa583a7bbc32b9004
Reviewed-on: https://chromium-review.googlesource.com/1138741
Commit-Ready: Adolfo Higueros <adokar@google.com>
Tested-by: Adolfo Higueros <adokar@google.com>
Reviewed-by: Amin Hassani <ahassani@chromium.org>
Reviewed-by: May Lippert <maybelle@chromium.org>
diff --git a/common/constants.cc b/common/constants.cc
index 215ca31..2edfbb7 100644
--- a/common/constants.cc
+++ b/common/constants.cc
@@ -92,7 +92,9 @@
     "update-state-signed-sha-256-context";
 const char kPrefsUpdateTimestampStart[] = "update-timestamp-start";
 const char kPrefsUrlSwitchCount[] = "url-switch-count";
-const char kPrefsWallClockWaitPeriod[] = "wall-clock-wait-period";
+const char kPrefsWallClockScatteringWaitPeriod[] = "wall-clock-wait-period";
+const char kPrefsWallClockStagingWaitPeriod[] =
+    "wall-clock-staging-wait-period";
 
 // These four fields are generated by scripts/brillo_update_payload.
 const char kPayloadPropertyFileSize[] = "FILE_SIZE";
diff --git a/common/constants.h b/common/constants.h
index 78353d8..d97c5fb 100644
--- a/common/constants.h
+++ b/common/constants.h
@@ -90,7 +90,8 @@
 extern const char kPrefsUpdateStateSignedSHA256Context[];
 extern const char kPrefsUpdateTimestampStart[];
 extern const char kPrefsUrlSwitchCount[];
-extern const char kPrefsWallClockWaitPeriod[];
+extern const char kPrefsWallClockScatteringWaitPeriod[];
+extern const char kPrefsWallClockStagingWaitPeriod[];
 
 // Keys used when storing and loading payload properties.
 extern const char kPayloadPropertyFileSize[];
diff --git a/mock_payload_state.h b/mock_payload_state.h
index f543842..4ac3ccf 100644
--- a/mock_payload_state.h
+++ b/mock_payload_state.h
@@ -53,6 +53,7 @@
   MOCK_METHOD1(SetScatteringWaitPeriod, void(base::TimeDelta));
   MOCK_METHOD1(SetP2PUrl, void(const std::string&));
   MOCK_METHOD0(NextPayload, bool());
+  MOCK_METHOD1(SetStagingWaitPeriod, void(base::TimeDelta));
 
   // Getters.
   MOCK_METHOD0(GetResponseSignature, std::string());
@@ -77,6 +78,7 @@
   MOCK_CONST_METHOD0(GetUsingP2PForSharing, bool());
   MOCK_METHOD0(GetScatteringWaitPeriod, base::TimeDelta());
   MOCK_CONST_METHOD0(GetP2PUrl, std::string());
+  MOCK_METHOD0(GetStagingWaitPeriod, base::TimeDelta());
 };
 
 }  // namespace chromeos_update_engine
diff --git a/payload_state.cc b/payload_state.cc
index d891da0..4670b14 100644
--- a/payload_state.cc
+++ b/payload_state.cc
@@ -793,6 +793,7 @@
   SetP2PNumAttempts(0);
   SetP2PFirstAttemptTimestamp(Time());  // Set to null time
   SetScatteringWaitPeriod(TimeDelta());
+  SetStagingWaitPeriod(TimeDelta());
 }
 
 void PayloadState::ResetRollbackVersion() {
@@ -915,7 +916,7 @@
 
 void PayloadState::LoadScatteringWaitPeriod() {
   SetScatteringWaitPeriod(TimeDelta::FromSeconds(
-      GetPersistedValue(kPrefsWallClockWaitPeriod, prefs_)));
+      GetPersistedValue(kPrefsWallClockScatteringWaitPeriod, prefs_)));
 }
 
 void PayloadState::SetScatteringWaitPeriod(TimeDelta wait_period) {
@@ -924,10 +925,27 @@
   LOG(INFO) << "Scattering Wait Period (seconds) = "
             << scattering_wait_period_.InSeconds();
   if (scattering_wait_period_.InSeconds() > 0) {
-    prefs_->SetInt64(kPrefsWallClockWaitPeriod,
+    prefs_->SetInt64(kPrefsWallClockScatteringWaitPeriod,
                      scattering_wait_period_.InSeconds());
   } else {
-    prefs_->Delete(kPrefsWallClockWaitPeriod);
+    prefs_->Delete(kPrefsWallClockScatteringWaitPeriod);
+  }
+}
+
+void PayloadState::LoadStagingWaitPeriod() {
+  SetStagingWaitPeriod(TimeDelta::FromSeconds(
+      GetPersistedValue(kPrefsWallClockStagingWaitPeriod, prefs_)));
+}
+
+void PayloadState::SetStagingWaitPeriod(TimeDelta wait_period) {
+  CHECK(prefs_);
+  staging_wait_period_ = wait_period;
+  LOG(INFO) << "Staging Wait Period (days) =" << staging_wait_period_.InDays();
+  if (staging_wait_period_.InSeconds() > 0) {
+    prefs_->SetInt64(kPrefsWallClockStagingWaitPeriod,
+                     staging_wait_period_.InSeconds());
+  } else {
+    prefs_->Delete(kPrefsWallClockStagingWaitPeriod);
   }
 }
 
diff --git a/payload_state.h b/payload_state.h
index e8b0db0..cb6454f 100644
--- a/payload_state.h
+++ b/payload_state.h
@@ -147,6 +147,8 @@
 
   void SetScatteringWaitPeriod(base::TimeDelta wait_period) override;
 
+  void SetStagingWaitPeriod(base::TimeDelta wait_period) override;
+
   void SetP2PUrl(const std::string& url) override {
     p2p_url_ = url;
   }
@@ -408,8 +410,6 @@
   // increments num_reboots.
   void UpdateNumReboots();
 
-
-
   // Loads the |kPrefsP2PFirstAttemptTimestamp| state variable from disk
   // into |p2p_first_attempt_timestamp_|.
   void LoadP2PFirstAttemptTimestamp();
@@ -426,6 +426,9 @@
   // Loads the persisted scattering wallclock-based wait period.
   void LoadScatteringWaitPeriod();
 
+  // Loads the persisted staging wallclock-based wait period.
+  void LoadStagingWaitPeriod();
+
   // Get the total size of all payloads.
   int64_t GetPayloadSize();
 
@@ -586,6 +589,9 @@
   // The current scattering wallclock-based wait period.
   base::TimeDelta scattering_wait_period_;
 
+  // The current staging wallclock-based wait period.
+  base::TimeDelta staging_wait_period_;
+
   DISALLOW_COPY_AND_ASSIGN(PayloadState);
 };
 
diff --git a/payload_state_interface.h b/payload_state_interface.h
index 3adc148..d384a0e 100644
--- a/payload_state_interface.h
+++ b/payload_state_interface.h
@@ -205,6 +205,9 @@
 
   // Switch to next payload.
   virtual bool NextPayload() = 0;
+
+  // Sets and persists the staging wallclock-based wait period.
+  virtual void SetStagingWaitPeriod(base::TimeDelta wait_period) = 0;
 };
 
 }  // namespace chromeos_update_engine
diff --git a/update_attempter.cc b/update_attempter.cc
index 67b7471..82acfe8 100644
--- a/update_attempter.cc
+++ b/update_attempter.cc
@@ -497,7 +497,8 @@
     if (omaha_request_params_->waiting_period().InSeconds() == 0) {
       // First case. Check if we have a suitable value to set for
       // the waiting period.
-      if (prefs_->GetInt64(kPrefsWallClockWaitPeriod, &wait_period_in_secs) &&
+      if (prefs_->GetInt64(kPrefsWallClockScatteringWaitPeriod,
+                           &wait_period_in_secs) &&
           wait_period_in_secs > 0 &&
           wait_period_in_secs <= scatter_factor_.InSeconds()) {
         // This means:
@@ -557,7 +558,7 @@
     omaha_request_params_->set_wall_clock_based_wait_enabled(false);
     omaha_request_params_->set_update_check_count_wait_enabled(false);
     omaha_request_params_->set_waiting_period(TimeDelta::FromSeconds(0));
-    prefs_->Delete(kPrefsWallClockWaitPeriod);
+    prefs_->Delete(kPrefsWallClockScatteringWaitPeriod);
     prefs_->Delete(kPrefsUpdateCheckCount);
     // Don't delete the UpdateFirstSeenAt file as we don't want manual checks
     // that result in no-updates (e.g. due to server side throttling) to
diff --git a/update_attempter_unittest.cc b/update_attempter_unittest.cc
index 80c9638..eceb02b 100644
--- a/update_attempter_unittest.cc
+++ b/update_attempter_unittest.cc
@@ -909,7 +909,8 @@
   fake_system_state_.fake_hardware()->SetIsOOBEComplete(Time::UnixEpoch());
   fake_system_state_.set_prefs(&fake_prefs);
 
-  EXPECT_TRUE(fake_prefs.SetInt64(kPrefsWallClockWaitPeriod, initial_value));
+  EXPECT_TRUE(
+      fake_prefs.SetInt64(kPrefsWallClockScatteringWaitPeriod, initial_value));
   EXPECT_TRUE(fake_prefs.SetInt64(kPrefsUpdateCheckCount, initial_value));
 
   // make sure scatter_factor is non-zero as scattering is disabled
@@ -942,7 +943,7 @@
   // checks and all artifacts are removed.
   EXPECT_FALSE(
       attempter_.omaha_request_params_->wall_clock_based_wait_enabled());
-  EXPECT_FALSE(fake_prefs.Exists(kPrefsWallClockWaitPeriod));
+  EXPECT_FALSE(fake_prefs.Exists(kPrefsWallClockScatteringWaitPeriod));
   EXPECT_EQ(0, attempter_.omaha_request_params_->waiting_period().InSeconds());
   EXPECT_FALSE(
       attempter_.omaha_request_params_->update_check_count_wait_enabled());