BootControlStub: New class used if CreateBootControl() fail.

This can happen if running update_engine on Brillo in the emulator or
other device lacking a boot_control HAL implementation. With this
change, the update_engine process continues to run but updates won't
work.

Bug: 25012817
Change-Id: I03d516c5e9a53c893c376885cd48068cd359e902
Test: update_engine no longer crashes on brilloemulator_arm.
diff --git a/Android.mk b/Android.mk
index b91a9f4..c3b0fda 100644
--- a/Android.mk
+++ b/Android.mk
@@ -126,6 +126,7 @@
 LOCAL_SRC_FILES := \
     action_processor.cc \
     boot_control_android.cc \
+    boot_control_stub.cc \
     bzip.cc \
     bzip_extent_writer.cc \
     certificate_checker.cc \
diff --git a/boot_control_stub.cc b/boot_control_stub.cc
new file mode 100644
index 0000000..8d43530
--- /dev/null
+++ b/boot_control_stub.cc
@@ -0,0 +1,62 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "update_engine/boot_control_stub.h"
+
+#include <base/logging.h>
+
+using std::string;
+
+namespace chromeos_update_engine {
+
+unsigned int BootControlStub::GetNumSlots() const {
+  return 0;
+}
+
+BootControlInterface::Slot BootControlStub::GetCurrentSlot() const {
+  LOG(ERROR) << __FUNCTION__ << " should never be called.";
+  return 0;
+}
+
+bool BootControlStub::GetPartitionDevice(const string& partition_name,
+                                         Slot slot,
+                                         string* device) const {
+  LOG(ERROR) << __FUNCTION__ << " should never be called.";
+  return false;
+}
+
+bool BootControlStub::IsSlotBootable(Slot slot) const {
+  LOG(ERROR) << __FUNCTION__ << " should never be called.";
+  return false;
+}
+
+bool BootControlStub::MarkSlotUnbootable(Slot slot) {
+  LOG(ERROR) << __FUNCTION__ << " should never be called.";
+  return false;
+}
+
+bool BootControlStub::SetActiveBootSlot(Slot slot) {
+  LOG(ERROR) << __FUNCTION__ << " should never be called.";
+  return false;
+}
+
+bool BootControlStub::MarkBootSuccessfulAsync(
+    base::Callback<void(bool)> callback) {
+  // This is expected to be called on update_engine startup.
+  return false;
+}
+
+}  // namespace chromeos_update_engine
diff --git a/boot_control_stub.h b/boot_control_stub.h
new file mode 100644
index 0000000..39fcb7a
--- /dev/null
+++ b/boot_control_stub.h
@@ -0,0 +1,55 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef UPDATE_ENGINE_BOOT_CONTROL_STUB_H_
+#define UPDATE_ENGINE_BOOT_CONTROL_STUB_H_
+
+#include <string>
+
+#include "update_engine/boot_control_interface.h"
+
+namespace chromeos_update_engine {
+
+// An implementation of the BootControlInterface that does nothing,
+// typically used when e.g. an underlying HAL implementation cannot be
+// loaded or doesn't exist.
+//
+// You are gauranteed that the implementation of GetNumSlots() method
+// always returns 0. This can be used to identify that this
+// implementation is in use.
+class BootControlStub : public BootControlInterface {
+ public:
+  BootControlStub() = default;
+  ~BootControlStub() = default;
+
+  // BootControlInterface overrides.
+  unsigned int GetNumSlots() const override;
+  BootControlInterface::Slot GetCurrentSlot() const override;
+  bool GetPartitionDevice(const std::string& partition_name,
+                          BootControlInterface::Slot slot,
+                          std::string* device) const override;
+  bool IsSlotBootable(BootControlInterface::Slot slot) const override;
+  bool MarkSlotUnbootable(BootControlInterface::Slot slot) override;
+  bool SetActiveBootSlot(BootControlInterface::Slot slot) override;
+  bool MarkBootSuccessfulAsync(base::Callback<void(bool)> callback) override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(BootControlStub);
+};
+
+}  // namespace chromeos_update_engine
+
+#endif  // UPDATE_ENGINE_BOOT_CONTROL_STUB_H_
diff --git a/real_system_state.cc b/real_system_state.cc
index 1d11090..cf904c2 100644
--- a/real_system_state.cc
+++ b/real_system_state.cc
@@ -18,8 +18,10 @@
 
 #include <base/files/file_util.h>
 #include <base/time/time.h>
+#include <brillo/make_unique_ptr.h>
 
 #include "update_engine/boot_control.h"
+#include "update_engine/boot_control_stub.h"
 #include "update_engine/constants.h"
 #include "update_engine/hardware.h"
 #include "update_engine/update_manager/state_factory.h"
@@ -39,8 +41,11 @@
   metrics_lib_.Init();
 
   boot_control_ = boot_control::CreateBootControl();
-  if (!boot_control_)
-    return false;
+  if (!boot_control_) {
+    LOG(WARNING) << "Unable to create BootControl instance, using stub "
+                 << "instead. All update attempts will fail.";
+    boot_control_ = brillo::make_unique_ptr(new BootControlStub());
+  }
 
   hardware_ = hardware::CreateHardware();
   if (!hardware_) {
diff --git a/update_engine.gyp b/update_engine.gyp
index acd6d19..5a87790 100644
--- a/update_engine.gyp
+++ b/update_engine.gyp
@@ -159,6 +159,7 @@
       'sources': [
         'action_processor.cc',
         'boot_control_chromeos.cc',
+        'boot_control_stub.cc',
         'bzip.cc',
         'bzip_extent_writer.cc',
         'certificate_checker.cc',