update_engine: Providing testing capability for periodic update checks

Currently, we are not able to properly test periodic update checks
because these update checks are disabled on test images. To solve this
problem this CL introduces a new pref test-update-check-interval-timeout
that contains the number of seconds between periodic update checks. The
tests can put this file in /var/lib/update_engine/prefs and restart the
update_engine. The update_engine should start checking for update after
the number of seconds identified in the above pref and continue checking
for update with that interval. The tests also need to make sure this
file is deleted at the end so it doesn't interfere with future device
updates. This pref internally is deleted after it has been read/used 3
times so it can't be abused. For the same reason, the maximum value that
can be set in the pref is limited to 10 minutes.

BUG=chromium:953471
TEST=FEATURES=test emerge-reef  update_engine
TEST=flashed a device with this new image, put the pref with value of 10
seconds and restarted the update_engine, the update check happened.

Change-Id: I3ad0e300f7908f17da26b0eb0d1510348a2d2435
Reviewed-on: https://chromium-review.googlesource.com/c/aosp/platform/system/update_engine/+/2333308
Commit-Queue: Amin Hassani <ahassani@chromium.org>
Tested-by: Amin Hassani <ahassani@chromium.org>
Reviewed-by: Jae Hoon Kim <kimjae@chromium.org>
Reviewed-by: Andrew Lassalle <andrewlassalle@chromium.org>
diff --git a/update_manager/real_updater_provider.cc b/update_manager/real_updater_provider.cc
index 134db69..268f3bb 100644
--- a/update_manager/real_updater_provider.cc
+++ b/update_manager/real_updater_provider.cc
@@ -18,6 +18,7 @@
 
 #include <inttypes.h>
 
+#include <algorithm>
 #include <string>
 
 #include <base/bind.h>
@@ -439,6 +440,46 @@
   DISALLOW_COPY_AND_ASSIGN(UpdateRestrictionsVariable);
 };
 
+// A variable class for reading timeout interval prefs value.
+class TestUpdateCheckIntervalTimeoutVariable : public Variable<int64_t> {
+ public:
+  TestUpdateCheckIntervalTimeoutVariable(
+      const string& name, chromeos_update_engine::PrefsInterface* prefs)
+      : Variable<int64_t>(name, kVariableModePoll),
+        prefs_(prefs),
+        read_count_(0) {
+    SetMissingOk();
+  }
+  ~TestUpdateCheckIntervalTimeoutVariable() = default;
+
+ private:
+  const int64_t* GetValue(TimeDelta /* timeout */,
+                          string* /* errmsg */) override {
+    auto key = chromeos_update_engine::kPrefsTestUpdateCheckIntervalTimeout;
+    int64_t result;
+    if (prefs_ && prefs_->Exists(key) && prefs_->GetInt64(key, &result)) {
+      // This specific value is used for testing only. So it should not be kept
+      // around and should be deleted after a few reads.
+      if (++read_count_ > 2)
+        prefs_->Delete(key);
+
+      // Limit the timeout interval to 10 minutes so it is not abused if it is
+      // seen on official images.
+      return new int64_t(std::min(result, static_cast<int64_t>(10 * 60)));
+    }
+    return nullptr;
+  }
+
+  chromeos_update_engine::PrefsInterface* prefs_;
+
+  // Counts how many times this variable is read. This is used to delete the
+  // underlying file defining the variable after a certain number of reads in
+  // order to prevent any abuse of this variable.
+  int read_count_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestUpdateCheckIntervalTimeoutVariable);
+};
+
 // RealUpdaterProvider methods.
 
 RealUpdaterProvider::RealUpdaterProvider(SystemState* system_state)
@@ -472,6 +513,9 @@
           "server_dictated_poll_interval", system_state_)),
       var_forced_update_requested_(new ForcedUpdateRequestedVariable(
           "forced_update_requested", system_state_)),
-      var_update_restrictions_(new UpdateRestrictionsVariable(
-          "update_restrictions", system_state_)) {}
+      var_update_restrictions_(
+          new UpdateRestrictionsVariable("update_restrictions", system_state_)),
+      var_test_update_check_interval_timeout_(
+          new TestUpdateCheckIntervalTimeoutVariable(
+              "test_update_check_interval_timeout", system_state_->prefs())) {}
 }  // namespace chromeos_update_manager