Fix non-critical updates on boards without an OOBE flow.

A recent change in the policy made update_engine to ignore available
updates if the OOBE flow is not completed and the update is not
critical. Nevertheless, some custom boards don't have a OOBE flow as
Chromebooks do and set is_oobe_enabled=false in the policy manager.
These board were not getting regular updates because the OOBE flow is
considered not completed in those cases.

This patch moves the is_oobe_enabled flag to the HardwareInterface class
together with the IsOOBEComplete() method and updates the callers to
check the IsOOBEEnabled() value before.

Bug: 28460247
Bug: 28553821
TEST=Added unittest for the disabled and not complete case.

Change-Id: Ifd3ac2dc5e7a43f6c24eb014b7e3eacad22e3ab3
diff --git a/hardware_chromeos.cc b/hardware_chromeos.cc
index ccb3978..57583a1 100644
--- a/hardware_chromeos.cc
+++ b/hardware_chromeos.cc
@@ -16,10 +16,12 @@
 
 #include "update_engine/hardware_chromeos.h"
 
+#include <base/files/file_path.h>
 #include <base/files/file_util.h>
 #include <base/logging.h>
 #include <base/strings/string_number_conversions.h>
 #include <base/strings/string_util.h>
+#include <brillo/key_value_store.h>
 #include <brillo/make_unique_ptr.h>
 #include <vboot/crossystem.h>
 
@@ -27,6 +29,7 @@
 #include "vboot/vboot_host.h"
 }
 
+#include "update_engine/common/constants.h"
 #include "update_engine/common/hardware.h"
 #include "update_engine/common/hwid_override.h"
 #include "update_engine/common/platform_constants.h"
@@ -50,6 +53,12 @@
 // a powerwash is performed.
 const char kPowerwashCountMarker[] = "powerwash_count";
 
+// UpdateManager config path.
+const char* kConfigFilePath = "/etc/update_manager.conf";
+
+// UpdateManager config options:
+const char* kConfigOptsIsOOBEEnabled = "is_oobe_enabled";
+
 }  // namespace
 
 namespace chromeos_update_engine {
@@ -58,11 +67,17 @@
 
 // Factory defined in hardware.h.
 std::unique_ptr<HardwareInterface> CreateHardware() {
-  return brillo::make_unique_ptr(new HardwareChromeOS());
+  std::unique_ptr<HardwareChromeOS> hardware(new HardwareChromeOS());
+  hardware->Init();
+  return std::move(hardware);
 }
 
 }  // namespace hardware
 
+void HardwareChromeOS::Init() {
+  LoadConfig("" /* root_prefix */, IsNormalBootMode());
+}
+
 bool HardwareChromeOS::IsOfficialBuild() const {
   return VbGetSystemPropertyInt("debug_build") == 0;
 }
@@ -72,7 +87,14 @@
   return !dev_mode;
 }
 
+bool HardwareChromeOS::IsOOBEEnabled() const {
+  return is_oobe_enabled_;
+}
+
 bool HardwareChromeOS::IsOOBEComplete(base::Time* out_time_of_oobe) const {
+  if (!is_oobe_enabled_) {
+    LOG(WARNING) << "OOBE is not enabled but IsOOBEComplete() was called";
+  }
   struct stat statbuf;
   if (stat(kOOBECompletedMarker, &statbuf) != 0) {
     if (errno != ENOENT) {
@@ -150,4 +172,22 @@
   return true;
 }
 
+void HardwareChromeOS::LoadConfig(const string& root_prefix, bool normal_mode) {
+  brillo::KeyValueStore store;
+
+  if (normal_mode) {
+    store.Load(base::FilePath(root_prefix + kConfigFilePath));
+  } else {
+    if (store.Load(base::FilePath(root_prefix + kStatefulPartition +
+                                  kConfigFilePath))) {
+      LOG(INFO) << "UpdateManager Config loaded from stateful partition.";
+    } else {
+      store.Load(base::FilePath(root_prefix + kConfigFilePath));
+    }
+  }
+
+  if (!store.GetBoolean(kConfigOptsIsOOBEEnabled, &is_oobe_enabled_))
+    is_oobe_enabled_ = true;  // Default value.
+}
+
 }  // namespace chromeos_update_engine