Merge changes from topic 'nyc-mr1-ue_sideload_recovery' into nyc-mr1-dev
* changes:
Setup a temporary directory for update_engine_sideload.
DO NOT MERGE: Make update_engine compile in the branch.
New setting to mark postinstall as optional.
Report the progress of the update when sideloading.
Compile update_engine_sideload as a static recovery program.
Remove libcurl support from update_engine_sideload.
Build update_engine_sideload.
Implement a memory-based Prefs class.
Remove unused libbrillo-http dependency.
diff --git a/Android.mk b/Android.mk
index 3bca905..3f44ecc 100644
--- a/Android.mk
+++ b/Android.mk
@@ -62,9 +62,8 @@
external/gtest/include \
system
ue_common_shared_libraries := \
- libbrillo \
- libbrillo-http \
libbrillo-stream \
+ libbrillo \
libchrome
ifeq ($(local_use_dbus),1)
@@ -146,14 +145,11 @@
$(ue_update_metadata_protos_exported_static_libraries)
ue_libpayload_consumer_exported_shared_libraries := \
libcrypto-host \
- libcurl-host \
- libssl-host \
$(ue_update_metadata_protos_exported_shared_libraries)
ue_libpayload_consumer_src_files := \
common/action_processor.cc \
common/boot_control_stub.cc \
- common/certificate_checker.cc \
common/clock.cc \
common/constants.cc \
common/cpu_limiter.cc \
@@ -163,7 +159,6 @@
common/http_fetcher.cc \
common/file_fetcher.cc \
common/hwid_override.cc \
- common/libcurl_http_fetcher.cc \
common/multi_range_http_fetcher.cc \
common/platform_constants_android.cc \
common/prefs.cc \
@@ -259,7 +254,9 @@
libexpat \
libbrillo-policy \
libhardware \
+ libcurl \
libcutils \
+ libssl \
$(ue_libpayload_consumer_exported_shared_libraries) \
$(ue_update_metadata_protos_exported_shared_libraries)
ifeq ($(local_use_binder),1)
@@ -305,6 +302,7 @@
$(ue_update_metadata_protos_exported_shared_libraries)
LOCAL_SRC_FILES := \
boot_control_android.cc \
+ certificate_checker.cc \
common_service.cc \
connection_manager.cc \
daemon.cc \
@@ -312,6 +310,7 @@
hardware_android.cc \
image_properties_android.cc \
libcros_proxy.cc \
+ libcurl_http_fetcher.cc \
metrics.cc \
metrics_utils.cc \
omaha_request_action.cc \
@@ -379,7 +378,9 @@
libbinderwrapper \
libbrillo-binder \
libcutils \
+ libcurl \
libhardware \
+ libssl \
libutils
include $(CLEAR_VARS)
@@ -408,9 +409,11 @@
binder_bindings/android/os/IUpdateEngineCallback.aidl \
binder_service_android.cc \
boot_control_android.cc \
+ certificate_checker.cc \
daemon.cc \
daemon_state_android.cc \
hardware_android.cc \
+ libcurl_http_fetcher.cc \
network_selector_android.cc \
proxy_resolver.cc \
update_attempter_android.cc \
@@ -463,6 +466,74 @@
LOCAL_INIT_RC := update_engine.rc
include $(BUILD_EXECUTABLE)
+# update_engine_sideload (type: executable)
+# ========================================================
+# A static binary equivalent to update_engine daemon that installs an update
+# from a local file directly instead of running in the background.
+include $(CLEAR_VARS)
+LOCAL_MODULE := update_engine_sideload
+LOCAL_FORCE_STATIC_EXECUTABLE := true
+LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_REQUIRED_MODULES := \
+ bspatch_recovery
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_CLANG := true
+LOCAL_CFLAGS := \
+ $(ue_common_cflags) \
+ -D_UE_SIDELOAD
+LOCAL_CPPFLAGS := $(ue_common_cppflags)
+LOCAL_LDFLAGS := $(ue_common_ldflags)
+LOCAL_C_INCLUDES := \
+ $(ue_common_c_includes) \
+ bootable/recovery
+#TODO(deymo): Remove external/cros/system_api/dbus once the strings are moved
+# out of the DBus interface.
+LOCAL_C_INCLUDES += \
+ external/cros/system_api/dbus
+LOCAL_SRC_FILES := \
+ boot_control_android.cc \
+ hardware_android.cc \
+ network_selector_stub.cc \
+ proxy_resolver.cc \
+ sideload_main.cc \
+ update_attempter_android.cc \
+ update_status_utils.cc \
+ utils_android.cc
+LOCAL_STATIC_LIBRARIES := \
+ libfs_mgr \
+ libpayload_consumer \
+ update_metadata-protos \
+ $(ue_libpayload_consumer_exported_static_libraries:-host=) \
+ $(ue_update_metadata_protos_exported_static_libraries)
+# We add the static versions of the shared libraries since we are forcing this
+# binary to be a static binary, so we also need to include all the static
+# library dependencies of these static libraries.
+LOCAL_STATIC_LIBRARIES += \
+ $(ue_common_shared_libraries) \
+ libcutils \
+ libcrypto_static \
+ $(ue_update_metadata_protos_exported_shared_libraries) \
+ libevent \
+ libmodpb64 \
+ liblog
+
+ifeq ($(strip $(PRODUCT_STATIC_BOOT_CONTROL_HAL)),)
+# No static boot_control HAL defined, so no sideload support. We use a fake
+# boot_control HAL to allow compiling update_engine_sideload for test purposes.
+ifeq ($(strip $(AB_OTA_UPDATER)),true)
+$(warning No PRODUCT_STATIC_BOOT_CONTROL_HAL configured but AB_OTA_UPDATER is \
+true, no update sideload support.)
+endif # AB_OTA_UPDATER == true
+LOCAL_SRC_FILES += \
+ boot_control_recovery_stub.cc
+else # PRODUCT_STATIC_BOOT_CONTROL_HAL != ""
+LOCAL_STATIC_LIBRARIES += \
+ $(PRODUCT_STATIC_BOOT_CONTROL_HAL)
+endif # PRODUCT_STATIC_BOOT_CONTROL_HAL != ""
+
+include $(BUILD_EXECUTABLE)
+
# libupdate_engine_client (type: shared_library)
# ========================================================
include $(CLEAR_VARS)
@@ -827,10 +898,10 @@
$(ue_libupdate_engine_exported_shared_libraries:-host=) \
$(ue_libpayload_generator_exported_shared_libraries:-host=)
LOCAL_SRC_FILES := \
+ certificate_checker_unittest.cc \
common/action_pipe_unittest.cc \
common/action_processor_unittest.cc \
common/action_unittest.cc \
- common/certificate_checker_unittest.cc \
common/cpu_limiter_unittest.cc \
common/fake_prefs.cc \
common/file_fetcher_unittest.cc \
diff --git a/boot_control_android.cc b/boot_control_android.cc
index ba6b559..d096a1b 100644
--- a/boot_control_android.cc
+++ b/boot_control_android.cc
@@ -28,6 +28,14 @@
using std::string;
+#ifdef _UE_SIDELOAD
+// When called from update_engine_sideload, we don't attempt to dynamically load
+// the right boot_control HAL, instead we use the only HAL statically linked in
+// via the PRODUCT_STATIC_BOOT_CONTROL_HAL make variable and access the module
+// struct directly.
+extern const hw_module_t HAL_MODULE_INFO_SYM;
+#endif // _UE_SIDELOAD
+
namespace chromeos_update_engine {
namespace boot_control {
@@ -47,7 +55,18 @@
const hw_module_t* hw_module;
int ret;
+#ifdef _UE_SIDELOAD
+ // For update_engine_sideload, we simulate the hw_get_module() by accessing it
+ // from the current process directly.
+ hw_module = &HAL_MODULE_INFO_SYM;
+ ret = 0;
+ if (!hw_module ||
+ strcmp(BOOT_CONTROL_HARDWARE_MODULE_ID, hw_module->id) != 0) {
+ ret = -EINVAL;
+ }
+#else // !_UE_SIDELOAD
ret = hw_get_module(BOOT_CONTROL_HARDWARE_MODULE_ID, &hw_module);
+#endif // _UE_SIDELOAD
if (ret != 0) {
LOG(ERROR) << "Error loading boot_control HAL implementation.";
return false;
diff --git a/boot_control_recovery_stub.cc b/boot_control_recovery_stub.cc
new file mode 100644
index 0000000..129c5d0
--- /dev/null
+++ b/boot_control_recovery_stub.cc
@@ -0,0 +1,21 @@
+//
+// Copyright (C) 2016 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 <hardware/hardware.h>
+
+hw_module_t HAL_MODULE_INFO_SYM = {
+ .id = "stub",
+};
diff --git a/common/certificate_checker.cc b/certificate_checker.cc
similarity index 98%
rename from common/certificate_checker.cc
rename to certificate_checker.cc
index 86df950..6e886e7 100644
--- a/common/certificate_checker.cc
+++ b/certificate_checker.cc
@@ -14,7 +14,7 @@
// limitations under the License.
//
-#include "update_engine/common/certificate_checker.h"
+#include "update_engine/certificate_checker.h"
#include <string>
diff --git a/common/certificate_checker.h b/certificate_checker.h
similarity index 97%
rename from common/certificate_checker.h
rename to certificate_checker.h
index c785192..5d0b5ba 100644
--- a/common/certificate_checker.h
+++ b/certificate_checker.h
@@ -14,8 +14,8 @@
// limitations under the License.
//
-#ifndef UPDATE_ENGINE_COMMON_CERTIFICATE_CHECKER_H_
-#define UPDATE_ENGINE_COMMON_CERTIFICATE_CHECKER_H_
+#ifndef UPDATE_ENGINE_CERTIFICATE_CHECKER_H_
+#define UPDATE_ENGINE_CERTIFICATE_CHECKER_H_
#include <curl/curl.h>
#include <openssl/ssl.h>
@@ -172,4 +172,4 @@
} // namespace chromeos_update_engine
-#endif // UPDATE_ENGINE_COMMON_CERTIFICATE_CHECKER_H_
+#endif // UPDATE_ENGINE_CERTIFICATE_CHECKER_H_
diff --git a/common/certificate_checker_unittest.cc b/certificate_checker_unittest.cc
similarity index 97%
rename from common/certificate_checker_unittest.cc
rename to certificate_checker_unittest.cc
index c30acc5..20efce9 100644
--- a/common/certificate_checker_unittest.cc
+++ b/certificate_checker_unittest.cc
@@ -14,7 +14,7 @@
// limitations under the License.
//
-#include "update_engine/common/certificate_checker.h"
+#include "update_engine/certificate_checker.h"
#include <string>
@@ -24,8 +24,8 @@
#include <gtest/gtest.h>
#include "update_engine/common/constants.h"
-#include "update_engine/common/mock_certificate_checker.h"
#include "update_engine/common/mock_prefs.h"
+#include "update_engine/mock_certificate_checker.h"
using ::testing::DoAll;
using ::testing::Return;
diff --git a/common/file_fetcher.cc b/common/file_fetcher.cc
index 77dadd1..d0a109b 100644
--- a/common/file_fetcher.cc
+++ b/common/file_fetcher.cc
@@ -27,7 +27,6 @@
#include <base/strings/stringprintf.h>
#include <brillo/streams/file_stream.h>
-#include "update_engine/common/certificate_checker.h"
#include "update_engine/common/hardware_interface.h"
#include "update_engine/common/platform_constants.h"
diff --git a/common/hash_calculator_unittest.cc b/common/hash_calculator_unittest.cc
index 27dbc56..436e6a7 100644
--- a/common/hash_calculator_unittest.cc
+++ b/common/hash_calculator_unittest.cc
@@ -25,7 +25,6 @@
#include <brillo/secure_blob.h>
#include <gtest/gtest.h>
-#include "update_engine/common/libcurl_http_fetcher.h"
#include "update_engine/common/utils.h"
using std::string;
diff --git a/common/http_fetcher_unittest.cc b/common/http_fetcher_unittest.cc
index 9bc4373..f99007f 100644
--- a/common/http_fetcher_unittest.cc
+++ b/common/http_fetcher_unittest.cc
@@ -44,11 +44,11 @@
#include "update_engine/common/fake_hardware.h"
#include "update_engine/common/file_fetcher.h"
#include "update_engine/common/http_common.h"
-#include "update_engine/common/libcurl_http_fetcher.h"
#include "update_engine/common/mock_http_fetcher.h"
#include "update_engine/common/multi_range_http_fetcher.h"
#include "update_engine/common/test_utils.h"
#include "update_engine/common/utils.h"
+#include "update_engine/libcurl_http_fetcher.h"
#include "update_engine/mock_proxy_resolver.h"
#include "update_engine/proxy_resolver.h"
diff --git a/common/prefs.cc b/common/prefs.cc
index a4b97d0..12d06c0 100644
--- a/common/prefs.cc
+++ b/common/prefs.cc
@@ -29,31 +29,12 @@
namespace chromeos_update_engine {
-bool Prefs::Init(const base::FilePath& prefs_dir) {
- prefs_dir_ = prefs_dir;
- return true;
+bool PrefsBase::GetString(const string& key, string* value) const {
+ return storage_->GetKey(key, value);
}
-bool Prefs::GetString(const string& key, string* value) const {
- base::FilePath filename;
- TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename));
- if (!base::ReadFileToString(filename, value)) {
- LOG(INFO) << key << " not present in " << prefs_dir_.value();
- return false;
- }
- return true;
-}
-
-bool Prefs::SetString(const string& key, const string& value) {
- base::FilePath filename;
- TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename));
- if (!base::DirectoryExists(filename.DirName())) {
- // Only attempt to create the directory if it doesn't exist to avoid calls
- // to parent directories where we might not have permission to write to.
- TEST_AND_RETURN_FALSE(base::CreateDirectory(filename.DirName()));
- }
- TEST_AND_RETURN_FALSE(base::WriteFile(filename, value.data(), value.size()) ==
- static_cast<int>(value.size()));
+bool PrefsBase::SetString(const string& key, const string& value) {
+ TEST_AND_RETURN_FALSE(storage_->SetKey(key, value));
const auto observers_for_key = observers_.find(key);
if (observers_for_key != observers_.end()) {
std::vector<ObserverInterface*> copy_observers(observers_for_key->second);
@@ -63,7 +44,7 @@
return true;
}
-bool Prefs::GetInt64(const string& key, int64_t* value) const {
+bool PrefsBase::GetInt64(const string& key, int64_t* value) const {
string str_value;
if (!GetString(key, &str_value))
return false;
@@ -72,11 +53,11 @@
return true;
}
-bool Prefs::SetInt64(const string& key, const int64_t value) {
+bool PrefsBase::SetInt64(const string& key, const int64_t value) {
return SetString(key, base::Int64ToString(value));
}
-bool Prefs::GetBoolean(const string& key, bool* value) const {
+bool PrefsBase::GetBoolean(const string& key, bool* value) const {
string str_value;
if (!GetString(key, &str_value))
return false;
@@ -92,20 +73,16 @@
return false;
}
-bool Prefs::SetBoolean(const string& key, const bool value) {
+bool PrefsBase::SetBoolean(const string& key, const bool value) {
return SetString(key, value ? "true" : "false");
}
-bool Prefs::Exists(const string& key) const {
- base::FilePath filename;
- TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename));
- return base::PathExists(filename);
+bool PrefsBase::Exists(const string& key) const {
+ return storage_->KeyExists(key);
}
-bool Prefs::Delete(const string& key) {
- base::FilePath filename;
- TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename));
- TEST_AND_RETURN_FALSE(base::DeleteFile(filename, false));
+bool PrefsBase::Delete(const string& key) {
+ TEST_AND_RETURN_FALSE(storage_->DeleteKey(key));
const auto observers_for_key = observers_.find(key);
if (observers_for_key != observers_.end()) {
std::vector<ObserverInterface*> copy_observers(observers_for_key->second);
@@ -115,11 +92,11 @@
return true;
}
-void Prefs::AddObserver(const string& key, ObserverInterface* observer) {
+void PrefsBase::AddObserver(const string& key, ObserverInterface* observer) {
observers_[key].push_back(observer);
}
-void Prefs::RemoveObserver(const string& key, ObserverInterface* observer) {
+void PrefsBase::RemoveObserver(const string& key, ObserverInterface* observer) {
std::vector<ObserverInterface*>& observers_for_key = observers_[key];
auto observer_it =
std::find(observers_for_key.begin(), observers_for_key.end(), observer);
@@ -127,8 +104,55 @@
observers_for_key.erase(observer_it);
}
-bool Prefs::GetFileNameForKey(const string& key,
- base::FilePath* filename) const {
+// Prefs
+
+bool Prefs::Init(const base::FilePath& prefs_dir) {
+ return file_storage_.Init(prefs_dir);
+}
+
+bool Prefs::FileStorage::Init(const base::FilePath& prefs_dir) {
+ prefs_dir_ = prefs_dir;
+ return true;
+}
+
+bool Prefs::FileStorage::GetKey(const string& key, string* value) const {
+ base::FilePath filename;
+ TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename));
+ if (!base::ReadFileToString(filename, value)) {
+ LOG(INFO) << key << " not present in " << prefs_dir_.value();
+ return false;
+ }
+ return true;
+}
+
+bool Prefs::FileStorage::SetKey(const string& key, const string& value) {
+ base::FilePath filename;
+ TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename));
+ if (!base::DirectoryExists(filename.DirName())) {
+ // Only attempt to create the directory if it doesn't exist to avoid calls
+ // to parent directories where we might not have permission to write to.
+ TEST_AND_RETURN_FALSE(base::CreateDirectory(filename.DirName()));
+ }
+ TEST_AND_RETURN_FALSE(base::WriteFile(filename, value.data(), value.size()) ==
+ static_cast<int>(value.size()));
+ return true;
+}
+
+bool Prefs::FileStorage::KeyExists(const string& key) const {
+ base::FilePath filename;
+ TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename));
+ return base::PathExists(filename);
+}
+
+bool Prefs::FileStorage::DeleteKey(const string& key) {
+ base::FilePath filename;
+ TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename));
+ TEST_AND_RETURN_FALSE(base::DeleteFile(filename, false));
+ return true;
+}
+
+bool Prefs::FileStorage::GetFileNameForKey(const string& key,
+ base::FilePath* filename) const {
// Allows only non-empty keys containing [A-Za-z0-9_-].
TEST_AND_RETURN_FALSE(!key.empty());
for (size_t i = 0; i < key.size(); ++i) {
@@ -140,4 +164,33 @@
return true;
}
+// MemoryPrefs
+
+bool MemoryPrefs::MemoryStorage::GetKey(const string& key,
+ string* value) const {
+ auto it = values_.find(key);
+ if (it == values_.end())
+ return false;
+ *value = it->second;
+ return true;
+}
+
+bool MemoryPrefs::MemoryStorage::SetKey(const string& key,
+ const string& value) {
+ values_[key] = value;
+ return true;
+}
+
+bool MemoryPrefs::MemoryStorage::KeyExists(const string& key) const {
+ return values_.find(key) != values_.end();
+}
+
+bool MemoryPrefs::MemoryStorage::DeleteKey(const string& key) {
+ auto it = values_.find(key);
+ if (it == values_.end())
+ return false;
+ values_.erase(it);
+ return true;
+}
+
} // namespace chromeos_update_engine
diff --git a/common/prefs.h b/common/prefs.h
index f11abc3..0116454 100644
--- a/common/prefs.h
+++ b/common/prefs.h
@@ -28,18 +28,36 @@
namespace chromeos_update_engine {
-// Implements a preference store by storing the value associated with
-// a key in a separate file named after the key under a preference
-// store directory.
-
-class Prefs : public PrefsInterface {
+// Implements a preference store by storing the value associated with a key
+// in a given storage passed during construction.
+class PrefsBase : public PrefsInterface {
public:
- Prefs() = default;
+ // Storage interface used to set and retrieve keys.
+ class StorageInterface {
+ public:
+ StorageInterface() = default;
+ virtual ~StorageInterface() = default;
- // Initializes the store by associating this object with |prefs_dir|
- // as the preference store directory. Returns true on success, false
- // otherwise.
- bool Init(const base::FilePath& prefs_dir);
+ // Get the key named |key| and store its value in the referenced |value|.
+ // Returns whether the operation succeeded.
+ virtual bool GetKey(const std::string& key, std::string* value) const = 0;
+
+ // Set the value of the key named |key| to |value| regardless of the
+ // previous value. Returns whether the operation succeeded.
+ virtual bool SetKey(const std::string& key, const std::string& value) = 0;
+
+ // Returns whether the key named |key| exists.
+ virtual bool KeyExists(const std::string& key) const = 0;
+
+ // Deletes the value associated with the key name |key|. Returns whether the
+ // key was deleted.
+ virtual bool DeleteKey(const std::string& key) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(StorageInterface);
+ };
+
+ explicit PrefsBase(StorageInterface* storage) : storage_(storage) {}
// PrefsInterface methods.
bool GetString(const std::string& key, std::string* value) const override;
@@ -58,24 +76,93 @@
ObserverInterface* observer) override;
private:
+ // The registered observers watching for changes.
+ std::map<std::string, std::vector<ObserverInterface*>> observers_;
+
+ // The concrete implementation of the storage used for the keys.
+ StorageInterface* storage_;
+
+ DISALLOW_COPY_AND_ASSIGN(PrefsBase);
+};
+
+// Implements a preference store by storing the value associated with
+// a key in a separate file named after the key under a preference
+// store directory.
+
+class Prefs : public PrefsBase {
+ public:
+ Prefs() : PrefsBase(&file_storage_) {}
+
+ // Initializes the store by associating this object with |prefs_dir|
+ // as the preference store directory. Returns true on success, false
+ // otherwise.
+ bool Init(const base::FilePath& prefs_dir);
+
+ private:
FRIEND_TEST(PrefsTest, GetFileNameForKey);
FRIEND_TEST(PrefsTest, GetFileNameForKeyBadCharacter);
FRIEND_TEST(PrefsTest, GetFileNameForKeyEmpty);
- // Sets |filename| to the full path to the file containing the data
- // associated with |key|. Returns true on success, false otherwise.
- bool GetFileNameForKey(const std::string& key,
- base::FilePath* filename) const;
+ class FileStorage : public PrefsBase::StorageInterface {
+ public:
+ FileStorage() = default;
- // Preference store directory.
- base::FilePath prefs_dir_;
+ bool Init(const base::FilePath& prefs_dir);
- // The registered observers watching for changes.
- std::map<std::string, std::vector<ObserverInterface*>> observers_;
+ // PrefsBase::StorageInterface overrides.
+ bool GetKey(const std::string& key, std::string* value) const override;
+ bool SetKey(const std::string& key, const std::string& value) override;
+ bool KeyExists(const std::string& key) const override;
+ bool DeleteKey(const std::string& key) override;
+
+ private:
+ FRIEND_TEST(PrefsTest, GetFileNameForKey);
+ FRIEND_TEST(PrefsTest, GetFileNameForKeyBadCharacter);
+ FRIEND_TEST(PrefsTest, GetFileNameForKeyEmpty);
+
+ // Sets |filename| to the full path to the file containing the data
+ // associated with |key|. Returns true on success, false otherwise.
+ bool GetFileNameForKey(const std::string& key,
+ base::FilePath* filename) const;
+
+ // Preference store directory.
+ base::FilePath prefs_dir_;
+ };
+
+ // The concrete file storage implementation.
+ FileStorage file_storage_;
DISALLOW_COPY_AND_ASSIGN(Prefs);
};
+// Implements a preference store in memory. The stored values are lost when the
+// object is destroyed.
+
+class MemoryPrefs : public PrefsBase {
+ public:
+ MemoryPrefs() : PrefsBase(&mem_storage_) {}
+
+ private:
+ class MemoryStorage : public PrefsBase::StorageInterface {
+ public:
+ MemoryStorage() = default;
+
+ // PrefsBase::StorageInterface overrides.
+ bool GetKey(const std::string& key, std::string* value) const override;
+ bool SetKey(const std::string& key, const std::string& value) override;
+ bool KeyExists(const std::string& key) const override;
+ bool DeleteKey(const std::string& key) override;
+
+ private:
+ // The std::map holding the values in memory.
+ std::map<std::string, std::string> values_;
+ };
+
+ // The concrete memory storage implementation.
+ MemoryStorage mem_storage_;
+
+ DISALLOW_COPY_AND_ASSIGN(MemoryPrefs);
+};
} // namespace chromeos_update_engine
#endif // UPDATE_ENGINE_COMMON_PREFS_H_
diff --git a/common/prefs_unittest.cc b/common/prefs_unittest.cc
index d94623a..0822599 100644
--- a/common/prefs_unittest.cc
+++ b/common/prefs_unittest.cc
@@ -18,6 +18,7 @@
#include <inttypes.h>
+#include <limits>
#include <string>
#include <base/files/file_util.h>
@@ -62,18 +63,18 @@
const char kAllvalidCharsKey[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-";
base::FilePath path;
- EXPECT_TRUE(prefs_.GetFileNameForKey(kAllvalidCharsKey, &path));
+ EXPECT_TRUE(prefs_.file_storage_.GetFileNameForKey(kAllvalidCharsKey, &path));
EXPECT_EQ(prefs_dir_.Append(kAllvalidCharsKey).value(), path.value());
}
TEST_F(PrefsTest, GetFileNameForKeyBadCharacter) {
base::FilePath path;
- EXPECT_FALSE(prefs_.GetFileNameForKey("ABC abc", &path));
+ EXPECT_FALSE(prefs_.file_storage_.GetFileNameForKey("ABC abc", &path));
}
TEST_F(PrefsTest, GetFileNameForKeyEmpty) {
base::FilePath path;
- EXPECT_FALSE(prefs_.GetFileNameForKey("", &path));
+ EXPECT_FALSE(prefs_.file_storage_.GetFileNameForKey("", &path));
}
TEST_F(PrefsTest, GetString) {
@@ -338,4 +339,24 @@
prefs_.RemoveObserver(kInvalidKey, &mock_obserser);
}
+class MemoryPrefsTest : public ::testing::Test {
+ protected:
+ MemoryPrefs prefs_;
+};
+
+TEST_F(MemoryPrefsTest, BasicTest) {
+ EXPECT_FALSE(prefs_.Exists(kKey));
+ int64_t value = 0;
+ EXPECT_FALSE(prefs_.GetInt64(kKey, &value));
+
+ EXPECT_TRUE(prefs_.SetInt64(kKey, 1234));
+ EXPECT_TRUE(prefs_.Exists(kKey));
+ EXPECT_TRUE(prefs_.GetInt64(kKey, &value));
+ EXPECT_EQ(1234, value);
+
+ EXPECT_TRUE(prefs_.Delete(kKey));
+ EXPECT_FALSE(prefs_.Exists(kKey));
+ EXPECT_FALSE(prefs_.Delete(kKey));
+}
+
} // namespace chromeos_update_engine
diff --git a/common/utils.cc b/common/utils.cc
index 19c63c0..166cfb4 100644
--- a/common/utils.cc
+++ b/common/utils.cc
@@ -87,6 +87,11 @@
// The path to the kernel's boot_id.
const char kBootIdPath[] = "/proc/sys/kernel/random/boot_id";
+// A pointer to a null-terminated string containing the root directory where all
+// the temporary files should be created. If null, the system default is used
+// instead.
+const char* root_temp_dir = nullptr;
+
// Return true if |disk_name| is an MTD or a UBI device. Note that this test is
// simply based on the name of the device.
bool IsMtdDeviceName(const string& disk_name) {
@@ -143,13 +148,17 @@
}
base::FilePath temp_dir;
+ if (root_temp_dir) {
+ temp_dir = base::FilePath(root_temp_dir);
+ } else {
#ifdef __ANDROID__
- temp_dir = base::FilePath(constants::kNonVolatileDirectory).Append("tmp");
+ temp_dir = base::FilePath(constants::kNonVolatileDirectory).Append("tmp");
+#else
+ TEST_AND_RETURN_FALSE(base::GetTempDir(&temp_dir));
+#endif // __ANDROID__
+ }
if (!base::PathExists(temp_dir))
TEST_AND_RETURN_FALSE(base::CreateDirectory(temp_dir));
-#else
- TEST_AND_RETURN_FALSE(base::GetTempDir(&temp_dir));
-#endif // __ANDROID__
*template_path = temp_dir.Append(path);
return true;
}
@@ -158,6 +167,10 @@
namespace utils {
+void SetRootTempDir(const char* new_root_temp_dir) {
+ root_temp_dir = new_root_temp_dir;
+}
+
string ParseECVersion(string input_line) {
base::TrimWhitespaceASCII(input_line, base::TRIM_ALL, &input_line);
diff --git a/common/utils.h b/common/utils.h
index 63328b6..24bf702 100644
--- a/common/utils.h
+++ b/common/utils.h
@@ -131,6 +131,13 @@
// only returns true if "/dev/ubi%d_0" becomes available in |timeout| seconds.
bool TryAttachingUbiVolume(int volume_num, int timeout);
+// Setup the directory |new_root_temp_dir| to be used as the root directory for
+// temporary files instead of the system's default. If the directory doesn't
+// exists, it will be created when first used.
+// NOTE: The memory pointed by |new_root_temp_dir| must be available until this
+// function is called again with a different value.
+void SetRootTempDir(const char* new_root_temp_dir);
+
// If |base_filename_template| is neither absolute (starts with "/") nor
// explicitly relative to the current working directory (starts with "./" or
// "../"), then it is prepended the system's temporary directory. On success,
diff --git a/daemon_state_android.h b/daemon_state_android.h
index 69180bc..928a14e 100644
--- a/daemon_state_android.h
+++ b/daemon_state_android.h
@@ -20,8 +20,8 @@
#include <memory>
#include <set>
+#include "update_engine/certificate_checker.h"
#include "update_engine/common/boot_control_interface.h"
-#include "update_engine/common/certificate_checker.h"
#include "update_engine/common/hardware_interface.h"
#include "update_engine/common/prefs_interface.h"
#include "update_engine/daemon_state_interface.h"
@@ -43,7 +43,7 @@
void AddObserver(ServiceObserverInterface* observer) override;
void RemoveObserver(ServiceObserverInterface* observer) override;
- const std::set<ServiceObserverInterface*>& service_observers() {
+ const std::set<ServiceObserverInterface*>& service_observers() override {
return service_observers_;
}
diff --git a/daemon_state_interface.h b/daemon_state_interface.h
index a0944aa..2356816 100644
--- a/daemon_state_interface.h
+++ b/daemon_state_interface.h
@@ -20,6 +20,7 @@
#include "update_engine/service_observer_interface.h"
#include <memory>
+#include <set>
namespace chromeos_update_engine {
@@ -36,6 +37,9 @@
virtual void AddObserver(ServiceObserverInterface* observer) = 0;
virtual void RemoveObserver(ServiceObserverInterface* observer) = 0;
+ // Return the set of current observers.
+ virtual const std::set<ServiceObserverInterface*>& service_observers() = 0;
+
protected:
DaemonStateInterface() = default;
};
diff --git a/common/libcurl_http_fetcher.cc b/libcurl_http_fetcher.cc
similarity index 99%
rename from common/libcurl_http_fetcher.cc
rename to libcurl_http_fetcher.cc
index b2dffc2..04d5c06 100644
--- a/common/libcurl_http_fetcher.cc
+++ b/libcurl_http_fetcher.cc
@@ -14,7 +14,7 @@
// limitations under the License.
//
-#include "update_engine/common/libcurl_http_fetcher.h"
+#include "update_engine/libcurl_http_fetcher.h"
#include <algorithm>
#include <string>
@@ -26,7 +26,7 @@
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
-#include "update_engine/common/certificate_checker.h"
+#include "update_engine/certificate_checker.h"
#include "update_engine/common/hardware_interface.h"
#include "update_engine/common/platform_constants.h"
diff --git a/common/libcurl_http_fetcher.h b/libcurl_http_fetcher.h
similarity index 97%
rename from common/libcurl_http_fetcher.h
rename to libcurl_http_fetcher.h
index d126171..199c495 100644
--- a/common/libcurl_http_fetcher.h
+++ b/libcurl_http_fetcher.h
@@ -14,8 +14,8 @@
// limitations under the License.
//
-#ifndef UPDATE_ENGINE_COMMON_LIBCURL_HTTP_FETCHER_H_
-#define UPDATE_ENGINE_COMMON_LIBCURL_HTTP_FETCHER_H_
+#ifndef UPDATE_ENGINE_LIBCURL_HTTP_FETCHER_H_
+#define UPDATE_ENGINE_LIBCURL_HTTP_FETCHER_H_
#include <map>
#include <memory>
@@ -28,7 +28,7 @@
#include <base/macros.h>
#include <brillo/message_loops/message_loop.h>
-#include "update_engine/common/certificate_checker.h"
+#include "update_engine/certificate_checker.h"
#include "update_engine/common/hardware_interface.h"
#include "update_engine/common/http_fetcher.h"
@@ -266,4 +266,4 @@
} // namespace chromeos_update_engine
-#endif // UPDATE_ENGINE_COMMON_LIBCURL_HTTP_FETCHER_H_
+#endif // UPDATE_ENGINE_LIBCURL_HTTP_FETCHER_H_
diff --git a/metrics.h b/metrics.h
index bb9fa5e..7c369ee 100644
--- a/metrics.h
+++ b/metrics.h
@@ -19,7 +19,7 @@
#include <base/time/time.h>
-#include "update_engine/common/certificate_checker.h"
+#include "update_engine/certificate_checker.h"
#include "update_engine/common/constants.h"
#include "update_engine/common/error_code.h"
diff --git a/common/mock_certificate_checker.h b/mock_certificate_checker.h
similarity index 81%
rename from common/mock_certificate_checker.h
rename to mock_certificate_checker.h
index 1f55ca1..c86f502 100644
--- a/common/mock_certificate_checker.h
+++ b/mock_certificate_checker.h
@@ -14,13 +14,13 @@
// limitations under the License.
//
-#ifndef UPDATE_ENGINE_COMMON_MOCK_CERTIFICATE_CHECKER_H_
-#define UPDATE_ENGINE_COMMON_MOCK_CERTIFICATE_CHECKER_H_
+#ifndef UPDATE_ENGINE_MOCK_CERTIFICATE_CHECKER_H_
+#define UPDATE_ENGINE_MOCK_CERTIFICATE_CHECKER_H_
#include <gmock/gmock.h>
#include <openssl/ssl.h>
-#include "update_engine/common/certificate_checker.h"
+#include "update_engine/certificate_checker.h"
namespace chromeos_update_engine {
@@ -35,4 +35,4 @@
} // namespace chromeos_update_engine
-#endif // UPDATE_ENGINE_COMMON_MOCK_CERTIFICATE_CHECKER_H_
+#endif // UPDATE_ENGINE_MOCK_CERTIFICATE_CHECKER_H_
diff --git a/payload_consumer/delta_performer.cc b/payload_consumer/delta_performer.cc
index 4b9e528..a156132 100644
--- a/payload_consumer/delta_performer.cc
+++ b/payload_consumer/delta_performer.cc
@@ -844,6 +844,7 @@
(partition.has_postinstall_path() ? partition.postinstall_path()
: kPostinstallDefaultScript);
install_part.filesystem_type = partition.filesystem_type();
+ install_part.postinstall_optional = partition.postinstall_optional();
}
if (partition.has_old_partition_info()) {
diff --git a/payload_consumer/download_action.h b/payload_consumer/download_action.h
index fc32068..285930a 100644
--- a/payload_consumer/download_action.h
+++ b/payload_consumer/download_action.h
@@ -24,8 +24,6 @@
#include <memory>
#include <string>
-#include <curl/curl.h>
-
#include "update_engine/common/action.h"
#include "update_engine/common/boot_control_interface.h"
#include "update_engine/common/http_fetcher.h"
diff --git a/payload_consumer/install_plan.cc b/payload_consumer/install_plan.cc
index 51e85b3..b04da74 100644
--- a/payload_consumer/install_plan.cc
+++ b/payload_consumer/install_plan.cc
@@ -115,7 +115,8 @@
target_hash == that.target_hash &&
run_postinstall == that.run_postinstall &&
postinstall_path == that.postinstall_path &&
- filesystem_type == that.filesystem_type);
+ filesystem_type == that.filesystem_type &&
+ postinstall_optional == that.postinstall_optional);
}
} // namespace chromeos_update_engine
diff --git a/payload_consumer/install_plan.h b/payload_consumer/install_plan.h
index 454dd78..f15775e 100644
--- a/payload_consumer/install_plan.h
+++ b/payload_consumer/install_plan.h
@@ -95,6 +95,7 @@
bool run_postinstall{false};
std::string postinstall_path;
std::string filesystem_type;
+ bool postinstall_optional{false};
};
std::vector<Partition> partitions;
diff --git a/payload_consumer/postinstall_runner_action.cc b/payload_consumer/postinstall_runner_action.cc
index 09f5096..84f1edf 100644
--- a/payload_consumer/postinstall_runner_action.cc
+++ b/payload_consumer/postinstall_runner_action.cc
@@ -301,7 +301,14 @@
// to get back to FW A.
error_code = ErrorCode::kPostinstallFirmwareRONotUpdatable;
}
- return CompletePostinstall(error_code);
+
+ // If postinstall script for this partition is optional we can ignore the
+ // result.
+ if (install_plan_.partitions[current_partition_].postinstall_optional) {
+ LOG(INFO) << "Ignoring postinstall failure since it is optional";
+ } else {
+ return CompletePostinstall(error_code);
+ }
}
accumulated_weight_ += partition_weight_[current_partition_];
current_partition_++;
diff --git a/payload_generator/payload_file.cc b/payload_generator/payload_file.cc
index de81a39..2f95b21 100644
--- a/payload_generator/payload_file.cc
+++ b/payload_generator/payload_file.cc
@@ -138,6 +138,7 @@
partition->set_postinstall_path(part.postinstall.path);
if (!part.postinstall.filesystem_type.empty())
partition->set_filesystem_type(part.postinstall.filesystem_type);
+ partition->set_postinstall_optional(part.postinstall.optional);
}
for (const AnnotatedOperation& aop : part.aops) {
*partition->add_operations() = aop.op;
diff --git a/payload_generator/payload_generation_config.cc b/payload_generator/payload_generation_config.cc
index dc2ced6..8ef30a0 100644
--- a/payload_generator/payload_generation_config.cc
+++ b/payload_generator/payload_generation_config.cc
@@ -27,7 +27,7 @@
namespace chromeos_update_engine {
bool PostInstallConfig::IsEmpty() const {
- return run == false && path.empty() && filesystem_type.empty();
+ return !run && path.empty() && filesystem_type.empty() && !optional;
}
bool PartitionConfig::ValidateExists() const {
@@ -95,6 +95,8 @@
store.GetString("POSTINSTALL_PATH_" + part.name, &part.postinstall.path);
store.GetString("FILESYSTEM_TYPE_" + part.name,
&part.postinstall.filesystem_type);
+ store.GetBoolean("POSTINSTALL_OPTIONAL_" + part.name,
+ &part.postinstall.optional);
}
if (!found_postinstall) {
LOG(ERROR) << "No valid postinstall config found.";
diff --git a/payload_generator/payload_generation_config.h b/payload_generator/payload_generation_config.h
index 2601821..373c7cd 100644
--- a/payload_generator/payload_generation_config.h
+++ b/payload_generator/payload_generation_config.h
@@ -46,6 +46,9 @@
// The filesystem type used to mount the partition in order to run the
// post-install program.
std::string filesystem_type;
+
+ // Whether this postinstall script should be ignored if it fails.
+ bool optional = false;
};
struct PartitionConfig {
diff --git a/payload_generator/payload_generation_config_unittest.cc b/payload_generator/payload_generation_config_unittest.cc
index 122d94a..3545056 100644
--- a/payload_generator/payload_generation_config_unittest.cc
+++ b/payload_generator/payload_generation_config_unittest.cc
@@ -29,12 +29,14 @@
EXPECT_TRUE(
store.LoadFromString("RUN_POSTINSTALL_root=true\n"
"POSTINSTALL_PATH_root=postinstall\n"
- "FILESYSTEM_TYPE_root=ext4"));
+ "FILESYSTEM_TYPE_root=ext4\n"
+ "POSTINSTALL_OPTIONAL_root=true"));
EXPECT_TRUE(image_config.LoadPostInstallConfig(store));
EXPECT_FALSE(image_config.partitions[0].postinstall.IsEmpty());
EXPECT_EQ(true, image_config.partitions[0].postinstall.run);
EXPECT_EQ("postinstall", image_config.partitions[0].postinstall.path);
EXPECT_EQ("ext4", image_config.partitions[0].postinstall.filesystem_type);
+ EXPECT_TRUE(image_config.partitions[0].postinstall.optional);
}
TEST_F(PayloadGenerationConfigTest, LoadPostInstallConfigNameMismatchTest) {
diff --git a/real_system_state.h b/real_system_state.h
index 071e3e0..480b4b7 100644
--- a/real_system_state.h
+++ b/real_system_state.h
@@ -20,6 +20,7 @@
#include "update_engine/system_state.h"
#include <memory>
+#include <set>
#include <debugd/dbus-proxies.h>
#include <metrics/metrics_library.h>
@@ -27,8 +28,8 @@
#include <power_manager/dbus-proxies.h>
#include <session_manager/dbus-proxies.h>
+#include "update_engine/certificate_checker.h"
#include "update_engine/common/boot_control_interface.h"
-#include "update_engine/common/certificate_checker.h"
#include "update_engine/common/clock.h"
#include "update_engine/common/hardware_interface.h"
#include "update_engine/common/prefs.h"
@@ -63,6 +64,10 @@
void AddObserver(ServiceObserverInterface* observer) override;
void RemoveObserver(ServiceObserverInterface* observer) override;
+ const std::set<ServiceObserverInterface*>& service_observers() override {
+ CHECK(update_attempter_.get());
+ return update_attempter_->service_observers();
+ }
// SystemState overrides.
inline void set_device_policy(
diff --git a/sideload_main.cc b/sideload_main.cc
new file mode 100644
index 0000000..35ed11b
--- /dev/null
+++ b/sideload_main.cc
@@ -0,0 +1,227 @@
+//
+// Copyright (C) 2016 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 <xz.h>
+
+#include <string>
+#include <vector>
+
+#include <base/command_line.h>
+#include <base/logging.h>
+#include <base/strings/string_split.h>
+#include <base/strings/stringprintf.h>
+#include <brillo/asynchronous_signal_handler.h>
+#include <brillo/flag_helper.h>
+#include <brillo/make_unique_ptr.h>
+#include <brillo/message_loops/base_message_loop.h>
+#include <brillo/streams/file_stream.h>
+#include <brillo/streams/stream.h>
+
+#include "update_engine/common/boot_control.h"
+#include "update_engine/common/error_code_utils.h"
+#include "update_engine/common/hardware.h"
+#include "update_engine/common/prefs.h"
+#include "update_engine/common/subprocess.h"
+#include "update_engine/common/terminator.h"
+#include "update_engine/common/utils.h"
+#include "update_engine/update_attempter_android.h"
+
+using std::string;
+using std::vector;
+using update_engine::UpdateStatus;
+
+namespace {
+// The root directory used for temporary files in update_engine_sideload.
+const char kSideloadRootTempDir[] = "/tmp/update_engine_sideload";
+} // namespace
+
+namespace chromeos_update_engine {
+namespace {
+
+void SetupLogging() {
+ string log_file;
+ logging::LoggingSettings log_settings;
+ log_settings.lock_log = logging::DONT_LOCK_LOG_FILE;
+ log_settings.delete_old = logging::APPEND_TO_OLD_LOG_FILE;
+ log_settings.log_file = nullptr;
+ log_settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
+
+ logging::InitLogging(log_settings);
+}
+
+class SideloadDaemonState : public DaemonStateInterface,
+ public ServiceObserverInterface {
+ public:
+ explicit SideloadDaemonState(brillo::StreamPtr status_stream)
+ : status_stream_(std::move(status_stream)) {
+ // Add this class as the only observer.
+ observers_.insert(this);
+ }
+ ~SideloadDaemonState() override = default;
+
+ // DaemonStateInterface overrides.
+ bool StartUpdater() override { return true; }
+ void AddObserver(ServiceObserverInterface* observer) override {}
+ void RemoveObserver(ServiceObserverInterface* observer) override {}
+ const std::set<ServiceObserverInterface*>& service_observers() override {
+ return observers_;
+ }
+
+ // ServiceObserverInterface overrides.
+ void SendStatusUpdate(int64_t last_checked_time,
+ double progress,
+ UpdateStatus status,
+ const string& new_version,
+ int64_t new_size) override {
+ if (status_ != status && (status == UpdateStatus::DOWNLOADING ||
+ status == UpdateStatus::FINALIZING)) {
+ // Split the progress bar in two parts for the two stages DOWNLOADING and
+ // FINALIZING.
+ ReportStatus(base::StringPrintf(
+ "ui_print Step %d/2", status == UpdateStatus::DOWNLOADING ? 1 : 2));
+ ReportStatus(base::StringPrintf("progress 0.5 0"));
+ }
+ if (status_ != status || fabs(progress - progress_) > 0.005) {
+ ReportStatus(base::StringPrintf("set_progress %.lf", progress));
+ }
+ progress_ = progress;
+ status_ = status;
+ }
+
+ void SendPayloadApplicationComplete(ErrorCode error_code) override {
+ if (error_code != ErrorCode::kSuccess) {
+ ReportStatus(
+ base::StringPrintf("ui_print Error applying update: %d (%s)",
+ error_code,
+ utils::ErrorCodeToString(error_code).c_str()));
+ }
+ error_code_ = error_code;
+ brillo::MessageLoop::current()->BreakLoop();
+ }
+
+ void SendChannelChangeUpdate(const string& tracking_channel) override {}
+
+ // Getters.
+ UpdateStatus status() { return status_; }
+ ErrorCode error_code() { return error_code_; }
+
+ private:
+ // Report a status message in the status_stream_, if any. These messages
+ // should conform to the specification defined in the Android recovery.
+ void ReportStatus(const string& message) {
+ if (!status_stream_)
+ return;
+ string status_line = message + "\n";
+ status_stream_->WriteAllBlocking(
+ status_line.data(), status_line.size(), nullptr);
+ }
+
+ std::set<ServiceObserverInterface*> observers_;
+ brillo::StreamPtr status_stream_;
+
+ // The last status and error code reported.
+ UpdateStatus status_{UpdateStatus::IDLE};
+ ErrorCode error_code_{ErrorCode::kSuccess};
+ double progress_{-1.};
+};
+
+// Apply an update payload directly from the given payload URI.
+bool ApplyUpdatePayload(const string& payload,
+ int64_t payload_offset,
+ int64_t payload_size,
+ const vector<string>& headers,
+ int64_t status_fd) {
+ base::MessageLoopForIO base_loop;
+ brillo::BaseMessageLoop loop(&base_loop);
+ loop.SetAsCurrent();
+
+ // Setup the subprocess handler.
+ brillo::AsynchronousSignalHandler handler;
+ handler.Init();
+ Subprocess subprocess;
+ subprocess.Init(&handler);
+
+ SideloadDaemonState sideload_daemon_state(
+ brillo::FileStream::FromFileDescriptor(status_fd, true, nullptr));
+
+ // During the sideload we don't access the prefs persisted on disk but instead
+ // use a temporary memory storage.
+ MemoryPrefs prefs;
+
+ std::unique_ptr<BootControlInterface> boot_control =
+ boot_control::CreateBootControl();
+ if (!boot_control) {
+ LOG(ERROR) << "Error initializing the BootControlInterface.";
+ return false;
+ }
+
+ std::unique_ptr<HardwareInterface> hardware = hardware::CreateHardware();
+ if (!hardware) {
+ LOG(ERROR) << "Error initializing the HardwareInterface.";
+ return false;
+ }
+
+ UpdateAttempterAndroid update_attempter(
+ &sideload_daemon_state, &prefs, boot_control.get(), hardware.get());
+ update_attempter.Init();
+
+ TEST_AND_RETURN_FALSE(update_attempter.ApplyPayload(
+ payload, payload_offset, payload_size, headers, nullptr));
+
+ loop.Run();
+ return sideload_daemon_state.status() == UpdateStatus::UPDATED_NEED_REBOOT;
+}
+
+} // namespace
+} // namespace chromeos_update_engine
+
+int main(int argc, char** argv) {
+ DEFINE_string(payload,
+ "file:///data/payload.bin",
+ "The URI to the update payload to use.");
+ DEFINE_int64(
+ offset, 0, "The offset in the payload where the CrAU update starts. ");
+ DEFINE_int64(size,
+ 0,
+ "The size of the CrAU part of the payload. If 0 is passed, it "
+ "will be autodetected.");
+ DEFINE_string(headers,
+ "",
+ "A list of key-value pairs, one element of the list per line.");
+ DEFINE_int64(status_fd, -1, "A file descriptor to notify the update status.");
+
+ chromeos_update_engine::Terminator::Init();
+ chromeos_update_engine::SetupLogging();
+ brillo::FlagHelper::Init(argc, argv, "Update Engine Sideload");
+
+ LOG(INFO) << "Update Engine Sideloading starting";
+
+ // xz-embedded requires to initialize its CRC-32 table once on startup.
+ xz_crc32_init();
+
+ // When called from recovery, /data is not accessible, so we need to use
+ // /tmp for temporary files.
+ chromeos_update_engine::utils::SetRootTempDir(kSideloadRootTempDir);
+
+ vector<string> headers = base::SplitString(
+ FLAGS_headers, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+
+ if (!chromeos_update_engine::ApplyUpdatePayload(
+ FLAGS_payload, FLAGS_offset, FLAGS_size, headers, FLAGS_status_fd))
+ return 1;
+
+ return 0;
+}
diff --git a/update_attempter.cc b/update_attempter.cc
index 4cafd00..c773063 100644
--- a/update_attempter.cc
+++ b/update_attempter.cc
@@ -41,18 +41,18 @@
#include <power_manager/dbus-proxies.h>
#include <update_engine/dbus-constants.h>
+#include "update_engine/certificate_checker.h"
#include "update_engine/common/boot_control_interface.h"
-#include "update_engine/common/certificate_checker.h"
#include "update_engine/common/clock_interface.h"
#include "update_engine/common/constants.h"
#include "update_engine/common/hardware_interface.h"
-#include "update_engine/common/libcurl_http_fetcher.h"
#include "update_engine/common/multi_range_http_fetcher.h"
#include "update_engine/common/platform_constants.h"
#include "update_engine/common/prefs_interface.h"
#include "update_engine/common/subprocess.h"
#include "update_engine/common/utils.h"
#include "update_engine/dbus_service.h"
+#include "update_engine/libcurl_http_fetcher.h"
#include "update_engine/metrics.h"
#include "update_engine/omaha_request_action.h"
#include "update_engine/omaha_request_params.h"
diff --git a/update_attempter.h b/update_attempter.h
index b045614..92683e6 100644
--- a/update_attempter.h
+++ b/update_attempter.h
@@ -31,9 +31,9 @@
#include "debugd/dbus-proxies.h"
#include "update_engine/chrome_browser_proxy_resolver.h"
+#include "update_engine/certificate_checker.h"
#include "update_engine/client_library/include/update_engine/update_status.h"
#include "update_engine/common/action_processor.h"
-#include "update_engine/common/certificate_checker.h"
#include "update_engine/common/cpu_limiter.h"
#include "update_engine/libcros_proxy.h"
#include "update_engine/omaha_request_params.h"
@@ -244,6 +244,10 @@
service_observers_.erase(observer);
}
+ const std::set<ServiceObserverInterface*>& service_observers() {
+ return service_observers_;
+ }
+
// Remove all the observers.
void ClearObservers() { service_observers_.clear(); }
diff --git a/update_attempter_android.cc b/update_attempter_android.cc
index 699ea97..c42b266 100644
--- a/update_attempter_android.cc
+++ b/update_attempter_android.cc
@@ -29,16 +29,21 @@
#include "update_engine/common/constants.h"
#include "update_engine/common/file_fetcher.h"
-#include "update_engine/common/libcurl_http_fetcher.h"
#include "update_engine/common/multi_range_http_fetcher.h"
#include "update_engine/common/utils.h"
-#include "update_engine/daemon_state_android.h"
+#include "update_engine/daemon_state_interface.h"
#include "update_engine/network_selector.h"
#include "update_engine/payload_consumer/download_action.h"
#include "update_engine/payload_consumer/filesystem_verifier_action.h"
#include "update_engine/payload_consumer/postinstall_runner_action.h"
#include "update_engine/update_status_utils.h"
+#ifndef _UE_SIDELOAD
+// Do not include support for external HTTP(s) urls when building
+// update_engine_sideload.
+#include "update_engine/libcurl_http_fetcher.h"
+#endif
+
using base::Bind;
using base::TimeDelta;
using base::TimeTicks;
@@ -72,7 +77,7 @@
} // namespace
UpdateAttempterAndroid::UpdateAttempterAndroid(
- DaemonStateAndroid* daemon_state,
+ DaemonStateInterface* daemon_state,
PrefsInterface* prefs,
BootControlInterface* boot_control,
HardwareInterface* hardware)
@@ -300,7 +305,7 @@
default:
// Ignore all other error codes.
break;
- }
+ }
TerminateUpdateAndNotify(code);
}
@@ -433,10 +438,14 @@
DLOG(INFO) << "Using FileFetcher for file URL.";
download_fetcher = new FileFetcher();
} else {
+#ifdef _UE_SIDELOAD
+ LOG(FATAL) << "Unsupported sideload URI: " << url;
+#else
LibcurlHttpFetcher* libcurl_fetcher =
new LibcurlHttpFetcher(&proxy_resolver_, hardware_);
libcurl_fetcher->set_server_to_check(ServerToCheck::kDownload);
download_fetcher = libcurl_fetcher;
+#endif // _UE_SIDELOAD
}
shared_ptr<DownloadAction> download_action(new DownloadAction(
prefs_,
diff --git a/update_attempter_android.h b/update_attempter_android.h
index 9e91dca..2617318 100644
--- a/update_attempter_android.h
+++ b/update_attempter_android.h
@@ -31,6 +31,7 @@
#include "update_engine/common/cpu_limiter.h"
#include "update_engine/common/hardware_interface.h"
#include "update_engine/common/prefs_interface.h"
+#include "update_engine/daemon_state_interface.h"
#include "update_engine/network_selector_interface.h"
#include "update_engine/payload_consumer/download_action.h"
#include "update_engine/payload_consumer/postinstall_runner_action.h"
@@ -39,8 +40,6 @@
namespace chromeos_update_engine {
-class DaemonStateAndroid;
-
class UpdateAttempterAndroid
: public ServiceDelegateAndroidInterface,
public ActionProcessorDelegate,
@@ -49,7 +48,7 @@
public:
using UpdateStatus = update_engine::UpdateStatus;
- UpdateAttempterAndroid(DaemonStateAndroid* daemon_state,
+ UpdateAttempterAndroid(DaemonStateInterface* daemon_state,
PrefsInterface* prefs,
BootControlInterface* boot_control_,
HardwareInterface* hardware_);
@@ -123,7 +122,7 @@
// Returns whether an update was completed in the current boot.
bool UpdateCompletedOnThisBoot();
- DaemonStateAndroid* daemon_state_;
+ DaemonStateInterface* daemon_state_;
// DaemonStateAndroid pointers.
PrefsInterface* prefs_;
diff --git a/update_metadata.proto b/update_metadata.proto
index 222542f..454c736 100644
--- a/update_metadata.proto
+++ b/update_metadata.proto
@@ -235,6 +235,10 @@
// associated operation blobs (in operations[i].data_offset, data_length)
// should be stored contiguously and in the same order.
repeated InstallOperation operations = 8;
+
+ // Whether a failure in the postinstall step for this partition should be
+ // ignored.
+ optional bool postinstall_optional = 9;
}
message DeltaArchiveManifest {