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',