Merge "Merge remote-tracking branch 'remotes/aosp/upstream-master' into merge-cros"
diff --git a/BUILD.gn b/BUILD.gn
index 9575fab..aec447c 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -44,6 +44,7 @@
":test_subprocess",
":update_engine-test_images",
":update_engine-testkeys",
+ ":update_engine-testkeys-ec",
":update_engine_test_libs",
":update_engine_unittests",
]
@@ -60,6 +61,7 @@
pkg_config("target_defaults") {
cflags_cc = [
"-fno-strict-aliasing",
+ "-std=gnu++17",
"-Wnon-virtual-dtor",
]
cflags = [
@@ -75,6 +77,7 @@
"__CHROMEOS__",
"_FILE_OFFSET_BITS=64",
"_POSIX_C_SOURCE=199309L",
+ "USE_CFM=${use.cfm}",
"USE_DBUS=${use.dbus}",
"USE_FEC=0",
"USE_HWID_OVERRIDE=${use.hwid_override}",
@@ -92,7 +95,7 @@
# NOSORT
pkg_deps = [
"libbrillo",
- "libchrome-${libbase_ver}",
+ "libchrome",
# system_api depends on protobuf (or protobuf-lite). It must appear
# before protobuf here or the linker flags won't be in the right
@@ -217,6 +220,7 @@
"payload_state.cc",
"power_manager_chromeos.cc",
"real_system_state.cc",
+ "requisition_util.cc",
"shill_proxy.cc",
"update_attempter.cc",
"update_boot_flags_action.cc",
@@ -258,7 +262,7 @@
"expat",
"libcurl",
"libdebugd-client",
- "libmetrics-${libbase_ver}",
+ "libmetrics",
"libpower_manager-client",
"libsession_manager-client",
"libshill-client",
@@ -418,10 +422,20 @@
openssl_pem_out_dir = "include/update_engine"
sources = [
"unittest_key.pem",
+ "unittest_key_RSA4096.pem",
"unittest_key2.pem",
]
}
+ genopenssl_key("update_engine-testkeys-ec") {
+ openssl_pem_in_dir = "."
+ openssl_pem_out_dir = "include/update_engine"
+ openssl_pem_algorithm = "ec"
+ sources = [
+ "unittest_key_EC.pem",
+ ]
+ }
+
# Unpacks sample images used for testing.
tar_bunzip2("update_engine-test_images") {
image_out_dir = "."
@@ -515,11 +529,13 @@
"payload_generator/squashfs_filesystem_unittest.cc",
"payload_generator/zip_unittest.cc",
"payload_state_unittest.cc",
+ "requisition_util_unittest.cc",
"testrunner.cc",
"update_attempter_unittest.cc",
"update_boot_flags_action_unittest.cc",
"update_manager/boxed_value_unittest.cc",
"update_manager/chromeos_policy_unittest.cc",
+ "update_manager/enterprise_device_policy_impl_unittest.cc",
"update_manager/evaluation_context_unittest.cc",
"update_manager/generic_variables_unittest.cc",
"update_manager/prng_unittest.cc",
@@ -548,7 +564,7 @@
]
pkg_deps = [
"libbrillo-test",
- "libchrome-test-${libbase_ver}",
+ "libchrome-test",
"libdebugd-client-test",
"libpower_manager-client-test",
"libsession_manager-client-test",
@@ -572,7 +588,7 @@
]
pkg_deps = [
"libbrillo-test",
- "libchrome-test-${libbase_ver}",
+ "libchrome-test",
]
deps = [
":libupdate_engine",
@@ -587,7 +603,7 @@
]
pkg_deps = [
"libbrillo-test",
- "libchrome-test-${libbase_ver}",
+ "libchrome-test",
]
deps = [
":libupdate_engine",
diff --git a/boot_control_chromeos.cc b/boot_control_chromeos.cc
index 95456f0..da2c891 100644
--- a/boot_control_chromeos.cc
+++ b/boot_control_chromeos.cc
@@ -128,8 +128,9 @@
}
if (current_slot_ >= num_slots_) {
LOG(ERROR) << "Couldn't find the slot number corresponding to the "
- << "partition " << boot_device << ", number of slots: "
- << num_slots_ << ". This device is not updateable.";
+ << "partition " << boot_device
+ << ", number of slots: " << num_slots_
+ << ". This device is not updateable.";
num_slots_ = 1;
current_slot_ = BootControlInterface::kInvalidSlot;
return false;
diff --git a/client_library/client_dbus.cc b/client_library/client_dbus.cc
index 8e9a7fd..30ad78c 100644
--- a/client_library/client_dbus.cc
+++ b/client_library/client_dbus.cc
@@ -16,7 +16,7 @@
#include "update_engine/client_library/client_dbus.h"
-#include <base/message_loop/message_loop.h>
+#include <base/message_loop/message_loop_current.h>
#include <memory>
diff --git a/common/constants.cc b/common/constants.cc
index c85ba54..8883668 100644
--- a/common/constants.cc
+++ b/common/constants.cc
@@ -64,6 +64,8 @@
const char kPrefsP2PFirstAttemptTimestamp[] = "p2p-first-attempt-timestamp";
const char kPrefsP2PNumAttempts[] = "p2p-num-attempts";
const char kPrefsPayloadAttemptNumber[] = "payload-attempt-number";
+const char kPrefsTestUpdateCheckIntervalTimeout[] =
+ "test-update-check-interval-timeout";
// Keep |kPrefsPingActive| in sync with |kDlcMetadataFilePingActive| in
// dlcservice.
const char kPrefsPingActive[] = "active";
diff --git a/common/constants.h b/common/constants.h
index 7170201..3685102 100644
--- a/common/constants.h
+++ b/common/constants.h
@@ -67,6 +67,7 @@
extern const char kPrefsP2PFirstAttemptTimestamp[];
extern const char kPrefsP2PNumAttempts[];
extern const char kPrefsPayloadAttemptNumber[];
+extern const char kPrefsTestUpdateCheckIntervalTimeout[];
extern const char kPrefsPingActive[];
extern const char kPrefsPingLastActive[];
extern const char kPrefsPingLastRollcall[];
diff --git a/common/error_code.h b/common/error_code.h
index e473a05..7d9cfff 100644
--- a/common/error_code.h
+++ b/common/error_code.h
@@ -85,6 +85,7 @@
kUnresolvedHostRecovered = 59,
kNotEnoughSpace = 60,
kDeviceCorrupted = 61,
+ kPackageExcludedFromUpdate = 62,
// VERY IMPORTANT! When adding new error codes:
//
diff --git a/common/error_code_utils.cc b/common/error_code_utils.cc
index 64df24a..cda4c7e 100644
--- a/common/error_code_utils.cc
+++ b/common/error_code_utils.cc
@@ -171,6 +171,8 @@
return "ErrorCode::kNotEnoughSpace";
case ErrorCode::kDeviceCorrupted:
return "ErrorCode::kDeviceCorrupted";
+ case ErrorCode::kPackageExcludedFromUpdate:
+ return "ErrorCode::kPackageExcludedFromUpdate";
// Don't add a default case to let the compiler warn about newly added
// error codes which should be added here.
}
diff --git a/common/fake_boot_control.h b/common/fake_boot_control.h
index 5d8823a..98b93e6 100644
--- a/common/fake_boot_control.h
+++ b/common/fake_boot_control.h
@@ -116,7 +116,7 @@
is_bootable_[slot] = bootable;
}
- DynamicPartitionControlInterface* GetDynamicPartitionControl() {
+ DynamicPartitionControlInterface* GetDynamicPartitionControl() override {
return dynamic_partition_control_.get();
}
diff --git a/common/fake_hardware.h b/common/fake_hardware.h
index 82382ff..00a212e 100644
--- a/common/fake_hardware.h
+++ b/common/fake_hardware.h
@@ -76,10 +76,6 @@
std::string GetHardwareClass() const override { return hardware_class_; }
- std::string GetFirmwareVersion() const override { return firmware_version_; }
-
- std::string GetECVersion() const override { return ec_version_; }
-
std::string GetDeviceRequisition() const override {
return device_requisition_;
}
@@ -176,12 +172,6 @@
hardware_class_ = hardware_class;
}
- void SetFirmwareVersion(const std::string& firmware_version) {
- firmware_version_ = firmware_version;
- }
-
- void SetECVersion(const std::string& ec_version) { ec_version_ = ec_version; }
-
void SetDeviceRequisition(const std::string& requisition) {
device_requisition_ = requisition;
}
@@ -233,8 +223,6 @@
// Jan 20, 2007
base::Time oobe_timestamp_{base::Time::FromTimeT(1169280000)};
std::string hardware_class_{"Fake HWID BLAH-1234"};
- std::string firmware_version_{"Fake Firmware v1.0.1"};
- std::string ec_version_{"Fake EC v1.0a"};
std::string device_requisition_{"fake_requisition"};
int min_kernel_key_version_{kMinKernelKeyVersion};
int min_firmware_key_version_{kMinFirmwareKeyVersion};
diff --git a/common/hardware_interface.h b/common/hardware_interface.h
index b37b007..cad32fc 100644
--- a/common/hardware_interface.h
+++ b/common/hardware_interface.h
@@ -64,14 +64,6 @@
// Returns the HWID or an empty string on error.
virtual std::string GetHardwareClass() const = 0;
- // Returns the firmware version or an empty string if the system is
- // not running chrome os firmware.
- virtual std::string GetFirmwareVersion() const = 0;
-
- // Returns the ec version or an empty string if the system is not
- // running a custom chrome os ec.
- virtual std::string GetECVersion() const = 0;
-
// Returns the OEM device requisition or an empty string if the system does
// not have a requisition, or if not running Chrome OS.
virtual std::string GetDeviceRequisition() const = 0;
diff --git a/common/hash_calculator_unittest.cc b/common/hash_calculator_unittest.cc
index e8f73d5..fe7d543 100644
--- a/common/hash_calculator_unittest.cc
+++ b/common/hash_calculator_unittest.cc
@@ -104,7 +104,7 @@
}
TEST_F(HashCalculatorTest, UpdateFileSimpleTest) {
- test_utils::ScopedTempFile data_file("data.XXXXXX");
+ ScopedTempFile data_file("data.XXXXXX");
ASSERT_TRUE(test_utils::WriteFileString(data_file.path(), "hi"));
for (const int length : {-1, 2, 10}) {
@@ -126,7 +126,7 @@
}
TEST_F(HashCalculatorTest, RawHashOfFileSimpleTest) {
- test_utils::ScopedTempFile data_file("data.XXXXXX");
+ ScopedTempFile data_file("data.XXXXXX");
ASSERT_TRUE(test_utils::WriteFileString(data_file.path(), "hi"));
for (const int length : {-1, 2, 10}) {
diff --git a/common/http_fetcher_unittest.cc b/common/http_fetcher_unittest.cc
index 9338087..99ea99b 100644
--- a/common/http_fetcher_unittest.cc
+++ b/common/http_fetcher_unittest.cc
@@ -28,11 +28,16 @@
#include <base/bind.h>
#include <base/location.h>
#include <base/logging.h>
+#if BASE_VER < 780000 // Android
#include <base/message_loop/message_loop.h>
+#endif // BASE_VER < 780000
#include <base/stl_util.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
+#if BASE_VER >= 780000 // CrOS
+#include <base/task/single_thread_task_executor.h>
+#endif // BASE_VER >= 780000
#include <base/time/time.h>
#include <brillo/message_loops/base_message_loop.h>
#include <brillo/message_loops/message_loop.h>
@@ -364,7 +369,7 @@
HttpServer* CreateServer() override { return new NullHttpServer; }
private:
- test_utils::ScopedTempFile temp_file_{"ue_file_fetcher.XXXXXX"};
+ ScopedTempFile temp_file_{"ue_file_fetcher.XXXXXX"};
};
class MultiRangeHttpFetcherOverFileFetcherTest : public FileFetcherTest {
@@ -403,8 +408,13 @@
template <typename T>
class HttpFetcherTest : public ::testing::Test {
public:
+#if BASE_VER < 780000 // Android
base::MessageLoopForIO base_loop_;
brillo::BaseMessageLoop loop_{&base_loop_};
+#else // Chrome OS
+ base::SingleThreadTaskExecutor base_loop_{base::MessagePumpType::IO};
+ brillo::BaseMessageLoop loop_{base_loop_.task_runner()};
+#endif // BASE_VER < 780000
T test_;
diff --git a/common/mock_hardware.h b/common/mock_hardware.h
index 84c0c5b..071906b 100644
--- a/common/mock_hardware.h
+++ b/common/mock_hardware.h
@@ -45,11 +45,6 @@
ON_CALL(*this, GetHardwareClass())
.WillByDefault(
testing::Invoke(&fake_, &FakeHardware::GetHardwareClass));
- ON_CALL(*this, GetFirmwareVersion())
- .WillByDefault(
- testing::Invoke(&fake_, &FakeHardware::GetFirmwareVersion));
- ON_CALL(*this, GetECVersion())
- .WillByDefault(testing::Invoke(&fake_, &FakeHardware::GetECVersion));
ON_CALL(*this, GetMinKernelKeyVersion())
.WillByDefault(
testing::Invoke(&fake_, &FakeHardware::GetMinKernelKeyVersion));
@@ -90,8 +85,6 @@
MOCK_CONST_METHOD0(IsOOBEEnabled, bool());
MOCK_CONST_METHOD1(IsOOBEComplete, bool(base::Time* out_time_of_oobe));
MOCK_CONST_METHOD0(GetHardwareClass, std::string());
- MOCK_CONST_METHOD0(GetFirmwareVersion, std::string());
- MOCK_CONST_METHOD0(GetECVersion, std::string());
MOCK_CONST_METHOD0(GetMinKernelKeyVersion, int());
MOCK_CONST_METHOD0(GetMinFirmwareKeyVersion, int());
MOCK_CONST_METHOD0(GetMaxFirmwareKeyRollforward, int());
diff --git a/common/subprocess.h b/common/subprocess.h
index 179a5c5..2ed8b81 100644
--- a/common/subprocess.h
+++ b/common/subprocess.h
@@ -37,7 +37,7 @@
#include <brillo/process.h>
#include <brillo/process_reaper.h>
#endif // __CHROMEOS__
-#include <gtest/gtest_prod.h> // for FRIEND_TEST
+#include <gtest/gtest_prod.h>
// The Subprocess class is a singleton. It's used to spawn off a subprocess
// and get notified when the subprocess exits. The result of Exec() can
diff --git a/common/subprocess_unittest.cc b/common/subprocess_unittest.cc
index b4d068f..ff4158e 100644
--- a/common/subprocess_unittest.cc
+++ b/common/subprocess_unittest.cc
@@ -28,9 +28,14 @@
#include <base/bind.h>
#include <base/files/scoped_temp_dir.h>
#include <base/location.h>
+#if BASE_VER < 780000 // Android
#include <base/message_loop/message_loop.h>
+#endif // BASE_VER < 780000
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
+#if BASE_VER >= 780000 // Chrome OS
+#include <base/task/single_thread_task_executor.h>
+#endif // BASE_VER >= 780000
#include <base/time/time.h>
#include <brillo/message_loops/base_message_loop.h>
#include <brillo/message_loops/message_loop.h>
@@ -70,8 +75,13 @@
subprocess_.Init(&async_signal_handler_);
}
+#if BASE_VER < 780000 // Android
base::MessageLoopForIO base_loop_;
brillo::BaseMessageLoop loop_{&base_loop_};
+#else // Chrome OS
+ base::SingleThreadTaskExecutor base_loop_{base::MessagePumpType::IO};
+ brillo::BaseMessageLoop loop_{base_loop_.task_runner()};
+#endif // BASE_VER < 780000
brillo::AsynchronousSignalHandler async_signal_handler_;
Subprocess subprocess_;
unique_ptr<base::FileDescriptorWatcher::Controller> watcher_;
diff --git a/common/test_utils.h b/common/test_utils.h
index 63ea749..bb5a678 100644
--- a/common/test_utils.h
+++ b/common/test_utils.h
@@ -138,22 +138,6 @@
DISALLOW_COPY_AND_ASSIGN(ScopedLoopbackDeviceBinder);
};
-class ScopedTempFile {
- public:
- ScopedTempFile() : ScopedTempFile("update_engine_test_temp_file.XXXXXX") {}
-
- explicit ScopedTempFile(const std::string& pattern) {
- EXPECT_TRUE(utils::MakeTempFile(pattern, &path_, nullptr));
- unlinker_.reset(new ScopedPathUnlinker(path_));
- }
-
- const std::string& path() const { return path_; }
-
- private:
- std::string path_;
- std::unique_ptr<ScopedPathUnlinker> unlinker_;
-};
-
class ScopedLoopMounter {
public:
explicit ScopedLoopMounter(const std::string& file_path,
diff --git a/common/utils.cc b/common/utils.cc
index 5d76f3f..c8924b1 100644
--- a/common/utils.cc
+++ b/common/utils.cc
@@ -112,27 +112,6 @@
namespace utils {
-string ParseECVersion(string input_line) {
- base::TrimWhitespaceASCII(input_line, base::TRIM_ALL, &input_line);
-
- // At this point we want to convert the format key=value pair from mosys to
- // a vector of key value pairs.
- vector<pair<string, string>> kv_pairs;
- if (base::SplitStringIntoKeyValuePairs(input_line, '=', ' ', &kv_pairs)) {
- for (const pair<string, string>& kv_pair : kv_pairs) {
- // Finally match against the fw_verion which may have quotes.
- if (kv_pair.first == "fw_version") {
- string output;
- // Trim any quotes.
- base::TrimString(kv_pair.second, "\"", &output);
- return output;
- }
- }
- }
- LOG(ERROR) << "Unable to parse fwid from ec info.";
- return "";
-}
-
bool WriteFile(const char* path, const void* data, size_t data_len) {
int fd = HANDLE_EINTR(open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600));
TEST_AND_RETURN_FALSE_ERRNO(fd >= 0);
@@ -911,6 +890,25 @@
return true;
}
+bool GetVpdValue(string key, string* result) {
+ int exit_code = 0;
+ string value, error;
+ vector<string> cmd = {"vpd_get_value", key};
+ if (!chromeos_update_engine::Subprocess::SynchronousExec(
+ cmd, &exit_code, &value, &error) ||
+ exit_code) {
+ LOG(ERROR) << "Failed to get vpd key for " << value
+ << " with exit code: " << exit_code << " and error: " << error;
+ return false;
+ } else if (!error.empty()) {
+ LOG(INFO) << "vpd_get_value succeeded but with following errors: " << error;
+ }
+
+ base::TrimWhitespaceASCII(value, base::TRIM_ALL, &value);
+ *result = value;
+ return true;
+}
+
bool GetBootId(string* boot_id) {
TEST_AND_RETURN_FALSE(
base::ReadFileToString(base::FilePath(kBootIdPath), boot_id));
diff --git a/common/utils.h b/common/utils.h
index 0a1dc0c..05a92be 100644
--- a/common/utils.h
+++ b/common/utils.h
@@ -53,10 +53,6 @@
std::string CalculateP2PFileId(const brillo::Blob& payload_hash,
size_t payload_size);
-// Parse the firmware version from one line of output from the
-// "mosys" command.
-std::string ParseECVersion(std::string input_line);
-
// Writes the data passed to path. The file at path will be overwritten if it
// exists. Returns true on success, false otherwise.
bool WriteFile(const char* path, const void* data, size_t data_len);
@@ -292,6 +288,10 @@
// reboot. Returns whether it succeeded getting the boot_id.
bool GetBootId(std::string* boot_id);
+// Gets a string value from the vpd for a given key using the `vpd_get_value`
+// shell command. Returns true on success.
+bool GetVpdValue(std::string key, std::string* result);
+
// This function gets the file path of the file pointed to by FileDiscriptor.
std::string GetFilePath(int fd);
@@ -370,6 +370,42 @@
DISALLOW_COPY_AND_ASSIGN(ScopedPathUnlinker);
};
+class ScopedTempFile {
+ public:
+ ScopedTempFile() : ScopedTempFile("update_engine_temp.XXXXXX") {}
+
+ // If |open_fd| is true, a writable file descriptor will be opened for this
+ // file.
+ explicit ScopedTempFile(const std::string& pattern, bool open_fd = false) {
+ CHECK(utils::MakeTempFile(pattern, &path_, open_fd ? &fd_ : nullptr));
+ unlinker_.reset(new ScopedPathUnlinker(path_));
+ if (open_fd) {
+ CHECK_GE(fd_, 0);
+ fd_closer_.reset(new ScopedFdCloser(&fd_));
+ }
+ }
+ virtual ~ScopedTempFile() = default;
+
+ const std::string& path() const { return path_; }
+ int fd() const {
+ CHECK(fd_closer_);
+ return fd_;
+ }
+ void CloseFd() {
+ CHECK(fd_closer_);
+ fd_closer_.reset();
+ }
+
+ private:
+ std::string path_;
+ std::unique_ptr<ScopedPathUnlinker> unlinker_;
+
+ int fd_{-1};
+ std::unique_ptr<ScopedFdCloser> fd_closer_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedTempFile);
+};
+
// A little object to call ActionComplete on the ActionProcessor when
// it's destructed.
class ScopedActionCompleter {
diff --git a/common/utils_unittest.cc b/common/utils_unittest.cc
index d73b3da..20c6b84 100644
--- a/common/utils_unittest.cc
+++ b/common/utils_unittest.cc
@@ -41,25 +41,12 @@
class UtilsTest : public ::testing::Test {};
-TEST(UtilsTest, CanParseECVersion) {
- // Should be able to parse and valid key value line.
- EXPECT_EQ("12345", utils::ParseECVersion("fw_version=12345"));
- EXPECT_EQ("123456",
- utils::ParseECVersion("b=1231a fw_version=123456 a=fasd2"));
- EXPECT_EQ("12345", utils::ParseECVersion("fw_version=12345"));
- EXPECT_EQ("00VFA616",
- utils::ParseECVersion("vendor=\"sam\" fw_version=\"00VFA616\""));
-
- // For invalid entries, should return the empty string.
- EXPECT_EQ("", utils::ParseECVersion("b=1231a fw_version a=fasd2"));
-}
-
TEST(UtilsTest, WriteFileOpenFailure) {
EXPECT_FALSE(utils::WriteFile("/this/doesn't/exist", "hello", 5));
}
TEST(UtilsTest, WriteFileReadFile) {
- test_utils::ScopedTempFile file;
+ ScopedTempFile file;
EXPECT_TRUE(utils::WriteFile(file.path().c_str(), "hello", 5));
brillo::Blob readback;
@@ -73,7 +60,7 @@
}
TEST(UtilsTest, ReadFileChunk) {
- test_utils::ScopedTempFile file;
+ ScopedTempFile file;
brillo::Blob data;
const size_t kSize = 1024 * 1024;
for (size_t i = 0; i < kSize; i++) {
@@ -162,7 +149,7 @@
namespace {
void GetFileFormatTester(const string& expected,
const vector<uint8_t>& contents) {
- test_utils::ScopedTempFile file;
+ ScopedTempFile file;
ASSERT_TRUE(utils::WriteFile(file.path().c_str(),
reinterpret_cast<const char*>(contents.data()),
contents.size()));
@@ -391,7 +378,7 @@
}
TEST(UtilsTest, RunAsRootUnmountFilesystemBusyFailureTest) {
- test_utils::ScopedTempFile tmp_image("img.XXXXXX");
+ ScopedTempFile tmp_image("img.XXXXXX");
EXPECT_TRUE(base::CopyFile(
test_utils::GetBuildArtifactsPath().Append("gen/disk_ext2_4k.img"),
@@ -431,7 +418,7 @@
EXPECT_TRUE(mnt_dir.CreateUniqueTempDir());
EXPECT_FALSE(utils::IsMountpoint(mnt_dir.GetPath().value()));
- test_utils::ScopedTempFile file;
+ ScopedTempFile file;
EXPECT_FALSE(utils::IsMountpoint(file.path()));
}
@@ -473,7 +460,7 @@
}
TEST(UtilsTest, GetFilePathTest) {
- test_utils::ScopedTempFile file;
+ ScopedTempFile file;
int fd = HANDLE_EINTR(open(file.path().c_str(), O_RDONLY));
EXPECT_GE(fd, 0);
EXPECT_EQ(file.path(), utils::GetFilePath(fd));
diff --git a/dynamic_partition_control_android_unittest.cc b/dynamic_partition_control_android_unittest.cc
index 223e177..c1e0daf 100644
--- a/dynamic_partition_control_android_unittest.cc
+++ b/dynamic_partition_control_android_unittest.cc
@@ -34,7 +34,6 @@
using android::dm::DmDeviceState;
using android::snapshot::MockSnapshotManager;
using chromeos_update_engine::test_utils::ScopedLoopbackDeviceBinder;
-using chromeos_update_engine::test_utils::ScopedTempFile;
using std::string;
using testing::_;
using testing::AnyNumber;
diff --git a/hardware_android.cc b/hardware_android.cc
index 5e24621..28c139a 100644
--- a/hardware_android.cc
+++ b/hardware_android.cc
@@ -45,8 +45,6 @@
// Android properties that identify the hardware and potentially non-updatable
// parts of the bootloader (such as the bootloader version and the baseband
// version).
-const char kPropBootBootloader[] = "ro.boot.bootloader";
-const char kPropBootBaseband[] = "ro.boot.baseband";
const char kPropProductManufacturer[] = "ro.product.manufacturer";
const char kPropBootHardwareSKU[] = "ro.boot.hardware.sku";
const char kPropBootRevision[] = "ro.boot.revision";
@@ -137,14 +135,6 @@
return manufacturer + ":" + sku + ":" + revision;
}
-string HardwareAndroid::GetFirmwareVersion() const {
- return GetProperty(kPropBootBootloader, "");
-}
-
-string HardwareAndroid::GetECVersion() const {
- return GetProperty(kPropBootBaseband, "");
-}
-
string HardwareAndroid::GetDeviceRequisition() const {
LOG(WARNING) << "STUB: Getting requisition is not supported.";
return "";
diff --git a/hardware_android.h b/hardware_android.h
index d8fbbbe..4d10835 100644
--- a/hardware_android.h
+++ b/hardware_android.h
@@ -42,8 +42,6 @@
bool IsOOBEEnabled() const override;
bool IsOOBEComplete(base::Time* out_time_of_oobe) const override;
std::string GetHardwareClass() const override;
- std::string GetFirmwareVersion() const override;
- std::string GetECVersion() const override;
std::string GetDeviceRequisition() const override;
int GetMinKernelKeyVersion() const override;
int GetMinFirmwareKeyVersion() const override;
diff --git a/hardware_chromeos.cc b/hardware_chromeos.cc
index 807e086..dbb99db 100644
--- a/hardware_chromeos.cc
+++ b/hardware_chromeos.cc
@@ -38,6 +38,9 @@
#include "update_engine/common/subprocess.h"
#include "update_engine/common/utils.h"
#include "update_engine/dbus_connection.h"
+#if USE_CFM
+#include "update_engine/requisition_util.h"
+#endif
using std::string;
using std::vector;
@@ -81,29 +84,6 @@
const char* kActivePingKey = "first_active_omaha_ping_sent";
-const char* kOemRequisitionKey = "oem_device_requisition";
-
-// Gets a string value from the vpd for a given key using the `vpd_get_value`
-// shell command. Returns true on success.
-int GetVpdValue(string key, string* result) {
- int exit_code = 0;
- string value, error;
- vector<string> cmd = {"vpd_get_value", key};
- if (!chromeos_update_engine::Subprocess::SynchronousExec(
- cmd, &exit_code, &value, &error) ||
- exit_code) {
- LOG(ERROR) << "Failed to get vpd key for " << value
- << " with exit code: " << exit_code << " and error: " << error;
- return false;
- } else if (!error.empty()) {
- LOG(INFO) << "vpd_get_value succeeded but with following errors: " << error;
- }
-
- base::TrimWhitespaceASCII(value, base::TRIM_ALL, &value);
- *result = value;
- return true;
-}
-
} // namespace
namespace chromeos_update_engine {
@@ -195,28 +175,13 @@
return ReadValueFromCrosSystem("hwid");
}
-string HardwareChromeOS::GetFirmwareVersion() const {
- return ReadValueFromCrosSystem("fwid");
-}
-
-string HardwareChromeOS::GetECVersion() const {
- string input_line, error;
- int exit_code = 0;
- vector<string> cmd = {"/usr/sbin/mosys", "-k", "ec", "info"};
-
- if (!Subprocess::SynchronousExec(cmd, &exit_code, &input_line, &error) ||
- exit_code != 0) {
- LOG(ERROR) << "Unable to read EC info from mosys with exit code: "
- << exit_code << " and error: " << error;
- return "";
- }
-
- return utils::ParseECVersion(input_line);
-}
-
string HardwareChromeOS::GetDeviceRequisition() const {
- string requisition;
- return GetVpdValue(kOemRequisitionKey, &requisition) ? requisition : "";
+#if USE_CFM
+ const char* kLocalStatePath = "/home/chronos/Local State";
+ return ReadDeviceRequisition(base::FilePath(kLocalStatePath));
+#else
+ return "";
+#endif
}
int HardwareChromeOS::GetMinKernelKeyVersion() const {
@@ -341,7 +306,7 @@
bool HardwareChromeOS::GetFirstActiveOmahaPingSent() const {
string active_ping_str;
- if (!GetVpdValue(kActivePingKey, &active_ping_str)) {
+ if (!utils::GetVpdValue(kActivePingKey, &active_ping_str)) {
return false;
}
diff --git a/hardware_chromeos.h b/hardware_chromeos.h
index bbfe273..9ee62f6 100644
--- a/hardware_chromeos.h
+++ b/hardware_chromeos.h
@@ -46,8 +46,6 @@
bool IsOOBEEnabled() const override;
bool IsOOBEComplete(base::Time* out_time_of_oobe) const override;
std::string GetHardwareClass() const override;
- std::string GetFirmwareVersion() const override;
- std::string GetECVersion() const override;
std::string GetDeviceRequisition() const override;
int GetMinKernelKeyVersion() const override;
int GetMinFirmwareKeyVersion() const override;
diff --git a/init/update-engine.conf b/init/update-engine.conf
index ca54c4a..36c89d7 100644
--- a/init/update-engine.conf
+++ b/init/update-engine.conf
@@ -37,7 +37,17 @@
# Put update_engine process in its own cgroup.
# Default cpu.shares is 1024.
post-start script
- cgroup_dir="/sys/fs/cgroup/cpu/${UPSTART_JOB}"
- mkdir -p "${cgroup_dir}"
- echo $(status | cut -f 4 -d ' ') > "${cgroup_dir}/tasks"
+ pid=$(status | cut -f 4 -d ' ')
+
+ cgroup_cpu_dir="/sys/fs/cgroup/cpu/${UPSTART_JOB}"
+ mkdir -p "${cgroup_cpu_dir}"
+ echo ${pid} > "${cgroup_cpu_dir}/tasks"
+
+ # Assigns net_cls handle 1:1 to packets generated from update_engine. For
+ # routing and tagging purposes, that value will be redefined in
+ # patchpanel/routing_service.h .
+ cgroup_net_cls_dir="/sys/fs/cgroup/net_cls/${UPSTART_JOB}"
+ mkdir -p "${cgroup_net_cls_dir}"
+ echo ${pid} > "${cgroup_net_cls_dir}/tasks"
+ echo "0x10001" > "${cgroup_net_cls_dir}/net_cls.classid"
end script
diff --git a/libcurl_http_fetcher.cc b/libcurl_http_fetcher.cc
index bce0920..1599aac 100644
--- a/libcurl_http_fetcher.cc
+++ b/libcurl_http_fetcher.cc
@@ -458,10 +458,10 @@
// There's either more work to do or we are paused, so we just keep the
// file descriptors to watch up to date and exit, until we are done with the
// work and we are not paused.
-#ifdef __ANDROID__
- // When there's no base::SingleThreadTaskRunner on current thread, it's not
- // possible to watch file descriptors. Just poll it later. This usually
- // happens if brillo::FakeMessageLoop is used.
+ //
+ // When there's no |base::SingleThreadTaskRunner| on current thread, it's
+ // not possible to watch file descriptors. Just poll it later. This usually
+ // happens if |brillo::FakeMessageLoop| is used.
if (!base::ThreadTaskRunnerHandle::IsSet()) {
MessageLoop::current()->PostDelayedTask(
FROM_HERE,
@@ -470,7 +470,6 @@
TimeDelta::FromSeconds(1));
return;
}
-#endif
SetupMessageLoopSources();
return;
}
diff --git a/libcurl_http_fetcher_unittest.cc b/libcurl_http_fetcher_unittest.cc
index 874ef2e..5d67570 100644
--- a/libcurl_http_fetcher_unittest.cc
+++ b/libcurl_http_fetcher_unittest.cc
@@ -100,7 +100,6 @@
libcurl_fetcher_.BeginTransfer("https://An-uNres0lvable-uRl.invalid");
-#ifdef __ANDROID__
// It's slower on Android that libcurl handle may not finish within 1 cycle.
// Will need to wait for more cycles until it finishes. Original test didn't
// correctly handle when we need to re-watch libcurl fds.
@@ -108,10 +107,7 @@
libcurl_fetcher_.GetAuxiliaryErrorCode() == ErrorCode::kSuccess) {
loop_.RunOnce(true);
}
-#else
- // The first time it can't resolve.
- loop_.RunOnce(true);
-#endif
+
EXPECT_EQ(libcurl_fetcher_.GetAuxiliaryErrorCode(),
ErrorCode::kUnresolvedHostError);
@@ -141,7 +137,6 @@
// easier to mock the part that depends on internet connectivity.
libcurl_fetcher_.BeginTransfer("https://An-uNres0lvable-uRl.invalid");
-#ifdef __ANDROID__
// It's slower on Android that libcurl handle may not finish within 1 cycle.
// Will need to wait for more cycles until it finishes. Original test didn't
// correctly handle when we need to re-watch libcurl fds.
@@ -149,10 +144,7 @@
libcurl_fetcher_.GetAuxiliaryErrorCode() == ErrorCode::kSuccess) {
loop_.RunOnce(true);
}
-#else
- // The first time it can't resolve.
- loop_.RunOnce(true);
-#endif
+
EXPECT_EQ(libcurl_fetcher_.GetAuxiliaryErrorCode(),
ErrorCode::kUnresolvedHostError);
@@ -165,7 +157,6 @@
[this]() { libcurl_fetcher_.http_response_code_ = 0; }));
libcurl_fetcher_.transfer_size_ = 10;
-#ifdef __ANDROID__
// It's slower on Android that libcurl handle may not finish within 1 cycle.
// Will need to wait for more cycles until it finishes. Original test didn't
// correctly handle when we need to re-watch libcurl fds.
@@ -173,11 +164,7 @@
ErrorCode::kUnresolvedHostError) {
loop_.RunOnce(true);
}
-#else
- // This time the host is resolved. But after that again we can't resolve
- // anymore (See above).
- loop_.RunOnce(true);
-#endif
+
EXPECT_EQ(libcurl_fetcher_.GetAuxiliaryErrorCode(),
ErrorCode::kUnresolvedHostRecovered);
diff --git a/logging.cc b/logging.cc
index 6320e36..012feee 100644
--- a/logging.cc
+++ b/logging.cc
@@ -79,7 +79,11 @@
if (log_to_file) {
log_file = SetupLogFile(kSystemLogsRoot);
log_settings.delete_old = logging::APPEND_TO_OLD_LOG_FILE;
+#if BASE_VER < 780000
log_settings.log_file = log_file.c_str();
+#else
+ log_settings.log_file_path = log_file.c_str();
+#endif
}
logging::InitLogging(log_settings);
}
diff --git a/metrics_constants.h b/metrics_constants.h
index db21d90..679680c 100644
--- a/metrics_constants.h
+++ b/metrics_constants.h
@@ -106,7 +106,7 @@
kUpdateCanceled, // Update canceled by the user.
kUpdateSucceededNotActive, // Update succeeded but the new slot is not
// active.
-
+ kUpdateSkipped, // Current update skipped.
kNumConstants,
kUnset = -1
diff --git a/metrics_reporter_omaha.cc b/metrics_reporter_omaha.cc
index fb4e4ce..0cf0e59 100644
--- a/metrics_reporter_omaha.cc
+++ b/metrics_reporter_omaha.cc
@@ -146,8 +146,6 @@
void MetricsReporterOmaha::ReportDailyMetrics(base::TimeDelta os_age) {
string metric = metrics::kMetricDailyOSAgeDays;
- LOG(INFO) << "Uploading " << utils::FormatTimeDelta(os_age) << " for metric "
- << metric;
metrics_lib_->SendToUMA(metric,
static_cast<int>(os_age.InDays()),
0, // min: 0 days
@@ -168,20 +166,17 @@
metric = metrics::kMetricCheckResult;
value = static_cast<int>(result);
max_value = static_cast<int>(metrics::CheckResult::kNumConstants) - 1;
- LOG(INFO) << "Sending " << value << " for metric " << metric << " (enum)";
metrics_lib_->SendEnumToUMA(metric, value, max_value);
}
if (reaction != metrics::CheckReaction::kUnset) {
metric = metrics::kMetricCheckReaction;
value = static_cast<int>(reaction);
max_value = static_cast<int>(metrics::CheckReaction::kNumConstants) - 1;
- LOG(INFO) << "Sending " << value << " for metric " << metric << " (enum)";
metrics_lib_->SendEnumToUMA(metric, value, max_value);
}
if (download_error_code != metrics::DownloadErrorCode::kUnset) {
metric = metrics::kMetricCheckDownloadErrorCode;
value = static_cast<int>(download_error_code);
- LOG(INFO) << "Sending " << value << " for metric " << metric << " (sparse)";
metrics_lib_->SendSparseToUMA(metric, value);
}
@@ -191,8 +186,6 @@
kPrefsMetricsCheckLastReportingTime,
&time_since_last)) {
metric = metrics::kMetricCheckTimeSinceLastCheckMinutes;
- LOG(INFO) << "Sending " << utils::FormatTimeDelta(time_since_last)
- << " for metric " << metric;
metrics_lib_->SendToUMA(metric,
time_since_last.InMinutes(),
0, // min: 0 min
@@ -205,8 +198,6 @@
if (metrics_utils::MonotonicDurationHelper(
system_state, &uptime_since_last_storage, &uptime_since_last)) {
metric = metrics::kMetricCheckTimeSinceLastCheckUptimeMinutes;
- LOG(INFO) << "Sending " << utils::FormatTimeDelta(uptime_since_last)
- << " for metric " << metric;
metrics_lib_->SendToUMA(metric,
uptime_since_last.InMinutes(),
0, // min: 0 min
@@ -221,13 +212,9 @@
value = utils::VersionPrefix(target_version);
if (value != 0) {
metric = metrics::kMetricCheckTargetVersion;
- LOG(INFO) << "Sending " << value << " for metric " << metric
- << " (sparse)";
metrics_lib_->SendSparseToUMA(metric, value);
if (system_state->request_params()->rollback_allowed()) {
metric = metrics::kMetricCheckRollbackTargetVersion;
- LOG(INFO) << "Sending " << value << " for metric " << metric
- << " (sparse)";
metrics_lib_->SendSparseToUMA(metric, value);
}
}
@@ -239,8 +226,6 @@
metrics::AttemptResult attempt_result =
metrics::AttemptResult::kAbnormalTermination;
- LOG(INFO) << "Uploading " << static_cast<int>(attempt_result)
- << " for metric " << metric;
metrics_lib_->SendEnumToUMA(
metric,
static_cast<int>(attempt_result),
@@ -257,7 +242,6 @@
metrics::AttemptResult attempt_result,
ErrorCode internal_error_code) {
string metric = metrics::kMetricAttemptNumber;
- LOG(INFO) << "Uploading " << attempt_number << " for metric " << metric;
metrics_lib_->SendToUMA(metric,
attempt_number,
0, // min: 0 attempts
@@ -265,13 +249,9 @@
50); // num_buckets
metric = metrics::kMetricAttemptPayloadType;
- LOG(INFO) << "Uploading " << utils::ToString(payload_type) << " for metric "
- << metric;
metrics_lib_->SendEnumToUMA(metric, payload_type, kNumPayloadTypes);
metric = metrics::kMetricAttemptDurationMinutes;
- LOG(INFO) << "Uploading " << utils::FormatTimeDelta(duration)
- << " for metric " << metric;
metrics_lib_->SendToUMA(metric,
duration.InMinutes(),
0, // min: 0 min
@@ -279,8 +259,6 @@
50); // num_buckets
metric = metrics::kMetricAttemptDurationUptimeMinutes;
- LOG(INFO) << "Uploading " << utils::FormatTimeDelta(duration_uptime)
- << " for metric " << metric;
metrics_lib_->SendToUMA(metric,
duration_uptime.InMinutes(),
0, // min: 0 min
@@ -289,7 +267,6 @@
metric = metrics::kMetricAttemptPayloadSizeMiB;
int64_t payload_size_mib = payload_size / kNumBytesInOneMiB;
- LOG(INFO) << "Uploading " << payload_size_mib << " for metric " << metric;
metrics_lib_->SendToUMA(metric,
payload_size_mib,
0, // min: 0 MiB
@@ -297,8 +274,6 @@
50); // num_buckets
metric = metrics::kMetricAttemptResult;
- LOG(INFO) << "Uploading " << static_cast<int>(attempt_result)
- << " for metric " << metric;
metrics_lib_->SendEnumToUMA(
metric,
static_cast<int>(attempt_result),
@@ -314,8 +289,6 @@
kPrefsMetricsAttemptLastReportingTime,
&time_since_last)) {
metric = metrics::kMetricAttemptTimeSinceLastAttemptMinutes;
- LOG(INFO) << "Sending " << utils::FormatTimeDelta(time_since_last)
- << " for metric " << metric;
metrics_lib_->SendToUMA(metric,
time_since_last.InMinutes(),
0, // min: 0 min
@@ -328,8 +301,6 @@
if (metrics_utils::MonotonicDurationHelper(
system_state, &uptime_since_last_storage, &uptime_since_last)) {
metric = metrics::kMetricAttemptTimeSinceLastAttemptUptimeMinutes;
- LOG(INFO) << "Sending " << utils::FormatTimeDelta(uptime_since_last)
- << " for metric " << metric;
metrics_lib_->SendToUMA(metric,
uptime_since_last.InMinutes(),
0, // min: 0 min
@@ -347,8 +318,6 @@
string metric = metrics::kMetricAttemptPayloadBytesDownloadedMiB;
int64_t payload_bytes_downloaded_mib =
payload_bytes_downloaded / kNumBytesInOneMiB;
- LOG(INFO) << "Uploading " << payload_bytes_downloaded_mib << " for metric "
- << metric;
metrics_lib_->SendToUMA(metric,
payload_bytes_downloaded_mib,
0, // min: 0 MiB
@@ -357,8 +326,6 @@
metric = metrics::kMetricAttemptPayloadDownloadSpeedKBps;
int64_t payload_download_speed_kbps = payload_download_speed_bps / 1000;
- LOG(INFO) << "Uploading " << payload_download_speed_kbps << " for metric "
- << metric;
metrics_lib_->SendToUMA(metric,
payload_download_speed_kbps,
0, // min: 0 kB/s
@@ -366,20 +333,15 @@
50); // num_buckets
metric = metrics::kMetricAttemptDownloadSource;
- LOG(INFO) << "Uploading " << download_source << " for metric " << metric;
metrics_lib_->SendEnumToUMA(metric, download_source, kNumDownloadSources);
if (payload_download_error_code != metrics::DownloadErrorCode::kUnset) {
metric = metrics::kMetricAttemptDownloadErrorCode;
- LOG(INFO) << "Uploading " << static_cast<int>(payload_download_error_code)
- << " for metric " << metric << " (sparse)";
metrics_lib_->SendSparseToUMA(
metric, static_cast<int>(payload_download_error_code));
}
metric = metrics::kMetricAttemptConnectionType;
- LOG(INFO) << "Uploading " << static_cast<int>(connection_type)
- << " for metric " << metric;
metrics_lib_->SendEnumToUMA(
metric,
static_cast<int>(connection_type),
@@ -399,7 +361,6 @@
int url_switch_count) {
string metric = metrics::kMetricSuccessfulUpdatePayloadSizeMiB;
int64_t mbs = payload_size / kNumBytesInOneMiB;
- LOG(INFO) << "Uploading " << mbs << " (MiBs) for metric " << metric;
metrics_lib_->SendToUMA(metric,
mbs,
0, // min: 0 MiB
@@ -429,7 +390,6 @@
}
if (mbs > 0) {
- LOG(INFO) << "Uploading " << mbs << " (MiBs) for metric " << metric;
metrics_lib_->SendToUMA(metric,
mbs,
0, // min: 0 MiB
@@ -439,8 +399,6 @@
}
metric = metrics::kMetricSuccessfulUpdateDownloadSourcesUsed;
- LOG(INFO) << "Uploading 0x" << std::hex << download_sources_used
- << " (bit flags) for metric " << metric;
metrics_lib_->SendToUMA(metric,
download_sources_used,
0, // min
@@ -448,8 +406,6 @@
1 << kNumDownloadSources); // num_buckets
metric = metrics::kMetricSuccessfulUpdateDownloadOverheadPercentage;
- LOG(INFO) << "Uploading " << download_overhead_percentage << "% for metric "
- << metric;
metrics_lib_->SendToUMA(metric,
download_overhead_percentage,
0, // min: 0% overhead
@@ -457,8 +413,6 @@
50); // num_buckets
metric = metrics::kMetricSuccessfulUpdateUrlSwitchCount;
- LOG(INFO) << "Uploading " << url_switch_count << " (count) for metric "
- << metric;
metrics_lib_->SendToUMA(metric,
url_switch_count,
0, // min: 0 URL switches
@@ -466,8 +420,6 @@
50); // num_buckets
metric = metrics::kMetricSuccessfulUpdateTotalDurationMinutes;
- LOG(INFO) << "Uploading " << utils::FormatTimeDelta(total_duration)
- << " for metric " << metric;
metrics_lib_->SendToUMA(metric,
static_cast<int>(total_duration.InMinutes()),
0, // min: 0 min
@@ -475,8 +427,6 @@
50); // num_buckets
metric = metrics::kMetricSuccessfulUpdateTotalDurationUptimeMinutes;
- LOG(INFO) << "Uploading " << utils::FormatTimeDelta(total_duration_uptime)
- << " for metric " << metric;
metrics_lib_->SendToUMA(metric,
static_cast<int>(total_duration_uptime.InMinutes()),
0, // min: 0 min
@@ -484,8 +434,6 @@
50); // num_buckets
metric = metrics::kMetricSuccessfulUpdateRebootCount;
- LOG(INFO) << "Uploading reboot count of " << reboot_count << " for metric "
- << metric;
metrics_lib_->SendToUMA(metric,
reboot_count,
0, // min: 0 reboots
@@ -494,8 +442,6 @@
metric = metrics::kMetricSuccessfulUpdatePayloadType;
metrics_lib_->SendEnumToUMA(metric, payload_type, kNumPayloadTypes);
- LOG(INFO) << "Uploading " << utils::ToString(payload_type) << " for metric "
- << metric;
metric = metrics::kMetricSuccessfulUpdateAttemptCount;
metrics_lib_->SendToUMA(metric,
@@ -503,11 +449,8 @@
1, // min: 1 attempt
50, // max: 50 attempts
50); // num_buckets
- LOG(INFO) << "Uploading " << attempt_count << " for metric " << metric;
metric = metrics::kMetricSuccessfulUpdateUpdatesAbandonedCount;
- LOG(INFO) << "Uploading " << updates_abandoned_count << " (count) for metric "
- << metric;
metrics_lib_->SendToUMA(metric,
updates_abandoned_count,
0, // min: 0 counts
@@ -519,7 +462,6 @@
metrics::RollbackResult result) {
string metric = metrics::kMetricRollbackResult;
int value = static_cast<int>(result);
- LOG(INFO) << "Sending " << value << " for metric " << metric << " (enum)";
metrics_lib_->SendEnumToUMA(
metric, value, static_cast<int>(metrics::RollbackResult::kNumConstants));
}
@@ -530,7 +472,6 @@
string metric = metrics::kMetricEnterpriseRollbackSuccess;
if (!success)
metric = metrics::kMetricEnterpriseRollbackFailure;
- LOG(INFO) << "Sending " << value << " for metric " << metric;
metrics_lib_->SendSparseToUMA(metric, value);
}
@@ -547,8 +488,6 @@
case ServerToCheck::kNone:
return;
}
- LOG(INFO) << "Uploading " << static_cast<int>(result) << " for metric "
- << metric;
metrics_lib_->SendEnumToUMA(
metric,
static_cast<int>(result),
@@ -562,9 +501,6 @@
1, // min value
50, // max value
kNumDefaultUmaBuckets);
-
- LOG(INFO) << "Uploading " << target_attempt << " (count) for metric "
- << metric;
}
void MetricsReporterOmaha::ReportTimeToReboot(int time_to_reboot_minutes) {
@@ -574,9 +510,6 @@
0, // min: 0 minute
30 * 24 * 60, // max: 1 month (approx)
kNumDefaultUmaBuckets);
-
- LOG(INFO) << "Uploading " << time_to_reboot_minutes << " for metric "
- << metric;
}
void MetricsReporterOmaha::ReportInstallDateProvisioningSource(int source,
@@ -588,7 +521,6 @@
void MetricsReporterOmaha::ReportInternalErrorCode(ErrorCode error_code) {
auto metric = metrics::kMetricAttemptInternalErrorCode;
- LOG(INFO) << "Uploading " << error_code << " for metric " << metric;
metrics_lib_->SendEnumToUMA(metric,
static_cast<int>(error_code),
static_cast<int>(ErrorCode::kUmaReportedMax));
@@ -600,18 +532,14 @@
bool kernel_max_rollforward_success) {
int value = kernel_min_version;
string metric = metrics::kMetricKernelMinVersion;
- LOG(INFO) << "Sending " << value << " for metric " << metric;
metrics_lib_->SendSparseToUMA(metric, value);
value = kernel_max_rollforward_version;
metric = metrics::kMetricKernelMaxRollforwardVersion;
- LOG(INFO) << "Sending " << value << " for metric " << metric;
metrics_lib_->SendSparseToUMA(metric, value);
bool bool_value = kernel_max_rollforward_success;
metric = metrics::kMetricKernelMaxRollforwardSetSuccess;
- LOG(INFO) << "Sending " << bool_value << " for metric " << metric
- << " (bool)";
metrics_lib_->SendBoolToUMA(metric, bool_value);
}
@@ -621,7 +549,6 @@
has_time_restriction_policy
? metrics::kMetricSuccessfulUpdateDurationFromSeenTimeRestrictedDays
: metrics::kMetricSuccessfulUpdateDurationFromSeenDays;
- LOG(INFO) << "Sending " << time_to_update_days << " for metric " << metric;
metrics_lib_->SendToUMA(metric,
time_to_update_days,
diff --git a/metrics_utils.cc b/metrics_utils.cc
index da3a2c3..2211a67 100644
--- a/metrics_utils.cc
+++ b/metrics_utils.cc
@@ -111,10 +111,6 @@
case ErrorCode::kDownloadInvalidMetadataSignature:
case ErrorCode::kOmahaResponseInvalid:
case ErrorCode::kOmahaUpdateIgnoredPerPolicy:
- // TODO(deymo): The next two items belong in their own category; they
- // should not be counted as internal errors. b/27112092
- case ErrorCode::kOmahaUpdateDeferredPerPolicy:
- case ErrorCode::kNonCriticalUpdateInOOBE:
case ErrorCode::kOmahaErrorInHTTPResponse:
case ErrorCode::kDownloadMetadataSignatureMissingError:
case ErrorCode::kOmahaUpdateDeferredForBackoff:
@@ -124,8 +120,13 @@
case ErrorCode::kOmahaUpdateIgnoredOverCellular:
case ErrorCode::kNoUpdate:
case ErrorCode::kFirstActiveOmahaPingSentPersistenceError:
+ case ErrorCode::kPackageExcludedFromUpdate:
return metrics::AttemptResult::kInternalError;
+ case ErrorCode::kOmahaUpdateDeferredPerPolicy:
+ case ErrorCode::kNonCriticalUpdateInOOBE:
+ return metrics::AttemptResult::kUpdateSkipped;
+
// Special flags. These can't happen (we mask them out above) but
// the compiler doesn't know that. Just break out so we can warn and
// return |kInternalError|.
@@ -240,6 +241,7 @@
case ErrorCode::kVerityCalculationError:
case ErrorCode::kNotEnoughSpace:
case ErrorCode::kDeviceCorrupted:
+ case ErrorCode::kPackageExcludedFromUpdate:
break;
// Special flags. These can't happen (we mask them out above) but
diff --git a/mock_update_attempter.h b/mock_update_attempter.h
index ad34802..96d93fd 100644
--- a/mock_update_attempter.h
+++ b/mock_update_attempter.h
@@ -30,16 +30,10 @@
public:
using UpdateAttempter::UpdateAttempter;
- MOCK_METHOD9(Update,
- void(const std::string& app_version,
- const std::string& omaha_url,
- const std::string& target_channel,
- const std::string& target_version_prefix,
- bool rollback_allowed,
- bool rollback_data_save_requested,
- int rollback_allowed_milestones,
- bool obey_proxies,
- bool interactive));
+ MOCK_METHOD(void,
+ Update,
+ (const chromeos_update_manager::UpdateCheckParams& params),
+ (override));
MOCK_METHOD1(GetStatus, bool(update_engine::UpdateEngineStatus* out_status));
diff --git a/omaha_request_action.cc b/omaha_request_action.cc
index 95e1250..161cf43 100644
--- a/omaha_request_action.cc
+++ b/omaha_request_action.cc
@@ -582,6 +582,7 @@
LOG(INFO) << "Found package " << package.name;
OmahaResponse::Package out_package;
+ out_package.app_id = app->id;
out_package.can_exclude = can_exclude;
for (const string& codebase : app->url_codebase) {
if (codebase.empty()) {
@@ -631,6 +632,7 @@
// Removes the candidate URLs which are excluded within packages, if all the
// candidate URLs are excluded within a package, the package will be excluded.
void ProcessExclusions(OmahaResponse* output_object,
+ OmahaRequestParams* params,
ExcluderInterface* excluder) {
for (auto package_it = output_object->packages.begin();
package_it != output_object->packages.end();
@@ -657,6 +659,9 @@
// If there are no candidate payload URLs, remove the package.
if (package_it->payload_urls.empty()) {
LOG(INFO) << "Excluding payload hash=" << package_it->hash;
+ // Need to set DLC as not updated so correct metrics can be sent when an
+ // update is completed.
+ params->SetDlcNoUpdate(package_it->app_id);
package_it = output_object->packages.erase(package_it);
continue;
}
@@ -1023,6 +1028,7 @@
if (!ParseResponse(&parser_data, &output_object, &completer))
return;
ProcessExclusions(&output_object,
+ system_state_->request_params(),
system_state_->update_attempter()->GetExcluder());
output_object.update_exists = true;
SetOutputObject(output_object);
diff --git a/omaha_request_action_unittest.cc b/omaha_request_action_unittest.cc
index 6a0c213..61e988b 100644
--- a/omaha_request_action_unittest.cc
+++ b/omaha_request_action_unittest.cc
@@ -365,8 +365,6 @@
request_params_.set_current_channel("unittest");
request_params_.set_target_channel("unittest");
request_params_.set_hwid("OEM MODEL 09235 7471");
- request_params_.set_fw_version("ChromeOSFirmware.1.0");
- request_params_.set_ec_version("0X0A1");
request_params_.set_delta_okay(true);
request_params_.set_interactive(false);
request_params_.set_update_url("http://url");
@@ -1528,6 +1526,7 @@
request_params_.set_os_board("x86 generic<id");
request_params_.set_current_channel("unittest_track<");
request_params_.set_target_channel("unittest_track<");
+ request_params_.set_lts_tag("unittest_hint<");
request_params_.set_hwid("<OEM MODEL>");
fake_prefs_.SetString(kPrefsOmahaCohort, "evil\nstring");
fake_prefs_.SetString(kPrefsOmahaCohortHint, "evil&string\\");
@@ -1547,6 +1546,8 @@
EXPECT_EQ(string::npos, post_str.find("x86 generic<id"));
EXPECT_NE(string::npos, post_str.find("unittest_track&lt;"));
EXPECT_EQ(string::npos, post_str.find("unittest_track<"));
+ EXPECT_NE(string::npos, post_str.find("unittest_hint&lt;"));
+ EXPECT_EQ(string::npos, post_str.find("unittest_hint<"));
EXPECT_NE(string::npos, post_str.find("<OEM MODEL>"));
EXPECT_EQ(string::npos, post_str.find("<OEM MODEL>"));
EXPECT_NE(string::npos, post_str.find("cohort=\"evil\nstring\""));
@@ -1601,8 +1602,6 @@
string::npos);
EXPECT_NE(post_str.find("hardware_class=\"OEM MODEL 09235 7471\""),
string::npos);
- EXPECT_NE(post_str.find("fw_version=\"ChromeOSFirmware.1.0\""), string::npos);
- EXPECT_NE(post_str.find("ec_version=\"0X0A1\""), string::npos);
// No <event> tag should be sent if we didn't reboot to an update.
EXPECT_EQ(post_str.find("<event"), string::npos);
}
@@ -1801,6 +1800,17 @@
EXPECT_EQ(string::npos, post_str.find(omaha_cohort_hint));
}
+TEST_F(OmahaRequestActionTest, TargetChannelHintTest) {
+ tuc_params_.http_response = fake_update_response_.GetNoUpdateResponse();
+ tuc_params_.expected_check_result = metrics::CheckResult::kNoUpdateAvailable;
+ tuc_params_.expected_check_reaction = metrics::CheckReaction::kUnset;
+ request_params_.set_lts_tag("hint>");
+
+ ASSERT_TRUE(TestUpdateCheck());
+
+ EXPECT_NE(string::npos, post_str.find("ltstag=\"hint>\""));
+}
+
void OmahaRequestActionTest::PingTest(bool ping_only) {
NiceMock<MockPrefs> prefs;
fake_system_state_.set_prefs(&prefs);
@@ -2776,8 +2786,8 @@
}
TEST_F(OmahaRequestActionTest, UpdateWithPartiallyExcludedDlcTest) {
- request_params_.set_dlc_apps_params(
- {{request_params_.GetDlcAppId(kDlcId1), {.name = kDlcId1}}});
+ const string kDlcAppId = request_params_.GetDlcAppId(kDlcId1);
+ request_params_.set_dlc_apps_params({{kDlcAppId, {.name = kDlcId1}}});
fake_update_response_.dlc_app_update = true;
tuc_params_.http_response = fake_update_response_.GetUpdateResponse();
// The first DLC candidate URL is excluded.
@@ -2790,11 +2800,12 @@
// One candidate URL.
EXPECT_EQ(response.packages[1].payload_urls.size(), 1u);
EXPECT_TRUE(response.update_exists);
+ EXPECT_TRUE(request_params_.dlc_apps_params().at(kDlcAppId).updated);
}
TEST_F(OmahaRequestActionTest, UpdateWithExcludedDlcTest) {
- request_params_.set_dlc_apps_params(
- {{request_params_.GetDlcAppId(kDlcId1), {.name = kDlcId1}}});
+ const string kDlcAppId = request_params_.GetDlcAppId(kDlcId1);
+ request_params_.set_dlc_apps_params({{kDlcAppId, {.name = kDlcId1}}});
fake_update_response_.dlc_app_update = true;
tuc_params_.http_response = fake_update_response_.GetUpdateResponse();
// Both DLC candidate URLs are excluded.
@@ -2805,6 +2816,7 @@
EXPECT_EQ(response.packages.size(), 1u);
EXPECT_TRUE(response.update_exists);
+ EXPECT_FALSE(request_params_.dlc_apps_params().at(kDlcAppId).updated);
}
TEST_F(OmahaRequestActionTest, UpdateWithDeprecatedDlcTest) {
diff --git a/omaha_request_builder_xml.cc b/omaha_request_builder_xml.cc
index e2857f1..6660afb 100644
--- a/omaha_request_builder_xml.cc
+++ b/omaha_request_builder_xml.cc
@@ -154,6 +154,11 @@
app_body += " rollback_allowed=\"true\"";
}
}
+ if (!params_->lts_tag().empty()) {
+ app_body += base::StringPrintf(
+ " ltstag=\"%s\"",
+ XmlEncodeWithDefault(params_->lts_tag()).c_str());
+ }
app_body += "></updatecheck>\n";
}
@@ -184,17 +189,26 @@
}
}
} else {
+ int event_result = event_->result;
// The error code is an optional attribute so append it only if the result
// is not success.
string error_code;
- if (event_->result != OmahaEvent::kResultSuccess) {
+ if (event_result != OmahaEvent::kResultSuccess) {
error_code = base::StringPrintf(" errorcode=\"%d\"",
static_cast<int>(event_->error_code));
+ } else if (app_data.is_dlc && !app_data.app_params.updated) {
+ // On a |OmahaEvent::kResultSuccess|, if the event is for an update
+ // completion and the App is a DLC, send error for excluded DLCs as they
+ // did not update.
+ event_result = OmahaEvent::Result::kResultError;
+ error_code = base::StringPrintf(
+ " errorcode=\"%d\"",
+ static_cast<int>(ErrorCode::kPackageExcludedFromUpdate));
}
app_body = base::StringPrintf(
" <event eventtype=\"%d\" eventresult=\"%d\"%s></event>\n",
event_->type,
- event_->result,
+ event_result,
error_code.c_str());
}
@@ -354,8 +368,6 @@
// DLC excluded for installs and updates.
(app_data.is_dlc ? "" :
"lang=\"" + XmlEncodeWithDefault(params_->app_lang(), "en-US") + "\" " +
- "fw_version=\"" + XmlEncodeWithDefault(params_->fw_version()) + "\" " +
- "ec_version=\"" + XmlEncodeWithDefault(params_->ec_version()) + "\" " +
requisition_arg) +
">\n" +
diff --git a/omaha_request_builder_xml_unittest.cc b/omaha_request_builder_xml_unittest.cc
index 017acec..042d991 100644
--- a/omaha_request_builder_xml_unittest.cc
+++ b/omaha_request_builder_xml_unittest.cc
@@ -108,8 +108,6 @@
// in fact present in the <app ...></app>.
const string app = omaha_request.GetApp(dlc_app_data);
EXPECT_NE(string::npos, app.find("lang="));
- EXPECT_NE(string::npos, app.find("fw_version="));
- EXPECT_NE(string::npos, app.find("ec_version="));
EXPECT_NE(string::npos, app.find("requisition="));
}
@@ -132,8 +130,6 @@
// fact not present in the <app ...></app>.
const string app = omaha_request.GetApp(dlc_app_data);
EXPECT_EQ(string::npos, app.find("lang="));
- EXPECT_EQ(string::npos, app.find("fw_version="));
- EXPECT_EQ(string::npos, app.find("ec_version="));
EXPECT_EQ(string::npos, app.find("requisition="));
}
@@ -148,10 +144,10 @@
0,
fake_system_state_.prefs(),
""};
- const string request_xml = omaha_request.GetRequest();
+ const string kRequestXml = omaha_request.GetRequest();
const string key = "requestid";
const string request_id =
- FindAttributeKeyValueInXml(request_xml, key, kGuidSize);
+ FindAttributeKeyValueInXml(kRequestXml, key, kGuidSize);
// A valid |request_id| is either a GUID version 4 or empty string.
if (!request_id.empty())
EXPECT_TRUE(base::IsValidGUID(request_id));
@@ -169,10 +165,10 @@
0,
fake_system_state_.prefs(),
gen_session_id};
- const string request_xml = omaha_request.GetRequest();
+ const string kRequestXml = omaha_request.GetRequest();
const string key = "sessionid";
const string session_id =
- FindAttributeKeyValueInXml(request_xml, key, kGuidSize);
+ FindAttributeKeyValueInXml(kRequestXml, key, kGuidSize);
// A valid |session_id| is either a GUID version 4 or empty string.
if (!session_id.empty()) {
EXPECT_TRUE(base::IsValidGUID(session_id));
@@ -191,9 +187,9 @@
0,
fake_system_state_.prefs(),
""};
- const string request_xml = omaha_request.GetRequest();
- EXPECT_EQ(1, CountSubstringInString(request_xml, "<updatecheck"))
- << request_xml;
+ const string kRequestXml = omaha_request.GetRequest();
+ EXPECT_EQ(1, CountSubstringInString(kRequestXml, "<updatecheck"))
+ << kRequestXml;
}
TEST_F(OmahaRequestBuilderXmlTest, GetRequestXmlPlatformUpdateWithDlcsTest) {
@@ -210,9 +206,9 @@
0,
fake_system_state_.prefs(),
""};
- const string request_xml = omaha_request.GetRequest();
- EXPECT_EQ(3, CountSubstringInString(request_xml, "<updatecheck"))
- << request_xml;
+ const string kRequestXml = omaha_request.GetRequest();
+ EXPECT_EQ(3, CountSubstringInString(kRequestXml, "<updatecheck"))
+ << kRequestXml;
}
TEST_F(OmahaRequestBuilderXmlTest, GetRequestXmlDlcInstallationTest) {
@@ -231,25 +227,25 @@
0,
fake_system_state_.prefs(),
""};
- const string request_xml = omaha_request.GetRequest();
- EXPECT_EQ(2, CountSubstringInString(request_xml, "<updatecheck"))
- << request_xml;
+ const string kRequestXml = omaha_request.GetRequest();
+ EXPECT_EQ(2, CountSubstringInString(kRequestXml, "<updatecheck"))
+ << kRequestXml;
- auto FindAppId = [request_xml](size_t pos) -> size_t {
- return request_xml.find("<app appid", pos);
+ auto FindAppId = [kRequestXml](size_t pos) -> size_t {
+ return kRequestXml.find("<app appid", pos);
};
// Skip over the Platform AppID, which is always first.
size_t pos = FindAppId(0);
for (auto&& _ : dlcs) {
(void)_;
- EXPECT_NE(string::npos, (pos = FindAppId(pos + 1))) << request_xml;
+ EXPECT_NE(string::npos, (pos = FindAppId(pos + 1))) << kRequestXml;
const string dlc_app_id_version = FindAttributeKeyValueInXml(
- request_xml.substr(pos), "version", string(kNoVersion).size());
+ kRequestXml.substr(pos), "version", string(kNoVersion).size());
EXPECT_EQ(kNoVersion, dlc_app_id_version);
const string false_str = "false";
const string dlc_app_id_delta_okay = FindAttributeKeyValueInXml(
- request_xml.substr(pos), "delta_okay", false_str.length());
+ kRequestXml.substr(pos), "delta_okay", false_str.length());
EXPECT_EQ(false_str, dlc_app_id_delta_okay);
}
}
@@ -267,8 +263,8 @@
0,
fake_system_state_.prefs(),
""};
- const string request_xml = omaha_request.GetRequest();
- EXPECT_EQ(0, CountSubstringInString(request_xml, "<ping")) << request_xml;
+ const string kRequestXml = omaha_request.GetRequest();
+ EXPECT_EQ(0, CountSubstringInString(kRequestXml, "<ping")) << kRequestXml;
}
TEST_F(OmahaRequestBuilderXmlTest, GetRequestXmlDlcPingRollCallNoActive) {
@@ -289,9 +285,9 @@
0,
fake_system_state_.prefs(),
""};
- const string request_xml = omaha_request.GetRequest();
- EXPECT_EQ(1, CountSubstringInString(request_xml, "<ping rd=\"36\""))
- << request_xml;
+ const string kRequestXml = omaha_request.GetRequest();
+ EXPECT_EQ(1, CountSubstringInString(kRequestXml, "<ping rd=\"36\""))
+ << kRequestXml;
}
TEST_F(OmahaRequestBuilderXmlTest, GetRequestXmlDlcPingRollCallAndActive) {
@@ -313,10 +309,93 @@
0,
fake_system_state_.prefs(),
""};
- const string request_xml = omaha_request.GetRequest();
+ const string kRequestXml = omaha_request.GetRequest();
EXPECT_EQ(1,
- CountSubstringInString(request_xml,
+ CountSubstringInString(kRequestXml,
"<ping active=\"1\" ad=\"25\" rd=\"36\""))
- << request_xml;
+ << kRequestXml;
+}
+
+TEST_F(OmahaRequestBuilderXmlTest, GetRequestXmlUpdateCompleteEvent) {
+ OmahaRequestParams omaha_request_params{&fake_system_state_};
+ OmahaEvent event(OmahaEvent::kTypeUpdateComplete);
+ OmahaRequestBuilderXml omaha_request{&event,
+ &omaha_request_params,
+ false,
+ false,
+ 0,
+ 0,
+ 0,
+ fake_system_state_.prefs(),
+ ""};
+ const string kRequestXml = omaha_request.GetRequest();
+ LOG(INFO) << kRequestXml;
+ EXPECT_EQ(
+ 1,
+ CountSubstringInString(
+ kRequestXml, "<event eventtype=\"3\" eventresult=\"1\"></event>"))
+ << kRequestXml;
+}
+
+TEST_F(OmahaRequestBuilderXmlTest,
+ GetRequestXmlUpdateCompleteEventSomeDlcsExcluded) {
+ OmahaRequestParams omaha_request_params{&fake_system_state_};
+ omaha_request_params.set_dlc_apps_params({
+ {omaha_request_params.GetDlcAppId("dlc_1"), {.updated = true}},
+ {omaha_request_params.GetDlcAppId("dlc_2"), {.updated = false}},
+ });
+ OmahaEvent event(OmahaEvent::kTypeUpdateComplete);
+ OmahaRequestBuilderXml omaha_request{&event,
+ &omaha_request_params,
+ false,
+ false,
+ 0,
+ 0,
+ 0,
+ fake_system_state_.prefs(),
+ ""};
+ const string kRequestXml = omaha_request.GetRequest();
+ EXPECT_EQ(
+ 2,
+ CountSubstringInString(
+ kRequestXml, "<event eventtype=\"3\" eventresult=\"1\"></event>"))
+ << kRequestXml;
+ EXPECT_EQ(
+ 1,
+ CountSubstringInString(
+ kRequestXml,
+ "<event eventtype=\"3\" eventresult=\"0\" errorcode=\"62\"></event>"))
+ << kRequestXml;
+}
+
+TEST_F(OmahaRequestBuilderXmlTest,
+ GetRequestXmlUpdateCompleteEventAllDlcsExcluded) {
+ OmahaRequestParams omaha_request_params{&fake_system_state_};
+ omaha_request_params.set_dlc_apps_params({
+ {omaha_request_params.GetDlcAppId("dlc_1"), {.updated = false}},
+ {omaha_request_params.GetDlcAppId("dlc_2"), {.updated = false}},
+ });
+ OmahaEvent event(OmahaEvent::kTypeUpdateComplete);
+ OmahaRequestBuilderXml omaha_request{&event,
+ &omaha_request_params,
+ false,
+ false,
+ 0,
+ 0,
+ 0,
+ fake_system_state_.prefs(),
+ ""};
+ const string kRequestXml = omaha_request.GetRequest();
+ EXPECT_EQ(
+ 1,
+ CountSubstringInString(
+ kRequestXml, "<event eventtype=\"3\" eventresult=\"1\"></event>"))
+ << kRequestXml;
+ EXPECT_EQ(
+ 2,
+ CountSubstringInString(
+ kRequestXml,
+ "<event eventtype=\"3\" eventresult=\"0\" errorcode=\"62\"></event>"))
+ << kRequestXml;
}
} // namespace chromeos_update_engine
diff --git a/omaha_request_params.cc b/omaha_request_params.cc
index 8a2e3dc..5a48720 100644
--- a/omaha_request_params.cc
+++ b/omaha_request_params.cc
@@ -37,9 +37,11 @@
#include "update_engine/common/platform_constants.h"
#include "update_engine/common/utils.h"
#include "update_engine/system_state.h"
+#include "update_engine/update_manager/policy.h"
#define CALL_MEMBER_FN(object, member) ((object).*(member))
+using chromeos_update_manager::UpdateCheckParams;
using std::string;
namespace chromeos_update_engine {
@@ -59,9 +61,9 @@
test::SetImagePropertiesRootPrefix(nullptr);
}
-bool OmahaRequestParams::Init(const string& in_app_version,
- const string& in_update_url,
- bool in_interactive) {
+bool OmahaRequestParams::Init(const string& app_version,
+ const string& update_url,
+ const UpdateCheckParams& params) {
LOG(INFO) << "Initializing parameters for this update attempt";
image_props_ = LoadImageProperties(system_state_);
mutable_image_props_ = LoadMutableImageProperties(system_state_);
@@ -77,23 +79,19 @@
os_platform_ = constants::kOmahaPlatformName;
if (!image_props_.system_version.empty()) {
- if (in_app_version == "ForcedUpdate") {
- image_props_.system_version = in_app_version;
+ if (app_version == "ForcedUpdate") {
+ image_props_.system_version = app_version;
}
os_version_ = image_props_.system_version;
} else {
os_version_ = OmahaRequestParams::kOsVersion;
}
- if (!in_app_version.empty())
- image_props_.version = in_app_version;
+ if (!app_version.empty())
+ image_props_.version = app_version;
os_sp_ = image_props_.version + "_" + GetMachineType();
app_lang_ = "en-US";
hwid_ = system_state_->hardware()->GetHardwareClass();
- if (CollectECFWVersions()) {
- fw_version_ = system_state_->hardware()->GetFirmwareVersion();
- ec_version_ = system_state_->hardware()->GetECVersion();
- }
device_requisition_ = system_state_->hardware()->GetDeviceRequisition();
if (image_props_.current_channel == mutable_image_props_.target_channel) {
@@ -115,17 +113,51 @@
delta_okay_ = false;
}
- if (in_update_url.empty())
+ if (update_url.empty())
update_url_ = image_props_.omaha_url;
else
- update_url_ = in_update_url;
+ update_url_ = update_url;
// Set the interactive flag accordingly.
- interactive_ = in_interactive;
+ interactive_ = params.interactive;
dlc_apps_params_.clear();
// Set false so it will do update by default.
is_install_ = false;
+
+ target_version_prefix_ = params.target_version_prefix;
+
+ lts_tag_ = params.lts_tag;
+
+ rollback_allowed_ = params.rollback_allowed;
+
+ // Set whether saving data over rollback is requested.
+ rollback_data_save_requested_ = params.rollback_data_save_requested;
+
+ // Set how many milestones of rollback are allowed.
+ rollback_allowed_milestones_ = params.rollback_allowed_milestones;
+
+ // Set the target channel, if one was provided.
+ if (params.target_channel.empty()) {
+ LOG(INFO) << "No target channel mandated by policy.";
+ } else {
+ LOG(INFO) << "Setting target channel as mandated: "
+ << params.target_channel;
+ string error_message;
+ if (!SetTargetChannel(params.target_channel,
+ params.rollback_on_channel_downgrade,
+ &error_message)) {
+ LOG(ERROR) << "Setting the channel failed: " << error_message;
+ }
+
+ // Since this is the beginning of a new attempt, update the download
+ // channel. The download channel won't be updated until the next attempt,
+ // even if target channel changes meanwhile, so that how we'll know if we
+ // should cancel the current download attempt if there's such a change in
+ // target channel.
+ UpdateDownloadChannel();
+ }
+
return true;
}
@@ -134,14 +166,6 @@
update_url_ == image_props_.omaha_url);
}
-bool OmahaRequestParams::CollectECFWVersions() const {
- return base::StartsWith(
- hwid_, string("PARROT"), base::CompareCase::SENSITIVE) ||
- base::StartsWith(
- hwid_, string("SPRING"), base::CompareCase::SENSITIVE) ||
- base::StartsWith(hwid_, string("SNOW"), base::CompareCase::SENSITIVE);
-}
-
bool OmahaRequestParams::SetTargetChannel(const string& new_target_channel,
bool is_powerwash_allowed,
string* error_message) {
diff --git a/omaha_request_params.h b/omaha_request_params.h
index 76fc806..ed3cc80 100644
--- a/omaha_request_params.h
+++ b/omaha_request_params.h
@@ -30,6 +30,7 @@
#include "update_engine/common/constants.h"
#include "update_engine/common/platform_constants.h"
#include "update_engine/image_properties.h"
+#include "update_engine/update_manager/policy.h"
// This gathers local system information and prepares info used by the
// Omaha request action.
@@ -103,8 +104,6 @@
}
inline std::string app_lang() const { return app_lang_; }
inline std::string hwid() const { return hwid_; }
- inline std::string fw_version() const { return fw_version_; }
- inline std::string ec_version() const { return ec_version_; }
inline std::string device_requisition() const { return device_requisition_; }
inline void set_app_version(const std::string& version) {
@@ -148,6 +147,10 @@
return target_version_prefix_;
}
+ inline std::string lts_tag() const { return lts_tag_; }
+
+ inline void set_lts_tag(const std::string& hint) { lts_tag_ = hint; }
+
inline void set_rollback_allowed(bool rollback_allowed) {
rollback_allowed_ = rollback_allowed;
}
@@ -245,7 +248,7 @@
// of the parameter. Returns true on success, false otherwise.
bool Init(const std::string& in_app_version,
const std::string& in_update_url,
- bool in_interactive);
+ const chromeos_update_manager::UpdateCheckParams& params);
// Permanently changes the release channel to |channel|. Performs a
// powerwash, if required and allowed.
@@ -289,22 +292,19 @@
}
void set_app_lang(const std::string& app_lang) { app_lang_ = app_lang; }
void set_hwid(const std::string& hwid) { hwid_ = hwid; }
- void set_fw_version(const std::string& fw_version) {
- fw_version_ = fw_version;
- }
- void set_ec_version(const std::string& ec_version) {
- ec_version_ = ec_version;
- }
void set_is_powerwash_allowed(bool powerwash_allowed) {
mutable_image_props_.is_powerwash_allowed = powerwash_allowed;
}
+ bool is_powerwash_allowed() {
+ return mutable_image_props_.is_powerwash_allowed;
+ }
+
void set_device_requisition(const std::string& requisition) {
device_requisition_ = requisition;
}
private:
FRIEND_TEST(OmahaRequestParamsTest, ChannelIndexTest);
- FRIEND_TEST(OmahaRequestParamsTest, CollectECFWVersionsTest);
FRIEND_TEST(OmahaRequestParamsTest, IsValidChannelTest);
FRIEND_TEST(OmahaRequestParamsTest, SetIsPowerwashAllowedTest);
FRIEND_TEST(OmahaRequestParamsTest, SetTargetChannelInvalidTest);
@@ -327,10 +327,6 @@
// i.e. index(target_channel) > index(current_channel).
bool ToMoreStableChannel() const;
- // Returns True if we should store the fw/ec versions based on our hwid_.
- // Compares hwid to a set of prefixes in the allowlist.
- bool CollectECFWVersions() const;
-
// Gets the machine type (e.g. "i686").
std::string GetMachineType() const;
@@ -367,14 +363,15 @@
// changed and cancel the current download attempt.
std::string download_channel_;
+ // The value defining the parameters of the LTS (Long Term Support).
+ std::string lts_tag_;
+
std::string hwid_; // Hardware Qualification ID of the client
- std::string fw_version_; // Chrome OS Firmware Version.
- std::string ec_version_; // Chrome OS EC Version.
// TODO(b:133324571) tracks removal of this field once it is no longer
// needed in AU requests. Remove by October 1st 2019.
std::string device_requisition_; // Chrome OS Requisition type.
- bool delta_okay_; // If this client can accept a delta
- bool interactive_; // Whether this is a user-initiated update check
+ bool delta_okay_; // If this client can accept a delta
+ bool interactive_; // Whether this is a user-initiated update check
// The URL to send the Omaha request to.
std::string update_url_;
diff --git a/omaha_request_params_unittest.cc b/omaha_request_params_unittest.cc
index bfcbc32..fcf8062 100644
--- a/omaha_request_params_unittest.cc
+++ b/omaha_request_params_unittest.cc
@@ -75,36 +75,36 @@
} // namespace
TEST_F(OmahaRequestParamsTest, MissingChannelTest) {
- EXPECT_TRUE(params_.Init("", "", false));
+ EXPECT_TRUE(params_.Init("", "", {}));
// By default, if no channel is set, we should track the stable-channel.
EXPECT_EQ("stable-channel", params_.target_channel());
}
TEST_F(OmahaRequestParamsTest, ForceVersionTest) {
- EXPECT_TRUE(params_.Init("ForcedVersion", "", false));
+ EXPECT_TRUE(params_.Init("ForcedVersion", "", {}));
EXPECT_EQ(string("ForcedVersion_") + GetMachineType(), params_.os_sp());
EXPECT_EQ("ForcedVersion", params_.app_version());
}
TEST_F(OmahaRequestParamsTest, ForcedURLTest) {
- EXPECT_TRUE(params_.Init("", "http://forced.google.com", false));
+ EXPECT_TRUE(params_.Init("", "http://forced.google.com", {}));
EXPECT_EQ("http://forced.google.com", params_.update_url());
}
TEST_F(OmahaRequestParamsTest, MissingURLTest) {
- EXPECT_TRUE(params_.Init("", "", false));
+ EXPECT_TRUE(params_.Init("", "", {}));
EXPECT_EQ(constants::kOmahaDefaultProductionURL, params_.update_url());
}
TEST_F(OmahaRequestParamsTest, DeltaOKTest) {
- EXPECT_TRUE(params_.Init("", "", false));
+ EXPECT_TRUE(params_.Init("", "", {}));
EXPECT_TRUE(params_.delta_okay());
}
TEST_F(OmahaRequestParamsTest, NoDeltasTest) {
ASSERT_TRUE(
WriteFileString(tempdir_.GetPath().Append(".nodelta").value(), ""));
- EXPECT_TRUE(params_.Init("", "", false));
+ EXPECT_TRUE(params_.Init("", "", {}));
EXPECT_FALSE(params_.delta_okay());
}
@@ -112,12 +112,12 @@
{
OmahaRequestParams params(&fake_system_state_);
params.set_root(tempdir_.GetPath().value());
- EXPECT_TRUE(params.Init("", "", false));
+ EXPECT_TRUE(params.Init("", "", {}));
EXPECT_TRUE(params.SetTargetChannel("canary-channel", false, nullptr));
EXPECT_FALSE(params.mutable_image_props_.is_powerwash_allowed);
}
params_.set_root(tempdir_.GetPath().value());
- EXPECT_TRUE(params_.Init("", "", false));
+ EXPECT_TRUE(params_.Init("", "", {}));
EXPECT_EQ("canary-channel", params_.target_channel());
EXPECT_FALSE(params_.mutable_image_props_.is_powerwash_allowed);
}
@@ -126,12 +126,12 @@
{
OmahaRequestParams params(&fake_system_state_);
params.set_root(tempdir_.GetPath().value());
- EXPECT_TRUE(params.Init("", "", false));
+ EXPECT_TRUE(params.Init("", "", {}));
EXPECT_TRUE(params.SetTargetChannel("canary-channel", true, nullptr));
EXPECT_TRUE(params.mutable_image_props_.is_powerwash_allowed);
}
params_.set_root(tempdir_.GetPath().value());
- EXPECT_TRUE(params_.Init("", "", false));
+ EXPECT_TRUE(params_.Init("", "", {}));
EXPECT_EQ("canary-channel", params_.target_channel());
EXPECT_TRUE(params_.mutable_image_props_.is_powerwash_allowed);
}
@@ -141,7 +141,7 @@
OmahaRequestParams params(&fake_system_state_);
params.set_root(tempdir_.GetPath().value());
SetLockDown(true);
- EXPECT_TRUE(params.Init("", "", false));
+ EXPECT_TRUE(params.Init("", "", {}));
params.image_props_.allow_arbitrary_channels = false;
string error_message;
EXPECT_FALSE(
@@ -151,7 +151,7 @@
EXPECT_FALSE(params.mutable_image_props_.is_powerwash_allowed);
}
params_.set_root(tempdir_.GetPath().value());
- EXPECT_TRUE(params_.Init("", "", false));
+ EXPECT_TRUE(params_.Init("", "", {}));
EXPECT_EQ("stable-channel", params_.target_channel());
EXPECT_FALSE(params_.mutable_image_props_.is_powerwash_allowed);
}
@@ -197,7 +197,7 @@
// When set to a valid value while a change is already pending, it should
// succeed.
- params_.Init("", "", false);
+ params_.Init("", "", {});
EXPECT_TRUE(params_.SetTargetChannel("beta-channel", true, nullptr));
// The target channel should reflect the change, but the download channel
// should continue to retain the old value ...
@@ -236,6 +236,13 @@
EXPECT_FALSE(params_.ToMoreStableChannel());
}
+TEST_F(OmahaRequestParamsTest, TargetChannelHintTest) {
+ EXPECT_TRUE(params_.Init("", "", {}));
+ const string kHint("foo-hint");
+ params_.set_lts_tag(kHint);
+ EXPECT_EQ(kHint, params_.lts_tag());
+}
+
TEST_F(OmahaRequestParamsTest, ShouldPowerwashTest) {
params_.mutable_image_props_.is_powerwash_allowed = false;
EXPECT_FALSE(params_.ShouldPowerwash());
@@ -250,16 +257,8 @@
EXPECT_TRUE(params_.ShouldPowerwash());
}
-TEST_F(OmahaRequestParamsTest, CollectECFWVersionsTest) {
- params_.hwid_ = string("STUMPY ALEX 12345");
- EXPECT_FALSE(params_.CollectECFWVersions());
-
- params_.hwid_ = string("SNOW 12345");
- EXPECT_TRUE(params_.CollectECFWVersions());
-}
-
TEST_F(OmahaRequestParamsTest, RequisitionIsSetTest) {
- EXPECT_TRUE(params_.Init("", "", false));
+ EXPECT_TRUE(params_.Init("", "", {}));
EXPECT_EQ("fake_requisition", params_.device_requisition());
}
} // namespace chromeos_update_engine
diff --git a/omaha_response.h b/omaha_response.h
index 2b86fe7..77f9083 100644
--- a/omaha_response.h
+++ b/omaha_response.h
@@ -54,6 +54,8 @@
// True if the payload can be excluded from updating if consistently faulty.
// False if the payload is critical to update.
bool can_exclude = false;
+ // The App ID associated with the package.
+ std::string app_id;
};
std::vector<Package> packages;
diff --git a/omaha_response_handler_action.cc b/omaha_response_handler_action.cc
index 040f8e7..92e0a72 100644
--- a/omaha_response_handler_action.cc
+++ b/omaha_response_handler_action.cc
@@ -188,10 +188,12 @@
}
// Powerwash if either the response requires it or the parameters indicated
- // powerwash and we are downgrading the version.
+ // powerwash (usually because there was a channel downgrade) and we are
+ // downgrading the version. Enterprise rollback, indicated by
+ // |response.is_rollback| is dealt with separately above.
if (response.powerwash_required) {
install_plan_.powerwash_required = true;
- } else if (params->ShouldPowerwash()) {
+ } else if (params->ShouldPowerwash() && !response.is_rollback) {
base::Version new_version(response.version);
base::Version current_version(params->app_version());
@@ -205,6 +207,10 @@
<< " Current version number: " << params->app_version();
} else if (new_version < current_version) {
install_plan_.powerwash_required = true;
+ // Always try to preserve enrollment and wifi data for enrolled devices.
+ install_plan_.rollback_data_save_requested =
+ system_state_ && system_state_->device_policy() &&
+ system_state_->device_policy()->IsEnterpriseEnrolled();
}
}
diff --git a/omaha_response_handler_action_unittest.cc b/omaha_response_handler_action_unittest.cc
index 04cfa73..9613e8d 100644
--- a/omaha_response_handler_action_unittest.cc
+++ b/omaha_response_handler_action_unittest.cc
@@ -176,7 +176,7 @@
}
TEST_F(OmahaResponseHandlerActionTest, SimpleTest) {
- test_utils::ScopedTempFile test_deadline_file(
+ ScopedTempFile test_deadline_file(
"omaha_response_handler_action_unittest-XXXXXX");
{
OmahaResponse in;
@@ -532,6 +532,132 @@
}
TEST_F(OmahaResponseHandlerActionTest,
+ ChangeToMoreStableChannelButSameVersionTest) {
+ OmahaResponse in;
+ in.update_exists = true;
+ in.version = "12345.0.0.0";
+ in.packages.push_back({.payload_urls = {"https://ChannelDownVersionUp"},
+ .size = 1,
+ .hash = kPayloadHashHex});
+ in.more_info_url = "http://more/info";
+
+ // Create a uniquely named test directory.
+ base::ScopedTempDir tempdir;
+ ASSERT_TRUE(tempdir.CreateUniqueTempDir());
+
+ OmahaRequestParams params(&fake_system_state_);
+ fake_system_state_.fake_hardware()->SetIsOfficialBuild(false);
+ params.set_root(tempdir.GetPath().value());
+ params.set_current_channel("beta-channel");
+ EXPECT_TRUE(params.SetTargetChannel("stable-channel", true, nullptr));
+ params.UpdateDownloadChannel();
+ params.set_app_version("12345.0.0.0");
+
+ fake_system_state_.set_request_params(¶ms);
+ InstallPlan install_plan;
+ EXPECT_TRUE(DoTest(in, "", &install_plan));
+ EXPECT_FALSE(install_plan.powerwash_required);
+ EXPECT_FALSE(install_plan.rollback_data_save_requested);
+}
+
+// On an enrolled device, the rollback data restore should be attempted when
+// doing a powerwash and channel downgrade.
+TEST_F(OmahaResponseHandlerActionTest,
+ ChangeToMoreStableChannelEnrolledDataRestore) {
+ OmahaResponse in;
+ in.update_exists = true;
+ in.version = "12345.96.0.0";
+ in.packages.push_back({.payload_urls = {"https://ChannelDownEnrolled"},
+ .size = 1,
+ .hash = kPayloadHashHex});
+ in.more_info_url = "http://more/info";
+
+ // Create a uniquely named test directory.
+ base::ScopedTempDir tempdir;
+ ASSERT_TRUE(tempdir.CreateUniqueTempDir());
+
+ OmahaRequestParams params(&fake_system_state_);
+ fake_system_state_.fake_hardware()->SetIsOfficialBuild(true);
+ params.set_root(tempdir.GetPath().value());
+ params.set_current_channel("beta-channel");
+ EXPECT_TRUE(params.SetTargetChannel("stable-channel", true, nullptr));
+ params.UpdateDownloadChannel();
+ params.set_app_version("12347.48.0.0");
+
+ testing::NiceMock<policy::MockDevicePolicy> mock_device_policy;
+ EXPECT_CALL(mock_device_policy, IsEnterpriseEnrolled())
+ .WillOnce(Return(true));
+ fake_system_state_.set_device_policy(&mock_device_policy);
+
+ fake_system_state_.set_request_params(¶ms);
+ InstallPlan install_plan;
+ EXPECT_TRUE(DoTest(in, "", &install_plan));
+ EXPECT_TRUE(install_plan.rollback_data_save_requested);
+}
+
+// Never attempt rollback data restore if the device is not enrolled.
+TEST_F(OmahaResponseHandlerActionTest,
+ ChangeToMoreStableChannelUnenrolledNoDataRestore) {
+ OmahaResponse in;
+ in.update_exists = true;
+ in.version = "12345.96.0.0";
+ in.packages.push_back({.payload_urls = {"https://ChannelDownEnrolled"},
+ .size = 1,
+ .hash = kPayloadHashHex});
+ in.more_info_url = "http://more/info";
+
+ // Create a uniquely named test directory.
+ base::ScopedTempDir tempdir;
+ ASSERT_TRUE(tempdir.CreateUniqueTempDir());
+
+ OmahaRequestParams params(&fake_system_state_);
+ fake_system_state_.fake_hardware()->SetIsOfficialBuild(true);
+ params.set_root(tempdir.GetPath().value());
+ params.set_current_channel("beta-channel");
+ EXPECT_TRUE(params.SetTargetChannel("stable-channel", true, nullptr));
+ params.UpdateDownloadChannel();
+ params.set_app_version("12347.48.0.0");
+
+ testing::NiceMock<policy::MockDevicePolicy> mock_device_policy;
+ EXPECT_CALL(mock_device_policy, IsEnterpriseEnrolled())
+ .WillOnce(Return(false));
+ fake_system_state_.set_device_policy(&mock_device_policy);
+
+ fake_system_state_.set_request_params(¶ms);
+ InstallPlan install_plan;
+ EXPECT_TRUE(DoTest(in, "", &install_plan));
+ EXPECT_FALSE(install_plan.rollback_data_save_requested);
+}
+
+// Never attempt rollback data restore if powerwash is not allowed.
+TEST_F(OmahaResponseHandlerActionTest,
+ ChangeToMoreStableChannelNoPowerwashNoDataRestore) {
+ OmahaResponse in;
+ in.update_exists = true;
+ in.version = "12345.96.0.0";
+ in.packages.push_back(
+ {.payload_urls = {"https://URL"}, .size = 1, .hash = kPayloadHashHex});
+ in.more_info_url = "http://more/info";
+
+ // Create a uniquely named test directory.
+ base::ScopedTempDir tempdir;
+ ASSERT_TRUE(tempdir.CreateUniqueTempDir());
+
+ OmahaRequestParams params(&fake_system_state_);
+ fake_system_state_.fake_hardware()->SetIsOfficialBuild(true);
+ params.set_root(tempdir.GetPath().value());
+ params.set_current_channel("beta-channel");
+ EXPECT_TRUE(params.SetTargetChannel("stable-channel", false, nullptr));
+ params.UpdateDownloadChannel();
+ params.set_app_version("12347.48.0.0");
+
+ fake_system_state_.set_request_params(¶ms);
+ InstallPlan install_plan;
+ EXPECT_TRUE(DoTest(in, "", &install_plan));
+ EXPECT_FALSE(install_plan.rollback_data_save_requested);
+}
+
+TEST_F(OmahaResponseHandlerActionTest,
ChangeToLessStableVersionAndChannelTest) {
OmahaResponse in;
in.update_exists = true;
diff --git a/p2p_manager_unittest.cc b/p2p_manager_unittest.cc
index 5771ec1..5510dd7 100644
--- a/p2p_manager_unittest.cc
+++ b/p2p_manager_unittest.cc
@@ -30,8 +30,13 @@
#include <base/bind.h>
#include <base/callback.h>
#include <base/files/file_util.h>
+#if BASE_VER < 780000 // Android
#include <base/message_loop/message_loop.h>
+#endif // BASE_VER < 780000
#include <base/strings/stringprintf.h>
+#if BASE_VER >= 780000 // CrOS
+#include <base/task/single_thread_task_executor.h>
+#endif // BASE_VER >= 780000
#include <brillo/asynchronous_signal_handler.h>
#include <brillo/message_loops/base_message_loop.h>
#include <brillo/message_loops/message_loop.h>
@@ -92,8 +97,13 @@
TimeDelta::FromDays(5)));
}
+#if BASE_VER < 780000 // Android
base::MessageLoopForIO base_loop_;
brillo::BaseMessageLoop loop_{&base_loop_};
+#else // CrOS
+ base::SingleThreadTaskExecutor base_loop_{base::MessagePumpType::IO};
+ brillo::BaseMessageLoop loop_{base_loop_.task_runner()};
+#endif // BASE_VER < 780000
brillo::AsynchronousSignalHandler async_signal_handler_;
Subprocess subprocess_;
diff --git a/payload_consumer/bzip_extent_writer_unittest.cc b/payload_consumer/bzip_extent_writer_unittest.cc
index 125e1e5..b587040 100644
--- a/payload_consumer/bzip_extent_writer_unittest.cc
+++ b/payload_consumer/bzip_extent_writer_unittest.cc
@@ -49,7 +49,7 @@
void TearDown() override { fd_->Close(); }
FileDescriptorPtr fd_;
- test_utils::ScopedTempFile temp_file_{"BzipExtentWriterTest-file.XXXXXX"};
+ ScopedTempFile temp_file_{"BzipExtentWriterTest-file.XXXXXX"};
};
TEST_F(BzipExtentWriterTest, SimpleTest) {
diff --git a/payload_consumer/cached_file_descriptor_unittest.cc b/payload_consumer/cached_file_descriptor_unittest.cc
index d2965fc..b64420a 100644
--- a/payload_consumer/cached_file_descriptor_unittest.cc
+++ b/payload_consumer/cached_file_descriptor_unittest.cc
@@ -73,7 +73,7 @@
protected:
FileDescriptorPtr fd_{new EintrSafeFileDescriptor};
- test_utils::ScopedTempFile temp_file_{"CachedFileDescriptor-file.XXXXXX"};
+ ScopedTempFile temp_file_{"CachedFileDescriptor-file.XXXXXX"};
int value_{1};
FileDescriptorPtr cfd_;
};
diff --git a/payload_consumer/delta_performer.cc b/payload_consumer/delta_performer.cc
index e7ef8a3..a3989d6 100644
--- a/payload_consumer/delta_performer.cc
+++ b/payload_consumer/delta_performer.cc
@@ -277,15 +277,6 @@
} // namespace
-uint32_t DeltaPerformer::GetMinorVersion() const {
- if (manifest_.has_minor_version()) {
- return manifest_.minor_version();
- }
- return payload_->type == InstallPayloadType::kDelta
- ? kMaxSupportedMinorPayloadVersion
- : kFullPayloadMinorVersion;
-}
-
bool DeltaPerformer::IsHeaderParsed() const {
return metadata_size_ != 0;
}
@@ -1091,13 +1082,6 @@
}
}
- if (manifest_.has_old_rootfs_info() || manifest_.has_new_rootfs_info() ||
- manifest_.has_old_kernel_info() || manifest_.has_new_kernel_info() ||
- manifest_.install_operations_size() != 0 ||
- manifest_.kernel_install_operations_size() != 0) {
- LOG(ERROR) << "Manifest contains deprecated fields.";
- return ErrorCode::kPayloadMismatchedType;
- }
ErrorCode error_code = CheckTimestampError();
if (error_code != ErrorCode::kSuccess) {
if (error_code == ErrorCode::kPayloadTimestampError) {
@@ -1294,6 +1278,13 @@
return ErrorCode::kPayloadSizeMismatchError;
}
+ // Verifies the payload hash.
+ TEST_AND_RETURN_VAL(ErrorCode::kDownloadPayloadVerificationError,
+ !payload_hash_calculator_.raw_hash().empty());
+ TEST_AND_RETURN_VAL(
+ ErrorCode::kPayloadHashMismatchError,
+ payload_hash_calculator_.raw_hash() == update_check_response_hash);
+
auto [payload_verifier, perform_verification] = CreatePayloadVerifier();
if (!perform_verification) {
LOG(WARNING) << "Not verifying signed delta payload -- missing public key.";
@@ -1304,13 +1295,6 @@
return ErrorCode::kDownloadPayloadPubKeyVerificationError;
}
- // Verifies the payload hash.
- TEST_AND_RETURN_VAL(ErrorCode::kDownloadPayloadVerificationError,
- !payload_hash_calculator_.raw_hash().empty());
- TEST_AND_RETURN_VAL(
- ErrorCode::kPayloadHashMismatchError,
- payload_hash_calculator_.raw_hash() == update_check_response_hash);
-
TEST_AND_RETURN_VAL(ErrorCode::kSignedDeltaPayloadExpectedError,
!signatures_message_data_.empty());
brillo::Blob hash_data = signed_hash_calculator_.raw_hash();
diff --git a/payload_consumer/delta_performer.h b/payload_consumer/delta_performer.h
index 96bc849..4990bf8 100644
--- a/payload_consumer/delta_performer.h
+++ b/payload_consumer/delta_performer.h
@@ -170,9 +170,13 @@
// Return true if header parsing is finished and no errors occurred.
bool IsHeaderParsed() const;
- // Returns the delta minor version. If this value is defined in the manifest,
- // it returns that value, otherwise it returns the default value.
- uint32_t GetMinorVersion() const;
+ // Compare |calculated_hash| with source hash in |operation|, return false and
+ // dump hash and set |error| if don't match.
+ // |source_fd| is the file descriptor of the source partition.
+ static bool ValidateSourceHash(const brillo::Blob& calculated_hash,
+ const InstallOperation& operation,
+ const FileDescriptorPtr source_fd,
+ ErrorCode* error);
// Initialize partitions and allocate required space for an update with the
// given |manifest|. |update_check_response_hash| is used to check if the
diff --git a/payload_consumer/delta_performer_integration_test.cc b/payload_consumer/delta_performer_integration_test.cc
index f2aeb03..74ddd27 100644
--- a/payload_consumer/delta_performer_integration_test.cc
+++ b/payload_consumer/delta_performer_integration_test.cc
@@ -52,7 +52,9 @@
namespace chromeos_update_engine {
+using std::list;
using std::string;
+using std::unique_ptr;
using std::vector;
using test_utils::GetBuildArtifactsPath;
using test_utils::kRandomString;
@@ -76,22 +78,24 @@
namespace {
struct DeltaState {
- string a_img;
- string b_img;
- string result_img;
+ unique_ptr<ScopedTempFile> a_img;
+ unique_ptr<ScopedTempFile> b_img;
+ unique_ptr<ScopedTempFile> result_img;
size_t image_size;
- string delta_path;
+ unique_ptr<ScopedTempFile> delta_file;
+ // The in-memory copy of delta file.
+ brillo::Blob delta;
uint64_t metadata_size;
uint32_t metadata_signature_size;
- string old_kernel;
+ unique_ptr<ScopedTempFile> old_kernel;
brillo::Blob old_kernel_data;
- string new_kernel;
+ unique_ptr<ScopedTempFile> new_kernel;
brillo::Blob new_kernel_data;
- string result_kernel;
+ unique_ptr<ScopedTempFile> result_kernel;
brillo::Blob result_kernel_data;
size_t kernel_size;
@@ -99,9 +103,6 @@
// the DeltaPerformer.
InstallPlan install_plan;
- // The in-memory copy of delta file.
- brillo::Blob delta;
-
// Mock and fake instances used by the delta performer.
FakeBootControl fake_boot_control_;
FakeHardware fake_hardware_;
@@ -155,7 +156,7 @@
EXPECT_EQ(expected, performer.ValidateManifest());
}
void AddPartition(DeltaArchiveManifest* manifest,
- std::string name,
+ string name,
int timestamp) {
auto& partition = *manifest->add_partitions();
partition.set_version(std::to_string(timestamp));
@@ -259,8 +260,7 @@
}
string signature_size_string = base::JoinString(signature_size_strings, ":");
- test_utils::ScopedTempFile hash_file("hash.XXXXXX"),
- metadata_hash_file("hash.XXXXXX");
+ ScopedTempFile hash_file("hash.XXXXXX"), metadata_hash_file("hash.XXXXXX");
string delta_generator_path = GetBuildArtifactsPath("delta_generator");
ASSERT_EQ(0,
System(base::StringPrintf(
@@ -273,29 +273,27 @@
metadata_hash_file.path().c_str())));
// Sign the hash with all private keys.
- vector<test_utils::ScopedTempFile> sig_files, metadata_sig_files;
+ list<ScopedTempFile> sig_files, metadata_sig_files;
vector<string> sig_file_paths, metadata_sig_file_paths;
for (const auto& key_path : private_key_paths) {
brillo::Blob hash, signature;
ASSERT_TRUE(utils::ReadFile(hash_file.path(), &hash));
ASSERT_TRUE(PayloadSigner::SignHash(hash, key_path, &signature));
- test_utils::ScopedTempFile sig_file("signature.XXXXXX");
- ASSERT_TRUE(test_utils::WriteFileVector(sig_file.path(), signature));
- sig_file_paths.push_back(sig_file.path());
- sig_files.push_back(std::move(sig_file));
+ sig_files.emplace_back("signature.XXXXXX");
+ ASSERT_TRUE(
+ test_utils::WriteFileVector(sig_files.back().path(), signature));
+ sig_file_paths.push_back(sig_files.back().path());
brillo::Blob metadata_hash, metadata_signature;
ASSERT_TRUE(utils::ReadFile(metadata_hash_file.path(), &metadata_hash));
ASSERT_TRUE(
PayloadSigner::SignHash(metadata_hash, key_path, &metadata_signature));
- test_utils::ScopedTempFile metadata_sig_file("signature.XXXXXX");
- ASSERT_TRUE(test_utils::WriteFileVector(metadata_sig_file.path(),
+ metadata_sig_files.emplace_back("metadata_signature.XXXXXX");
+ ASSERT_TRUE(test_utils::WriteFileVector(metadata_sig_files.back().path(),
metadata_signature));
-
- metadata_sig_file_paths.push_back(metadata_sig_file.path());
- metadata_sig_files.push_back(std::move(metadata_sig_file));
+ metadata_sig_file_paths.push_back(metadata_sig_files.back().path());
}
string sig_files_string = base::JoinString(sig_file_paths, ":");
string metadata_sig_files_string =
@@ -377,7 +375,7 @@
GetBuildArtifactsPath(kUnittestPrivateKey2Path));
}
- std::string public_key;
+ string public_key;
if (signature_test == kSignatureGeneratedShellRotateCl2) {
public_key = GetBuildArtifactsPath(kUnittestPublicKey2Path);
} else if (signature_test == kSignatureGeneratedShellECKey) {
@@ -397,44 +395,23 @@
SignatureTest signature_test,
DeltaState* state,
uint32_t minor_version) {
- EXPECT_TRUE(utils::MakeTempFile("a_img.XXXXXX", &state->a_img, nullptr));
- EXPECT_TRUE(utils::MakeTempFile("b_img.XXXXXX", &state->b_img, nullptr));
+ state->a_img.reset(new ScopedTempFile("a_img.XXXXXX"));
+ state->b_img.reset(new ScopedTempFile("b_img.XXXXXX"));
// result_img is used in minor version 2. Instead of applying the update
// in-place on A, we apply it to a new image, result_img.
- EXPECT_TRUE(
- utils::MakeTempFile("result_img.XXXXXX", &state->result_img, nullptr));
+ state->result_img.reset(new ScopedTempFile("result_img.XXXXXX"));
EXPECT_TRUE(
base::CopyFile(GetBuildArtifactsPath().Append("gen/disk_ext2_4k.img"),
- base::FilePath(state->a_img)));
+ base::FilePath(state->a_img->path())));
- state->image_size = utils::FileSize(state->a_img);
-
- // Create ImageInfo A & B
- ImageInfo old_image_info;
- ImageInfo new_image_info;
-
- if (!full_rootfs) {
- old_image_info.set_channel("src-channel");
- old_image_info.set_board("src-board");
- old_image_info.set_version("src-version");
- old_image_info.set_key("src-key");
- old_image_info.set_build_channel("src-build-channel");
- old_image_info.set_build_version("src-build-version");
- }
-
- new_image_info.set_channel("test-channel");
- new_image_info.set_board("test-board");
- new_image_info.set_version("test-version");
- new_image_info.set_key("test-key");
- new_image_info.set_build_channel("test-build-channel");
- new_image_info.set_build_version("test-build-version");
+ state->image_size = utils::FileSize(state->a_img->path());
// Make some changes to the A image.
{
string a_mnt;
- ScopedLoopMounter b_mounter(state->a_img, &a_mnt, 0);
+ ScopedLoopMounter b_mounter(state->a_img->path(), &a_mnt, 0);
brillo::Blob hardtocompress;
while (hardtocompress.size() < 3 * kBlockSize) {
@@ -471,17 +448,18 @@
// Create a result image with image_size bytes of garbage.
brillo::Blob ones(state->image_size, 0xff);
- EXPECT_TRUE(
- utils::WriteFile(state->result_img.c_str(), ones.data(), ones.size()));
- EXPECT_EQ(utils::FileSize(state->a_img), utils::FileSize(state->result_img));
+ EXPECT_TRUE(utils::WriteFile(
+ state->result_img->path().c_str(), ones.data(), ones.size()));
+ EXPECT_EQ(utils::FileSize(state->a_img->path()),
+ utils::FileSize(state->result_img->path()));
EXPECT_TRUE(
base::CopyFile(GetBuildArtifactsPath().Append("gen/disk_ext2_4k.img"),
- base::FilePath(state->b_img)));
+ base::FilePath(state->b_img->path())));
{
// Make some changes to the B image.
string b_mnt;
- ScopedLoopMounter b_mounter(state->b_img, &b_mnt, 0);
+ ScopedLoopMounter b_mounter(state->b_img->path(), &b_mnt, 0);
base::FilePath mnt_path(b_mnt);
EXPECT_TRUE(base::CopyFile(mnt_path.Append("regular-small"),
@@ -529,18 +507,9 @@
hardtocompress.size()));
}
- string old_kernel;
- EXPECT_TRUE(
- utils::MakeTempFile("old_kernel.XXXXXX", &state->old_kernel, nullptr));
-
- string new_kernel;
- EXPECT_TRUE(
- utils::MakeTempFile("new_kernel.XXXXXX", &state->new_kernel, nullptr));
-
- string result_kernel;
- EXPECT_TRUE(utils::MakeTempFile(
- "result_kernel.XXXXXX", &state->result_kernel, nullptr));
-
+ state->old_kernel.reset(new ScopedTempFile("old_kernel.XXXXXX"));
+ state->new_kernel.reset(new ScopedTempFile("new_kernel.XXXXXX"));
+ state->result_kernel.reset(new ScopedTempFile("result_kernel.XXXXXX"));
state->kernel_size = kDefaultKernelSize;
state->old_kernel_data.resize(kDefaultKernelSize);
state->new_kernel_data.resize(state->old_kernel_data.size());
@@ -554,18 +523,17 @@
std::begin(kNewData), std::end(kNewData), state->new_kernel_data.begin());
// Write kernels to disk
- EXPECT_TRUE(utils::WriteFile(state->old_kernel.c_str(),
+ EXPECT_TRUE(utils::WriteFile(state->old_kernel->path().c_str(),
state->old_kernel_data.data(),
state->old_kernel_data.size()));
- EXPECT_TRUE(utils::WriteFile(state->new_kernel.c_str(),
+ EXPECT_TRUE(utils::WriteFile(state->new_kernel->path().c_str(),
state->new_kernel_data.data(),
state->new_kernel_data.size()));
- EXPECT_TRUE(utils::WriteFile(state->result_kernel.c_str(),
+ EXPECT_TRUE(utils::WriteFile(state->result_kernel->path().c_str(),
state->result_kernel_data.data(),
state->result_kernel_data.size()));
- EXPECT_TRUE(utils::MakeTempFile("delta.XXXXXX", &state->delta_path, nullptr));
- LOG(INFO) << "delta path: " << state->delta_path;
+ state->delta_file.reset(new ScopedTempFile("delta.XXXXXX"));
{
const string private_key =
signature_test == kSignatureGenerator
@@ -581,10 +549,10 @@
if (!full_rootfs) {
payload_config.source.partitions.emplace_back(kPartitionNameRoot);
payload_config.source.partitions.emplace_back(kPartitionNameKernel);
- payload_config.source.partitions.front().path = state->a_img;
+ payload_config.source.partitions.front().path = state->a_img->path();
if (!full_kernel)
- payload_config.source.partitions.back().path = state->old_kernel;
- payload_config.source.image_info = old_image_info;
+ payload_config.source.partitions.back().path =
+ state->old_kernel->path();
EXPECT_TRUE(payload_config.source.LoadImageSize());
for (PartitionConfig& part : payload_config.source.partitions)
EXPECT_TRUE(part.OpenFilesystem());
@@ -594,29 +562,30 @@
payload_config.hard_chunk_size = 1024 * 1024;
}
payload_config.target.partitions.emplace_back(kPartitionNameRoot);
- payload_config.target.partitions.back().path = state->b_img;
+ payload_config.target.partitions.back().path = state->b_img->path();
payload_config.target.partitions.emplace_back(kPartitionNameKernel);
- payload_config.target.partitions.back().path = state->new_kernel;
- payload_config.target.image_info = new_image_info;
+ payload_config.target.partitions.back().path = state->new_kernel->path();
EXPECT_TRUE(payload_config.target.LoadImageSize());
for (PartitionConfig& part : payload_config.target.partitions)
EXPECT_TRUE(part.OpenFilesystem());
EXPECT_TRUE(payload_config.Validate());
- EXPECT_TRUE(GenerateUpdatePayloadFile(
- payload_config, state->delta_path, private_key, &state->metadata_size));
+ EXPECT_TRUE(GenerateUpdatePayloadFile(payload_config,
+ state->delta_file->path(),
+ private_key,
+ &state->metadata_size));
}
// Extend the "partitions" holding the file system a bit.
EXPECT_EQ(0,
- HANDLE_EINTR(truncate(state->a_img.c_str(),
+ HANDLE_EINTR(truncate(state->a_img->path().c_str(),
state->image_size + 1024 * 1024)));
EXPECT_EQ(static_cast<off_t>(state->image_size + 1024 * 1024),
- utils::FileSize(state->a_img));
+ utils::FileSize(state->a_img->path()));
EXPECT_EQ(0,
- HANDLE_EINTR(truncate(state->b_img.c_str(),
+ HANDLE_EINTR(truncate(state->b_img->path().c_str(),
state->image_size + 1024 * 1024)));
EXPECT_EQ(static_cast<off_t>(state->image_size + 1024 * 1024),
- utils::FileSize(state->b_img));
+ utils::FileSize(state->b_img->path()));
if (signature_test == kSignatureGeneratedPlaceholder ||
signature_test == kSignatureGeneratedPlaceholderMismatch) {
@@ -625,13 +594,13 @@
GetBuildArtifactsPath(kUnittestPrivateKeyPath), &signature_size));
LOG(INFO) << "Inserting placeholder signature.";
ASSERT_TRUE(InsertSignaturePlaceholder(
- signature_size, state->delta_path, &state->metadata_size));
+ signature_size, state->delta_file->path(), &state->metadata_size));
if (signature_test == kSignatureGeneratedPlaceholderMismatch) {
signature_size -= 1;
LOG(INFO) << "Inserting mismatched placeholder signature.";
ASSERT_FALSE(InsertSignaturePlaceholder(
- signature_size, state->delta_path, &state->metadata_size));
+ signature_size, state->delta_file->path(), &state->metadata_size));
return;
}
}
@@ -643,13 +612,13 @@
// reflect the new size after adding the signature operation to the
// manifest.
LOG(INFO) << "Signing payload.";
- SignGeneratedPayload(state->delta_path, &state->metadata_size);
+ SignGeneratedPayload(state->delta_file->path(), &state->metadata_size);
} else if (signature_test == kSignatureGeneratedShell ||
signature_test == kSignatureGeneratedShellECKey ||
signature_test == kSignatureGeneratedShellBadKey ||
signature_test == kSignatureGeneratedShellRotateCl1 ||
signature_test == kSignatureGeneratedShellRotateCl2) {
- SignGeneratedShellPayload(signature_test, state->delta_path);
+ SignGeneratedShellPayload(signature_test, state->delta_file->path());
}
}
@@ -663,7 +632,7 @@
uint32_t minor_version) {
// Check the metadata.
{
- EXPECT_TRUE(utils::ReadFile(state->delta_path, &state->delta));
+ EXPECT_TRUE(utils::ReadFile(state->delta_file->path(), &state->delta));
PayloadMetadata payload_metadata;
EXPECT_TRUE(payload_metadata.ParsePayloadHeader(state->delta));
state->metadata_size = payload_metadata.GetMetadataSize();
@@ -738,22 +707,6 @@
EXPECT_FALSE(rootfs_part.old_partition_info().hash().empty());
}
EXPECT_FALSE(rootfs_part.new_partition_info().hash().empty());
-
- EXPECT_EQ(manifest.new_image_info().channel(), "test-channel");
- EXPECT_EQ(manifest.new_image_info().board(), "test-board");
- EXPECT_EQ(manifest.new_image_info().version(), "test-version");
- EXPECT_EQ(manifest.new_image_info().key(), "test-key");
- EXPECT_EQ(manifest.new_image_info().build_channel(), "test-build-channel");
- EXPECT_EQ(manifest.new_image_info().build_version(), "test-build-version");
-
- if (!full_rootfs) {
- EXPECT_EQ(manifest.old_image_info().channel(), "src-channel");
- EXPECT_EQ(manifest.old_image_info().board(), "src-board");
- EXPECT_EQ(manifest.old_image_info().version(), "src-version");
- EXPECT_EQ(manifest.old_image_info().key(), "src-key");
- EXPECT_EQ(manifest.old_image_info().build_channel(), "src-build-channel");
- EXPECT_EQ(manifest.old_image_info().build_version(), "src-build-version");
- }
}
MockPrefs prefs;
@@ -832,9 +785,10 @@
(*performer)->set_public_key_path(public_key_path);
(*performer)->set_update_certificates_path("");
- EXPECT_EQ(static_cast<off_t>(state->image_size),
- HashCalculator::RawHashOfFile(
- state->a_img, state->image_size, &root_part.source_hash));
+ EXPECT_EQ(
+ static_cast<off_t>(state->image_size),
+ HashCalculator::RawHashOfFile(
+ state->a_img->path(), state->image_size, &root_part.source_hash));
EXPECT_TRUE(HashCalculator::RawHashOfData(state->old_kernel_data,
&kernel_part.source_hash));
@@ -842,13 +796,15 @@
install_plan->partitions.clear();
state->fake_boot_control_.SetPartitionDevice(
- kPartitionNameRoot, install_plan->source_slot, state->a_img);
+ kPartitionNameRoot, install_plan->source_slot, state->a_img->path());
+ state->fake_boot_control_.SetPartitionDevice(kPartitionNameKernel,
+ install_plan->source_slot,
+ state->old_kernel->path());
state->fake_boot_control_.SetPartitionDevice(
- kPartitionNameKernel, install_plan->source_slot, state->old_kernel);
- state->fake_boot_control_.SetPartitionDevice(
- kPartitionNameRoot, install_plan->target_slot, state->result_img);
- state->fake_boot_control_.SetPartitionDevice(
- kPartitionNameKernel, install_plan->target_slot, state->result_kernel);
+ kPartitionNameRoot, install_plan->target_slot, state->result_img->path());
+ state->fake_boot_control_.SetPartitionDevice(kPartitionNameKernel,
+ install_plan->target_slot,
+ state->result_kernel->path());
ErrorCode expected_error, actual_error;
bool continue_writing;
@@ -927,12 +883,15 @@
return;
}
+ CompareFilesByBlock(state->result_kernel->path(),
+ state->new_kernel->path(),
+ state->kernel_size);
CompareFilesByBlock(
- state->result_kernel, state->new_kernel, state->kernel_size);
- CompareFilesByBlock(state->result_img, state->b_img, state->image_size);
+ state->result_img->path(), state->b_img->path(), state->image_size);
brillo::Blob updated_kernel_partition;
- EXPECT_TRUE(utils::ReadFile(state->result_kernel, &updated_kernel_partition));
+ EXPECT_TRUE(
+ utils::ReadFile(state->result_kernel->path(), &updated_kernel_partition));
ASSERT_GE(updated_kernel_partition.size(), base::size(kNewData));
EXPECT_TRUE(std::equal(std::begin(kNewData),
std::end(kNewData),
@@ -951,9 +910,10 @@
EXPECT_EQ(state->image_size, partitions[0].target_size);
brillo::Blob expected_new_rootfs_hash;
- EXPECT_EQ(static_cast<off_t>(state->image_size),
- HashCalculator::RawHashOfFile(
- state->b_img, state->image_size, &expected_new_rootfs_hash));
+ EXPECT_EQ(
+ static_cast<off_t>(state->image_size),
+ HashCalculator::RawHashOfFile(
+ state->b_img->path(), state->image_size, &expected_new_rootfs_hash));
EXPECT_EQ(expected_new_rootfs_hash, partitions[0].target_hash);
}
@@ -991,13 +951,6 @@
&state,
minor_version);
- ScopedPathUnlinker a_img_unlinker(state.a_img);
- ScopedPathUnlinker b_img_unlinker(state.b_img);
- ScopedPathUnlinker new_img_unlinker(state.result_img);
- ScopedPathUnlinker delta_unlinker(state.delta_path);
- ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
- ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
- ScopedPathUnlinker result_kernel_unlinker(state.result_kernel);
ApplyDeltaFile(full_kernel,
full_rootfs,
signature_test,
@@ -1015,11 +968,6 @@
DeltaState state;
uint64_t minor_version = kFullPayloadMinorVersion;
GenerateDeltaFile(true, true, -1, kSignatureGenerated, &state, minor_version);
- ScopedPathUnlinker a_img_unlinker(state.a_img);
- ScopedPathUnlinker b_img_unlinker(state.b_img);
- ScopedPathUnlinker delta_unlinker(state.delta_path);
- ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
- ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
DeltaPerformer* performer = nullptr;
ApplyDeltaFile(true,
true,
diff --git a/payload_consumer/delta_performer_unittest.cc b/payload_consumer/delta_performer_unittest.cc
index a5eb538..f742b1c 100644
--- a/payload_consumer/delta_performer_unittest.cc
+++ b/payload_consumer/delta_performer_unittest.cc
@@ -202,7 +202,7 @@
uint64_t major_version,
uint32_t minor_version,
PartitionConfig* old_part = nullptr) {
- test_utils::ScopedTempFile blob_file("Blob-XXXXXX");
+ ScopedTempFile blob_file("Blob-XXXXXX");
EXPECT_TRUE(test_utils::WriteFileVector(blob_file.path(), blob_data));
PayloadGenerationConfig config;
@@ -236,7 +236,7 @@
new_part.size = 0;
payload.AddPartition(*old_part, new_part, {}, {});
- test_utils::ScopedTempFile payload_file("Payload-XXXXXX");
+ ScopedTempFile payload_file("Payload-XXXXXX");
string private_key =
sign_payload ? GetBuildArtifactsPath(kUnittestPrivateKeyPath) : "";
EXPECT_TRUE(payload.WritePayload(payload_file.path(),
@@ -287,7 +287,7 @@
const string& source_path,
const brillo::Blob& target_data,
bool expect_success) {
- test_utils::ScopedTempFile new_part("Partition-XXXXXX");
+ ScopedTempFile new_part("Partition-XXXXXX");
EXPECT_TRUE(test_utils::WriteFileVector(new_part.path(), target_data));
payload_.size = payload_data.size();
@@ -576,7 +576,7 @@
EXPECT_TRUE(HashCalculator::RawHashOfData(expected_data, &src_hash));
aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size());
- test_utils::ScopedTempFile source("Source-XXXXXX");
+ ScopedTempFile source("Source-XXXXXX");
EXPECT_TRUE(test_utils::WriteFileVector(source.path(), expected_data));
PartitionConfig old_part(kPartitionNameRoot);
@@ -604,7 +604,7 @@
EXPECT_TRUE(HashCalculator::RawHashOfData(src, &src_hash));
aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size());
- test_utils::ScopedTempFile source("Source-XXXXXX");
+ ScopedTempFile source("Source-XXXXXX");
EXPECT_TRUE(test_utils::WriteFileVector(source.path(), src));
PartitionConfig old_part(kPartitionNameRoot);
@@ -632,7 +632,7 @@
EXPECT_TRUE(HashCalculator::RawHashOfData(expected_data, &src_hash));
aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size());
- test_utils::ScopedTempFile source("Source-XXXXXX");
+ ScopedTempFile source("Source-XXXXXX");
EXPECT_TRUE(test_utils::WriteFileVector(source.path(), actual_data));
PartitionConfig old_part(kPartitionNameRoot);
@@ -645,9 +645,6 @@
EXPECT_EQ(actual_data, ApplyPayload(payload_data, source.path(), false));
}
-
-
-
TEST_F(DeltaPerformerTest, ExtentsToByteStringTest) {
uint64_t test[] = {1, 1, 4, 2, 0, 1};
static_assert(base::size(test) % 2 == 0, "Array size uneven");
diff --git a/payload_consumer/download_action_unittest.cc b/payload_consumer/download_action_unittest.cc
index e6ca219..9daa791 100644
--- a/payload_consumer/download_action_unittest.cc
+++ b/payload_consumer/download_action_unittest.cc
@@ -51,7 +51,6 @@
using base::WriteFile;
using std::string;
using std::unique_ptr;
-using test_utils::ScopedTempFile;
using testing::_;
using testing::AtLeast;
using testing::InSequence;
@@ -133,7 +132,6 @@
loop.SetAsCurrent();
FakeSystemState fake_system_state;
- // TODO(adlr): see if we need a different file for build bots
ScopedTempFile output_temp_file;
TestDirectFileWriter writer;
EXPECT_EQ(
diff --git a/payload_consumer/extent_reader_unittest.cc b/payload_consumer/extent_reader_unittest.cc
index b7059bc..686f14d 100644
--- a/payload_consumer/extent_reader_unittest.cc
+++ b/payload_consumer/extent_reader_unittest.cc
@@ -72,7 +72,7 @@
}
FileDescriptorPtr fd_;
- test_utils::ScopedTempFile temp_file_{"ExtentReaderTest-file.XXXXXX"};
+ ScopedTempFile temp_file_{"ExtentReaderTest-file.XXXXXX"};
brillo::Blob sample_;
};
diff --git a/payload_consumer/extent_writer_unittest.cc b/payload_consumer/extent_writer_unittest.cc
index aef856b..afebb1a 100644
--- a/payload_consumer/extent_writer_unittest.cc
+++ b/payload_consumer/extent_writer_unittest.cc
@@ -59,7 +59,7 @@
void WriteAlignedExtents(size_t chunk_size, size_t first_chunk_size);
FileDescriptorPtr fd_;
- test_utils::ScopedTempFile temp_file_{"ExtentWriterTest-file.XXXXXX"};
+ ScopedTempFile temp_file_{"ExtentWriterTest-file.XXXXXX"};
};
TEST_F(ExtentWriterTest, SimpleTest) {
diff --git a/payload_consumer/file_descriptor_utils_unittest.cc b/payload_consumer/file_descriptor_utils_unittest.cc
index 48e610f..478893d 100644
--- a/payload_consumer/file_descriptor_utils_unittest.cc
+++ b/payload_consumer/file_descriptor_utils_unittest.cc
@@ -52,14 +52,13 @@
class FileDescriptorUtilsTest : public ::testing::Test {
protected:
void SetUp() override {
- EXPECT_TRUE(utils::MakeTempFile("fd_tgt.XXXXXX", &tgt_path_, nullptr));
- EXPECT_TRUE(target_->Open(tgt_path_.c_str(), O_RDWR));
+ EXPECT_TRUE(target_->Open(tgt_file_.path().c_str(), O_RDWR));
}
// Check that the |target_| file contains |expected_contents|.
void ExpectTarget(const std::string& expected_contents) {
std::string target_contents;
- EXPECT_TRUE(utils::ReadFile(tgt_path_, &target_contents));
+ EXPECT_TRUE(utils::ReadFile(tgt_file_.path(), &target_contents));
EXPECT_EQ(expected_contents.size(), target_contents.size());
if (target_contents != expected_contents) {
ADD_FAILURE() << "Contents don't match.";
@@ -70,8 +69,7 @@
}
}
- // Path to the target temporary file.
- std::string tgt_path_;
+ ScopedTempFile tgt_file_{"fd_tgt.XXXXXX"};
// Source and target file descriptor used for testing the tools.
FakeFileDescriptor* fake_source_{new FakeFileDescriptor()};
diff --git a/payload_consumer/file_writer_unittest.cc b/payload_consumer/file_writer_unittest.cc
index 59cfe2b..3b959f3 100644
--- a/payload_consumer/file_writer_unittest.cc
+++ b/payload_consumer/file_writer_unittest.cc
@@ -35,8 +35,7 @@
class FileWriterTest : public ::testing::Test {};
TEST(FileWriterTest, SimpleTest) {
- // Create a uniquely named file for testing.
- test_utils::ScopedTempFile file("FileWriterTest-XXXXXX");
+ ScopedTempFile file("FileWriterTest-XXXXXX");
DirectFileWriter file_writer;
EXPECT_EQ(0,
file_writer.Open(file.path().c_str(),
@@ -60,7 +59,7 @@
TEST(FileWriterTest, WriteErrorTest) {
// Create a uniquely named file for testing.
- test_utils::ScopedTempFile file("FileWriterTest-XXXXXX");
+ ScopedTempFile file("FileWriterTest-XXXXXX");
DirectFileWriter file_writer;
EXPECT_EQ(0,
file_writer.Open(file.path().c_str(),
diff --git a/payload_consumer/filesystem_verifier_action_unittest.cc b/payload_consumer/filesystem_verifier_action_unittest.cc
index 2971849..2c29b44 100644
--- a/payload_consumer/filesystem_verifier_action_unittest.cc
+++ b/payload_consumer/filesystem_verifier_action_unittest.cc
@@ -92,7 +92,7 @@
bool FilesystemVerifierActionTest::DoTest(bool terminate_early,
bool hash_fail) {
- test_utils::ScopedTempFile a_loop_file("a_loop_file.XXXXXX");
+ ScopedTempFile a_loop_file("a_loop_file.XXXXXX");
// Make random data for a.
const size_t kLoopFileSize = 10 * 1024 * 1024 + 512;
@@ -278,7 +278,7 @@
#ifdef __ANDROID__
TEST_F(FilesystemVerifierActionTest, RunAsRootWriteVerityTest) {
- test_utils::ScopedTempFile part_file("part_file.XXXXXX");
+ ScopedTempFile part_file("part_file.XXXXXX");
constexpr size_t filesystem_size = 200 * 4096;
constexpr size_t part_size = 256 * 4096;
brillo::Blob part_data(filesystem_size, 0x1);
@@ -340,7 +340,7 @@
#endif // __ANDROID__
TEST_F(FilesystemVerifierActionTest, RunAsRootSkipWriteVerityTest) {
- test_utils::ScopedTempFile part_file("part_file.XXXXXX");
+ ScopedTempFile part_file("part_file.XXXXXX");
constexpr size_t filesystem_size = 200 * 4096;
constexpr size_t part_size = 256 * 4096;
brillo::Blob part_data(part_size);
diff --git a/payload_consumer/install_plan.cc b/payload_consumer/install_plan.cc
index a313627..c7ef7b2 100644
--- a/payload_consumer/install_plan.cc
+++ b/payload_consumer/install_plan.cc
@@ -98,8 +98,8 @@
<< version_str
<< ", source_slot: " << BootControlInterface::SlotName(source_slot)
<< ", target_slot: " << BootControlInterface::SlotName(target_slot)
- << ", initial url: " << url_str << payloads_str
- << partitions_str << ", hash_checks_mandatory: "
+ << ", initial url: " << url_str << payloads_str << partitions_str
+ << ", hash_checks_mandatory: "
<< utils::ToString(hash_checks_mandatory)
<< ", powerwash_required: " << utils::ToString(powerwash_required)
<< ", switch_slot_on_reboot: "
diff --git a/payload_consumer/install_plan.h b/payload_consumer/install_plan.h
index f04c650..5534fb3 100644
--- a/payload_consumer/install_plan.h
+++ b/payload_consumer/install_plan.h
@@ -59,8 +59,8 @@
struct Payload {
std::vector<std::string> payload_urls; // URLs to download the payload
- uint64_t size = 0; // size of the payload
- uint64_t metadata_size = 0; // size of the metadata
+ uint64_t size = 0; // size of the payload
+ uint64_t metadata_size = 0; // size of the metadata
std::string metadata_signature; // signature of the metadata in base64
brillo::Blob hash; // SHA256 hash of the payload
InstallPayloadType type{InstallPayloadType::kUnknown};
diff --git a/payload_consumer/partition_update_generator_android.cc b/payload_consumer/partition_update_generator_android.cc
index d5d5313..25771e1 100644
--- a/payload_consumer/partition_update_generator_android.cc
+++ b/payload_consumer/partition_update_generator_android.cc
@@ -32,10 +32,8 @@
namespace chromeos_update_engine {
PartitionUpdateGeneratorAndroid::PartitionUpdateGeneratorAndroid(
- BootControlInterface* boot_control,
- size_t block_size)
- : boot_control_(boot_control),
- block_size_(block_size) {}
+ BootControlInterface* boot_control, size_t block_size)
+ : boot_control_(boot_control), block_size_(block_size) {}
bool PartitionUpdateGeneratorAndroid::
GenerateOperationsForPartitionsNotInPayload(
diff --git a/payload_consumer/partition_writer_unittest.cc b/payload_consumer/partition_writer_unittest.cc
index c1ff4f4..1ef4783 100644
--- a/payload_consumer/partition_writer_unittest.cc
+++ b/payload_consumer/partition_writer_unittest.cc
@@ -81,14 +81,14 @@
brillo::Blob PerformSourceCopyOp(const InstallOperation& op,
const brillo::Blob blob_data) {
- test_utils::ScopedTempFile source_partition("Blob-XXXXXX");
+ ScopedTempFile source_partition("Blob-XXXXXX");
DirectExtentWriter extent_writer;
FileDescriptorPtr fd(new EintrSafeFileDescriptor());
EXPECT_TRUE(fd->Open(source_partition.path().c_str(), O_RDWR));
EXPECT_TRUE(extent_writer.Init(fd, op.src_extents(), kBlockSize));
EXPECT_TRUE(extent_writer.Write(blob_data.data(), blob_data.size()));
- test_utils::ScopedTempFile target_partition("Blob-XXXXXX");
+ ScopedTempFile target_partition("Blob-XXXXXX");
install_part_.source_path = source_partition.path();
install_part_.target_path = target_partition.path();
@@ -120,7 +120,7 @@
// file descriptor when the size of the error corrected one is too small.
TEST_F(PartitionWriterTest, ErrorCorrectionSourceCopyWhenNoHashFallbackTest) {
constexpr size_t kCopyOperationSize = 4 * 4096;
- test_utils::ScopedTempFile source("Source-XXXXXX");
+ ScopedTempFile source("Source-XXXXXX");
// Setup the source path with the right expected data.
brillo::Blob expected_data = FakeFileDescriptorData(kCopyOperationSize);
EXPECT_TRUE(test_utils::WriteFileVector(source.path(), expected_data));
@@ -172,7 +172,7 @@
TEST_F(PartitionWriterTest, ChooseSourceFDTest) {
constexpr size_t kSourceSize = 4 * 4096;
- test_utils::ScopedTempFile source("Source-XXXXXX");
+ ScopedTempFile source("Source-XXXXXX");
// Write invalid data to the source image, which doesn't match the expected
// hash.
brillo::Blob invalid_data(kSourceSize, 0x55);
diff --git a/payload_consumer/payload_verifier.cc b/payload_consumer/payload_verifier.cc
index 24e337e..85902c8 100644
--- a/payload_consumer/payload_verifier.cc
+++ b/payload_consumer/payload_verifier.cc
@@ -203,7 +203,7 @@
//
// openssl rsautl -verify -pubin -inkey <(echo pem_public_key)
// -in |sig_data| -out |out_hash_data|
- RSA* rsa = EVP_PKEY_get0_RSA(public_key);
+ RSA* rsa = EVP_PKEY_get0_RSA(const_cast<EVP_PKEY*>(public_key));
TEST_AND_RETURN_FALSE(rsa != nullptr);
unsigned int keysize = RSA_size(rsa);
diff --git a/payload_consumer/postinstall_runner_action.cc b/payload_consumer/postinstall_runner_action.cc
index e8fa81b..91c3a64 100644
--- a/payload_consumer/postinstall_runner_action.cc
+++ b/payload_consumer/postinstall_runner_action.cc
@@ -63,9 +63,8 @@
// that retains a small amount of system state such as enrollment and
// network configuration. In both cases all user accounts are deleted.
if (install_plan_.powerwash_required || install_plan_.is_rollback) {
- bool save_rollback_data =
- install_plan_.is_rollback && install_plan_.rollback_data_save_requested;
- if (hardware_->SchedulePowerwash(save_rollback_data)) {
+ if (hardware_->SchedulePowerwash(
+ install_plan_.rollback_data_save_requested)) {
powerwash_scheduled_ = true;
} else {
return CompletePostinstall(ErrorCode::kPostinstallPowerwashError);
diff --git a/payload_consumer/postinstall_runner_action_unittest.cc b/payload_consumer/postinstall_runner_action_unittest.cc
index cf5158b..5910c23 100644
--- a/payload_consumer/postinstall_runner_action_unittest.cc
+++ b/payload_consumer/postinstall_runner_action_unittest.cc
@@ -26,9 +26,14 @@
#include <base/bind.h>
#include <base/files/file_util.h>
+#if BASE_VER < 780000 // Android
#include <base/message_loop/message_loop.h>
+#endif // BASE_VER < 780000
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
+#if BASE_VER >= 780000 // CrOS
+#include <base/task/single_thread_task_executor.h>
+#endif // BASE_VER >= 780000
#include <brillo/message_loops/base_message_loop.h>
#include <brillo/message_loops/message_loop_utils.h>
#include <gmock/gmock.h>
@@ -156,8 +161,13 @@
}
protected:
+#if BASE_VER < 780000 // Android
base::MessageLoopForIO base_loop_;
brillo::BaseMessageLoop loop_{&base_loop_};
+#else // CrOS
+ base::SingleThreadTaskExecutor base_loop_{base::MessagePumpType::IO};
+ brillo::BaseMessageLoop loop_{base_loop_.task_runner()};
+#endif // BASE_VER < 780000
brillo::AsynchronousSignalHandler async_signal_handler_;
Subprocess subprocess_;
diff --git a/payload_consumer/verity_writer_android_unittest.cc b/payload_consumer/verity_writer_android_unittest.cc
index f943ce8..ec22ffb 100644
--- a/payload_consumer/verity_writer_android_unittest.cc
+++ b/payload_consumer/verity_writer_android_unittest.cc
@@ -39,7 +39,7 @@
VerityWriterAndroid verity_writer_;
InstallPlan::Partition partition_;
- test_utils::ScopedTempFile temp_file_;
+ ScopedTempFile temp_file_;
};
TEST_F(VerityWriterAndroidTest, SimpleTest) {
diff --git a/payload_generator/ab_generator_unittest.cc b/payload_generator/ab_generator_unittest.cc
index 7a95284..84eeb77 100644
--- a/payload_generator/ab_generator_unittest.cc
+++ b/payload_generator/ab_generator_unittest.cc
@@ -70,8 +70,7 @@
part_data.push_back(dis(gen));
}
ASSERT_EQ(part_size, part_data.size());
- test_utils::ScopedTempFile part_file(
- "SplitReplaceOrReplaceXzTest_part.XXXXXX");
+ ScopedTempFile part_file("SplitReplaceOrReplaceXzTest_part.XXXXXX");
ASSERT_TRUE(test_utils::WriteFileVector(part_file.path(), part_data));
// Create original operation and blob data.
@@ -107,8 +106,7 @@
aop.name = "SplitTestOp";
// Create the data file.
- test_utils::ScopedTempFile data_file(
- "SplitReplaceOrReplaceXzTest_data.XXXXXX");
+ ScopedTempFile data_file("SplitReplaceOrReplaceXzTest_data.XXXXXX");
EXPECT_TRUE(test_utils::WriteFileVector(data_file.path(), op_blob));
int data_fd = open(data_file.path().c_str(), O_RDWR, 000);
EXPECT_GE(data_fd, 0);
@@ -220,8 +218,7 @@
part_data.push_back(dis(gen));
}
ASSERT_EQ(part_size, part_data.size());
- test_utils::ScopedTempFile part_file(
- "MergeReplaceOrReplaceXzTest_part.XXXXXX");
+ ScopedTempFile part_file("MergeReplaceOrReplaceXzTest_part.XXXXXX");
ASSERT_TRUE(test_utils::WriteFileVector(part_file.path(), part_data));
// Create original operations and blob data.
@@ -271,8 +268,7 @@
aops.push_back(second_aop);
// Create the data file.
- test_utils::ScopedTempFile data_file(
- "MergeReplaceOrReplaceXzTest_data.XXXXXX");
+ ScopedTempFile data_file("MergeReplaceOrReplaceXzTest_data.XXXXXX");
EXPECT_TRUE(test_utils::WriteFileVector(data_file.path(), blob_data));
int data_fd = open(data_file.path().c_str(), O_RDWR, 000);
EXPECT_GE(data_fd, 0);
@@ -561,7 +557,7 @@
second_aop.op = second_op;
aops.push_back(second_aop);
- test_utils::ScopedTempFile src_part_file("AddSourceHashTest_src_part.XXXXXX");
+ ScopedTempFile src_part_file("AddSourceHashTest_src_part.XXXXXX");
brillo::Blob src_data(kBlockSize);
test_utils::FillWithData(&src_data);
ASSERT_TRUE(test_utils::WriteFileVector(src_part_file.path(), src_data));
diff --git a/payload_generator/blob_file_writer_unittest.cc b/payload_generator/blob_file_writer_unittest.cc
index 487bc73..f4dcafb 100644
--- a/payload_generator/blob_file_writer_unittest.cc
+++ b/payload_generator/blob_file_writer_unittest.cc
@@ -31,24 +31,21 @@
class BlobFileWriterTest : public ::testing::Test {};
TEST(BlobFileWriterTest, SimpleTest) {
- string blob_path;
- int blob_fd;
- EXPECT_TRUE(
- utils::MakeTempFile("BlobFileWriterTest.XXXXXX", &blob_path, &blob_fd));
+ ScopedTempFile blob_file("BlobFileWriterTest.XXXXXX", true);
off_t blob_file_size = 0;
- BlobFileWriter blob_file(blob_fd, &blob_file_size);
+ BlobFileWriter blob_file_writer(blob_file.fd(), &blob_file_size);
- off_t blob_size = 1024;
- brillo::Blob blob(blob_size);
+ const off_t kBlobSize = 1024;
+ brillo::Blob blob(kBlobSize);
FillWithData(&blob);
- EXPECT_EQ(0, blob_file.StoreBlob(blob));
- EXPECT_EQ(blob_size, blob_file.StoreBlob(blob));
+ EXPECT_EQ(0, blob_file_writer.StoreBlob(blob));
+ EXPECT_EQ(kBlobSize, blob_file_writer.StoreBlob(blob));
- brillo::Blob stored_blob(blob_size);
+ brillo::Blob stored_blob(kBlobSize);
ssize_t bytes_read;
- ASSERT_TRUE(
- utils::PReadAll(blob_fd, stored_blob.data(), blob_size, 0, &bytes_read));
- EXPECT_EQ(bytes_read, blob_size);
+ ASSERT_TRUE(utils::PReadAll(
+ blob_file.fd(), stored_blob.data(), kBlobSize, 0, &bytes_read));
+ EXPECT_EQ(bytes_read, kBlobSize);
EXPECT_EQ(blob, stored_blob);
}
diff --git a/payload_generator/block_mapping_unittest.cc b/payload_generator/block_mapping_unittest.cc
index 9b9b4f1..017548a 100644
--- a/payload_generator/block_mapping_unittest.cc
+++ b/payload_generator/block_mapping_unittest.cc
@@ -36,8 +36,8 @@
class BlockMappingTest : public ::testing::Test {
protected:
// Old new partition files used in testing.
- test_utils::ScopedTempFile old_part_{"BlockMappingTest_old.XXXXXX"};
- test_utils::ScopedTempFile new_part_{"BlockMappingTest_new.XXXXXX"};
+ ScopedTempFile old_part_{"BlockMappingTest_old.XXXXXX"};
+ ScopedTempFile new_part_{"BlockMappingTest_new.XXXXXX"};
size_t block_size_{1024};
BlockMapping bm_{block_size_}; // BlockMapping under test.
diff --git a/payload_generator/boot_img_filesystem_unittest.cc b/payload_generator/boot_img_filesystem_unittest.cc
index 0b115e0..7805156 100644
--- a/payload_generator/boot_img_filesystem_unittest.cc
+++ b/payload_generator/boot_img_filesystem_unittest.cc
@@ -63,7 +63,7 @@
return boot_img;
}
- test_utils::ScopedTempFile boot_file_;
+ ScopedTempFile boot_file_;
};
TEST_F(BootImgFilesystemTest, SimpleTest) {
diff --git a/payload_generator/delta_diff_generator.cc b/payload_generator/delta_diff_generator.cc
index c2b35ee..ff8b0da 100644
--- a/payload_generator/delta_diff_generator.cc
+++ b/payload_generator/delta_diff_generator.cc
@@ -119,18 +119,10 @@
PayloadFile payload;
TEST_AND_RETURN_FALSE(payload.Init(config));
- const string kTempFileTemplate("CrAU_temp_data.XXXXXX");
- string temp_file_path;
- int data_file_fd;
- TEST_AND_RETURN_FALSE(
- utils::MakeTempFile(kTempFileTemplate, &temp_file_path, &data_file_fd));
- ScopedPathUnlinker temp_file_unlinker(temp_file_path);
- TEST_AND_RETURN_FALSE(data_file_fd >= 0);
-
+ ScopedTempFile data_file("CrAU_temp_data.XXXXXX", true);
{
off_t data_file_size = 0;
- ScopedFdCloser data_file_fd_closer(&data_file_fd);
- BlobFileWriter blob_file(data_file_fd, &data_file_size);
+ BlobFileWriter blob_file(data_file.fd(), &data_file_size);
if (config.is_delta) {
TEST_AND_RETURN_FALSE(config.source.partitions.size() ==
config.target.partitions.size());
@@ -190,11 +182,12 @@
std::move(all_merge_sequences[i])));
}
}
+ data_file.CloseFd();
LOG(INFO) << "Writing payload file...";
// Write payload file to disk.
TEST_AND_RETURN_FALSE(payload.WritePayload(
- output_path, temp_file_path, private_key_path, metadata_size));
+ output_path, data_file.path(), private_key_path, metadata_size));
LOG(INFO) << "All done. Successfully created delta file with "
<< "metadata size = " << *metadata_size;
diff --git a/payload_generator/delta_diff_utils.cc b/payload_generator/delta_diff_utils.cc
index 220c7ae..3c025e1 100644
--- a/payload_generator/delta_diff_utils.cc
+++ b/payload_generator/delta_diff_utils.cc
@@ -822,17 +822,13 @@
// Only Puffdiff if both files have at least one deflate left.
if (!src_deflates.empty() && !dst_deflates.empty()) {
brillo::Blob puffdiff_delta;
- string temp_file_path;
- TEST_AND_RETURN_FALSE(utils::MakeTempFile(
- "puffdiff-delta.XXXXXX", &temp_file_path, nullptr));
- ScopedPathUnlinker temp_file_unlinker(temp_file_path);
-
+ ScopedTempFile temp_file("puffdiff-delta.XXXXXX");
// Perform PuffDiff operation.
TEST_AND_RETURN_FALSE(puffin::PuffDiff(old_data,
new_data,
src_deflates,
dst_deflates,
- temp_file_path,
+ temp_file.path(),
&puffdiff_delta));
TEST_AND_RETURN_FALSE(puffdiff_delta.size() > 0);
if (IsDiffOperationBetter(operation,
diff --git a/payload_generator/delta_diff_utils_unittest.cc b/payload_generator/delta_diff_utils_unittest.cc
index 0857f9c..f2db1bd 100644
--- a/payload_generator/delta_diff_utils_unittest.cc
+++ b/payload_generator/delta_diff_utils_unittest.cc
@@ -69,13 +69,12 @@
// Create a fake filesystem of the given |size| and initialize the partition
// holding it in the PartitionConfig |part|.
void CreatePartition(PartitionConfig* part,
- const string& pattern,
+ ScopedTempFile* part_file,
uint64_t block_size,
off_t size) {
- int fd = -1;
- ASSERT_TRUE(utils::MakeTempFile(pattern.c_str(), &part->path, &fd));
- ASSERT_EQ(0, ftruncate(fd, size));
- ASSERT_EQ(0, close(fd));
+ part->path = part_file->path();
+ ASSERT_EQ(0, ftruncate(part_file->fd(), size));
+ part_file->CloseFd();
part->fs_interface.reset(new FakeFilesystem(block_size, size / block_size));
part->size = size;
}
@@ -112,30 +111,20 @@
void SetUp() override {
CreatePartition(&old_part_,
- "DeltaDiffUtilsTest-old_part-XXXXXX",
+ &old_part_file_,
block_size_,
block_size_ * kDefaultBlockCount);
CreatePartition(&new_part_,
- "DeltaDiffUtilsTest-old_part-XXXXXX",
+ &new_part_file_,
block_size_,
block_size_ * kDefaultBlockCount);
- ASSERT_TRUE(utils::MakeTempFile(
- "DeltaDiffUtilsTest-blob-XXXXXX", &blob_path_, &blob_fd_));
- }
-
- void TearDown() override {
- unlink(old_part_.path.c_str());
- unlink(new_part_.path.c_str());
- if (blob_fd_ != -1)
- close(blob_fd_);
- unlink(blob_path_.c_str());
}
// Helper function to call DeltaMovedAndZeroBlocks() using this class' data
// members. This simply avoids repeating all the arguments that never change.
bool RunDeltaMovedAndZeroBlocks(ssize_t chunk_blocks,
uint32_t minor_version) {
- BlobFileWriter blob_file(blob_fd_, &blob_size_);
+ BlobFileWriter blob_file(tmp_blob_file_.fd(), &blob_size_);
PayloadVersion version(kBrilloMajorPayloadVersion, minor_version);
ExtentRanges old_zero_blocks;
return diff_utils::DeltaMovedAndZeroBlocks(&aops_,
@@ -155,10 +144,11 @@
// with
PartitionConfig old_part_{"part"};
PartitionConfig new_part_{"part"};
+ ScopedTempFile old_part_file_{"DeltaDiffUtilsTest-old_part-XXXXXX", true};
+ ScopedTempFile new_part_file_{"DeltaDiffUtilsTest-new_part-XXXXXX", true};
// The file holding the output blob from the various diff utils functions.
- string blob_path_;
- int blob_fd_{-1};
+ ScopedTempFile tmp_blob_file_{"DeltaDiffUtilsTest-blob-XXXXXX", true};
off_t blob_size_{0};
size_t block_size_{kBlockSize};
@@ -173,7 +163,7 @@
new_part_.verity.hash_tree_extent = ExtentForRange(20, 30);
new_part_.verity.fec_extent = ExtentForRange(40, 50);
- BlobFileWriter blob_file(blob_fd_, &blob_size_);
+ BlobFileWriter blob_file(tmp_blob_file_.fd(), &blob_size_);
EXPECT_TRUE(diff_utils::DeltaReadPartition(
&aops_,
old_part_,
diff --git a/payload_generator/ext2_filesystem_unittest.cc b/payload_generator/ext2_filesystem_unittest.cc
index 54600e9..88e1538 100644
--- a/payload_generator/ext2_filesystem_unittest.cc
+++ b/payload_generator/ext2_filesystem_unittest.cc
@@ -62,7 +62,7 @@
class Ext2FilesystemTest : public ::testing::Test {};
TEST_F(Ext2FilesystemTest, InvalidFilesystem) {
- test_utils::ScopedTempFile fs_filename_{"Ext2FilesystemTest-XXXXXX"};
+ ScopedTempFile fs_filename_{"Ext2FilesystemTest-XXXXXX"};
ASSERT_EQ(0, truncate(fs_filename_.path().c_str(), kDefaultFilesystemSize));
unique_ptr<Ext2Filesystem> fs =
Ext2Filesystem::CreateFromFile(fs_filename_.path());
diff --git a/payload_generator/extent_ranges_unittest.cc b/payload_generator/extent_ranges_unittest.cc
index 326e936..f55bb73 100644
--- a/payload_generator/extent_ranges_unittest.cc
+++ b/payload_generator/extent_ranges_unittest.cc
@@ -52,8 +52,8 @@
}
}
-#define EXPECT_RANGE_EQ(ranges, var) \
- do { \
+#define EXPECT_RANGE_EQ(ranges, var) \
+ do { \
ExpectRangeEq(ranges, var, base::size(var), __LINE__); \
} while (0)
diff --git a/payload_generator/full_update_generator_unittest.cc b/payload_generator/full_update_generator_unittest.cc
index 5f39e8b..d3b3491 100644
--- a/payload_generator/full_update_generator_unittest.cc
+++ b/payload_generator/full_update_generator_unittest.cc
@@ -41,11 +41,9 @@
config_.block_size = 4096;
new_part_conf.path = part_file_.path();
- EXPECT_TRUE(utils::MakeTempFile(
- "FullUpdateTest_blobs.XXXXXX", &out_blobs_path_, &out_blobs_fd_));
- blob_file_.reset(new BlobFileWriter(out_blobs_fd_, &out_blobs_length_));
- out_blobs_unlinker_.reset(new ScopedPathUnlinker(out_blobs_path_));
+ blob_file_writer_.reset(
+ new BlobFileWriter(blob_file_.fd(), &out_blobs_length_));
}
PayloadGenerationConfig config_;
@@ -54,14 +52,11 @@
vector<AnnotatedOperation> aops;
// Output file holding the payload blobs.
- string out_blobs_path_;
- int out_blobs_fd_{-1};
off_t out_blobs_length_{0};
- ScopedFdCloser out_blobs_fd_closer_{&out_blobs_fd_};
- test_utils::ScopedTempFile part_file_{"FullUpdateTest_partition.XXXXXX"};
+ ScopedTempFile part_file_{"FullUpdateTest_partition.XXXXXX"};
- std::unique_ptr<BlobFileWriter> blob_file_;
- std::unique_ptr<ScopedPathUnlinker> out_blobs_unlinker_;
+ ScopedTempFile blob_file_{"FullUpdateTest_blobs.XXXXXX", true};
+ std::unique_ptr<BlobFileWriter> blob_file_writer_;
// FullUpdateGenerator under test.
FullUpdateGenerator generator_;
@@ -77,7 +72,7 @@
EXPECT_TRUE(generator_.GenerateOperations(config_,
new_part_conf, // this is ignored
new_part_conf,
- blob_file_.get(),
+ blob_file_writer_.get(),
&aops));
int64_t new_part_chunks = new_part_conf.size / config_.hard_chunk_size;
EXPECT_EQ(new_part_chunks, static_cast<int64_t>(aops.size()));
@@ -108,7 +103,7 @@
EXPECT_TRUE(generator_.GenerateOperations(config_,
new_part_conf, // this is ignored
new_part_conf,
- blob_file_.get(),
+ blob_file_writer_.get(),
&aops));
// new_part has one chunk and a half.
EXPECT_EQ(2U, aops.size());
@@ -129,7 +124,7 @@
EXPECT_TRUE(generator_.GenerateOperations(config_,
new_part_conf, // this is ignored
new_part_conf,
- blob_file_.get(),
+ blob_file_writer_.get(),
&aops));
// new_part has less than one chunk.
diff --git a/payload_generator/generate_delta_main.cc b/payload_generator/generate_delta_main.cc
index dd41a29..1944847 100644
--- a/payload_generator/generate_delta_main.cc
+++ b/payload_generator/generate_delta_main.cc
@@ -74,38 +74,6 @@
}
}
-bool ParseImageInfo(const string& channel,
- const string& board,
- const string& version,
- const string& key,
- const string& build_channel,
- const string& build_version,
- ImageInfo* image_info) {
- // All of these arguments should be present or missing.
- bool empty = channel.empty();
-
- CHECK_EQ(channel.empty(), empty);
- CHECK_EQ(board.empty(), empty);
- CHECK_EQ(version.empty(), empty);
- CHECK_EQ(key.empty(), empty);
-
- if (empty)
- return false;
-
- image_info->set_channel(channel);
- image_info->set_board(board);
- image_info->set_version(version);
- image_info->set_key(key);
-
- image_info->set_build_channel(build_channel.empty() ? channel
- : build_channel);
-
- image_info->set_build_version(build_version.empty() ? version
- : build_version);
-
- return true;
-}
-
void CalculateHashForSigning(const vector<size_t>& sizes,
const string& out_hash_file,
const string& out_metadata_hash_file,
@@ -426,51 +394,6 @@
"The per-partition maximum timestamps which the OS allowed to apply this "
"payload. Passed in comma separated pairs, e.x. system:1234,vendor:5678");
- DEFINE_string(old_channel,
- "",
- "The channel for the old image. 'dev-channel', 'npo-channel', "
- "etc. Ignored, except during delta generation.");
- DEFINE_string(old_board,
- "",
- "The board for the old image. 'x86-mario', 'lumpy', "
- "etc. Ignored, except during delta generation.");
- DEFINE_string(
- old_version, "", "The build version of the old image. 1.2.3, etc.");
- DEFINE_string(old_key,
- "",
- "The key used to sign the old image. 'premp', 'mp', 'mp-v3',"
- " etc");
- DEFINE_string(old_build_channel,
- "",
- "The channel for the build of the old image. 'dev-channel', "
- "etc, but will never contain special channels such as "
- "'npo-channel'. Ignored, except during delta generation.");
- DEFINE_string(old_build_version,
- "",
- "The version of the build containing the old image.");
-
- DEFINE_string(new_channel,
- "",
- "The channel for the new image. 'dev-channel', 'npo-channel', "
- "etc. Ignored, except during delta generation.");
- DEFINE_string(new_board,
- "",
- "The board for the new image. 'x86-mario', 'lumpy', "
- "etc. Ignored, except during delta generation.");
- DEFINE_string(
- new_version, "", "The build version of the new image. 1.2.3, etc.");
- DEFINE_string(new_key,
- "",
- "The key used to sign the new image. 'premp', 'mp', 'mp-v3',"
- " etc");
- DEFINE_string(new_build_channel,
- "",
- "The channel for the build of the new image. 'dev-channel', "
- "etc, but will never contain special channels such as "
- "'npo-channel'. Ignored, except during delta generation.");
- DEFINE_string(new_build_version,
- "",
- "The version of the build containing the new image.");
DEFINE_string(new_postinstall_config_file,
"",
"A config file specifying postinstall related metadata. "
@@ -501,7 +424,11 @@
Terminator::Init();
logging::LoggingSettings log_settings;
+#if BASE_VER < 780000
log_settings.log_file = "delta_generator.log";
+#else
+ log_settings.log_file_path = "delta_generator.log";
+#endif
log_settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
log_settings.lock_log = logging::LOCK_LOG_FILE;
log_settings.delete_old = logging::APPEND_TO_OLD_LOG_FILE;
@@ -680,24 +607,6 @@
CHECK(!FLAGS_out_file.empty());
- // Ignore failures. These are optional arguments.
- ParseImageInfo(FLAGS_new_channel,
- FLAGS_new_board,
- FLAGS_new_version,
- FLAGS_new_key,
- FLAGS_new_build_channel,
- FLAGS_new_build_version,
- &payload_config.target.image_info);
-
- // Ignore failures. These are optional arguments.
- ParseImageInfo(FLAGS_old_channel,
- FLAGS_old_board,
- FLAGS_old_version,
- FLAGS_old_key,
- FLAGS_old_build_channel,
- FLAGS_old_build_version,
- &payload_config.source.image_info);
-
payload_config.rootfs_partition_size = FLAGS_rootfs_partition_size;
if (payload_config.is_delta) {
diff --git a/payload_generator/mapfile_filesystem_unittest.cc b/payload_generator/mapfile_filesystem_unittest.cc
index 36ae3bf..57b672b 100644
--- a/payload_generator/mapfile_filesystem_unittest.cc
+++ b/payload_generator/mapfile_filesystem_unittest.cc
@@ -55,8 +55,8 @@
class MapfileFilesystemTest : public ::testing::Test {
protected:
- test_utils::ScopedTempFile temp_file_{"mapfile_file.XXXXXX"};
- test_utils::ScopedTempFile temp_mapfile_{"mapfile_mapfile.XXXXXX"};
+ ScopedTempFile temp_file_{"mapfile_file.XXXXXX"};
+ ScopedTempFile temp_mapfile_{"mapfile_mapfile.XXXXXX"};
};
TEST_F(MapfileFilesystemTest, EmptyFilesystem) {
diff --git a/payload_generator/payload_file.cc b/payload_generator/payload_file.cc
index 49dff4e..74423d1 100644
--- a/payload_generator/payload_file.cc
+++ b/payload_generator/payload_file.cc
@@ -64,13 +64,6 @@
TEST_AND_RETURN_FALSE(config.version.Validate());
major_version_ = config.version.major;
manifest_.set_minor_version(config.version.minor);
-
- if (!config.source.ImageInfoIsEmpty())
- *(manifest_.mutable_old_image_info()) = config.source.image_info;
-
- if (!config.target.ImageInfoIsEmpty())
- *(manifest_.mutable_new_image_info()) = config.target.image_info;
-
manifest_.set_block_size(config.block_size);
manifest_.set_max_timestamp(config.max_timestamp);
@@ -110,11 +103,9 @@
const string& private_key_path,
uint64_t* metadata_size_out) {
// Reorder the data blobs with the manifest_.
- string ordered_blobs_path;
- TEST_AND_RETURN_FALSE(utils::MakeTempFile(
- "CrAU_temp_data.ordered.XXXXXX", &ordered_blobs_path, nullptr));
- ScopedPathUnlinker ordered_blobs_unlinker(ordered_blobs_path);
- TEST_AND_RETURN_FALSE(ReorderDataBlobs(data_blobs_path, ordered_blobs_path));
+ ScopedTempFile ordered_blobs_file("CrAU_temp_data.ordered.XXXXXX");
+ TEST_AND_RETURN_FALSE(
+ ReorderDataBlobs(data_blobs_path, ordered_blobs_file.path()));
// Check that install op blobs are in order.
uint64_t next_blob_offset = 0;
@@ -238,7 +229,7 @@
// Append the data blobs.
LOG(INFO) << "Writing final delta file data blobs...";
- int blobs_fd = open(ordered_blobs_path.c_str(), O_RDONLY, 0);
+ int blobs_fd = open(ordered_blobs_file.path().c_str(), O_RDONLY, 0);
ScopedFdCloser blobs_fd_closer(&blobs_fd);
TEST_AND_RETURN_FALSE(blobs_fd >= 0);
for (;;) {
diff --git a/payload_generator/payload_file_unittest.cc b/payload_generator/payload_file_unittest.cc
index 45faebb..1fd36f5 100644
--- a/payload_generator/payload_file_unittest.cc
+++ b/payload_generator/payload_file_unittest.cc
@@ -36,7 +36,7 @@
};
TEST_F(PayloadFileTest, ReorderBlobsTest) {
- test_utils::ScopedTempFile orig_blobs("ReorderBlobsTest.orig.XXXXXX");
+ ScopedTempFile orig_blobs("ReorderBlobsTest.orig.XXXXXX");
// The operations have three blob and one gap (the whitespace):
// Rootfs operation 1: [8, 3] bcd
@@ -45,7 +45,7 @@
string orig_data = "kernel abcd";
EXPECT_TRUE(test_utils::WriteFileString(orig_blobs.path(), orig_data));
- test_utils::ScopedTempFile new_blobs("ReorderBlobsTest.new.XXXXXX");
+ ScopedTempFile new_blobs("ReorderBlobsTest.new.XXXXXX");
payload_.part_vec_.resize(2);
diff --git a/payload_generator/payload_generation_config.cc b/payload_generator/payload_generation_config.cc
index 9c5832d..ef2f240 100644
--- a/payload_generator/payload_generation_config.cc
+++ b/payload_generator/payload_generation_config.cc
@@ -103,7 +103,6 @@
}
bool ImageConfig::ValidateIsEmpty() const {
- TEST_AND_RETURN_FALSE(ImageInfoIsEmpty());
return partitions.empty();
}
@@ -215,13 +214,6 @@
return true;
}
-bool ImageConfig::ImageInfoIsEmpty() const {
- return image_info.board().empty() && image_info.key().empty() &&
- image_info.channel().empty() && image_info.version().empty() &&
- image_info.build_channel().empty() &&
- image_info.build_version().empty();
-}
-
PayloadVersion::PayloadVersion(uint64_t major_version, uint32_t minor_version) {
major = major_version;
minor = minor_version;
@@ -293,9 +285,6 @@
TEST_AND_RETURN_FALSE(part.verity.IsEmpty());
}
- // If new_image_info is present, old_image_info must be present.
- TEST_AND_RETURN_FALSE(source.ImageInfoIsEmpty() ==
- target.ImageInfoIsEmpty());
} else {
// All the "source" image fields must be empty for full payloads.
TEST_AND_RETURN_FALSE(source.ValidateIsEmpty());
diff --git a/payload_generator/payload_generation_config.h b/payload_generator/payload_generation_config.h
index ec63043..1d88101 100644
--- a/payload_generator/payload_generation_config.h
+++ b/payload_generator/payload_generation_config.h
@@ -149,13 +149,6 @@
// Validate |dynamic_partition_metadata| against |partitions|.
bool ValidateDynamicPartitionMetadata() const;
- // Returns whether the |image_info| field is empty.
- bool ImageInfoIsEmpty() const;
-
- // The ImageInfo message defined in the update_metadata.proto file describes
- // the metadata of the image.
- ImageInfo image_info;
-
// The updated partitions.
std::vector<PartitionConfig> partitions;
diff --git a/payload_generator/payload_generation_config_android_unittest.cc b/payload_generator/payload_generation_config_android_unittest.cc
index 44eaf55..e87b034 100644
--- a/payload_generator/payload_generation_config_android_unittest.cc
+++ b/payload_generator/payload_generation_config_android_unittest.cc
@@ -138,8 +138,7 @@
}
ImageConfig image_config_;
- test_utils::ScopedTempFile temp_file_{
- "PayloadGenerationConfigAndroidTest.XXXXXX"};
+ ScopedTempFile temp_file_{"PayloadGenerationConfigAndroidTest.XXXXXX"};
};
TEST_F(PayloadGenerationConfigAndroidTest, LoadVerityConfigSimpleTest) {
diff --git a/payload_generator/payload_properties.cc b/payload_generator/payload_properties.cc
index bc82eb7..bcf4fbd 100644
--- a/payload_generator/payload_properties.cc
+++ b/payload_generator/payload_properties.cc
@@ -47,8 +47,6 @@
// These are needed by the Nebraska and devserver.
const char kPayloadPropertyJsonPayloadSize[] = "size";
const char kPayloadPropertyJsonIsDelta[] = "is_delta";
-const char kPayloadPropertyJsonTargetVersion[] = "target_version";
-const char kPayloadPropertyJsonSourceVersion[] = "source_version";
} // namespace
PayloadProperties::PayloadProperties(const string& payload_path)
@@ -65,10 +63,6 @@
properties.SetInteger(kPayloadPropertyJsonPayloadSize, payload_size_);
properties.SetString(kPayloadPropertyJsonPayloadHash, payload_hash_);
properties.SetBoolean(kPayloadPropertyJsonIsDelta, is_delta_);
- properties.SetString(kPayloadPropertyJsonTargetVersion, target_version_);
- if (is_delta_) {
- properties.SetString(kPayloadPropertyJsonSourceVersion, source_version_);
- }
return base::JSONWriter::Write(properties, json_str);
}
@@ -119,23 +113,11 @@
metadata_signatures_ = base::JoinString(base64_signatures, ":");
}
- is_delta_ = manifest.has_old_image_info() ||
- std::any_of(manifest.partitions().begin(),
+ is_delta_ = std::any_of(manifest.partitions().begin(),
manifest.partitions().end(),
[](const PartitionUpdate& part) {
return part.has_old_partition_info();
});
-
- if (manifest.has_new_image_info()) {
- target_version_ = manifest.new_image_info().version();
- } else {
- target_version_ = "99999.0.0";
- }
-
- // No need to set the source version if it was not a delta payload.
- if (is_delta_ && manifest.has_old_image_info()) {
- source_version_ = manifest.old_image_info().version();
- }
return true;
}
diff --git a/payload_generator/payload_properties.h b/payload_generator/payload_properties.h
index 3b34511..846b181 100644
--- a/payload_generator/payload_properties.h
+++ b/payload_generator/payload_properties.h
@@ -62,9 +62,6 @@
// Whether the payload is a delta (true) or full (false).
bool is_delta_;
- std::string target_version_;
- std::string source_version_;
-
DISALLOW_COPY_AND_ASSIGN(PayloadProperties);
};
diff --git a/payload_generator/payload_properties_unittest.cc b/payload_generator/payload_properties_unittest.cc
index e0072fc..ed936ff 100644
--- a/payload_generator/payload_properties_unittest.cc
+++ b/payload_generator/payload_properties_unittest.cc
@@ -40,7 +40,6 @@
#include "update_engine/payload_generator/payload_file.h"
#include "update_engine/payload_generator/payload_generation_config.h"
-using chromeos_update_engine::test_utils::ScopedTempFile;
using std::string;
using std::unique_ptr;
using std::vector;
@@ -57,19 +56,9 @@
PayloadGenerationConfig config;
config.version.major = kBrilloMajorPayloadVersion;
config.version.minor = kSourceMinorPayloadVersion;
- config.source.image_info.set_version("123.0.0");
- config.target.image_info.set_version("456.7.8");
PayloadFile payload;
EXPECT_TRUE(payload.Init(config));
- const string kTempFileTemplate = "temp_data.XXXXXX";
- int data_file_fd;
- string temp_file_path;
- EXPECT_TRUE(
- utils::MakeTempFile(kTempFileTemplate, &temp_file_path, &data_file_fd));
- ScopedPathUnlinker temp_file_unlinker(temp_file_path);
- EXPECT_LE(0, data_file_fd);
-
const auto SetupPartitionConfig =
[](PartitionConfig* config, const string& path, size_t size) {
config->path = path;
@@ -79,8 +68,8 @@
string zeros(size, '\0');
EXPECT_TRUE(utils::WriteFile(path, zeros.c_str(), zeros.size()));
};
- ScopedTempFile old_part_file;
- ScopedTempFile new_part_file;
+ ScopedTempFile old_part_file("old_part.XXXXXX");
+ ScopedTempFile new_part_file("new_part.XXXXXX");
PartitionConfig old_part(kPartitionNameRoot);
PartitionConfig new_part(kPartitionNameRoot);
SetupPartitionConfig(&old_part, old_part_file.path(), 0);
@@ -93,7 +82,8 @@
vector<AnnotatedOperation> aops;
off_t data_file_size = 0;
- BlobFileWriter blob_file_writer(data_file_fd, &data_file_size);
+ ScopedTempFile data_file("temp_data.XXXXXX", true);
+ BlobFileWriter blob_file_writer(data_file.fd(), &data_file_size);
// Generate the operations using the strategy we selected above.
EXPECT_TRUE(strategy->GenerateOperations(
config, old_part, new_part, &blob_file_writer, &aops));
@@ -102,10 +92,10 @@
uint64_t metadata_size;
EXPECT_TRUE(payload.WritePayload(
- payload_file.path(), temp_file_path, "", &metadata_size));
+ payload_file_.path(), data_file.path(), "", &metadata_size));
}
- ScopedTempFile payload_file;
+ ScopedTempFile payload_file_{"payload_file.XXXXXX"};
};
// Validate the hash of file exists within the output.
@@ -114,28 +104,26 @@
"{"
R"("is_delta":true,)"
R"("metadata_signature":"",)"
- R"("metadata_size":187,)"
- R"("sha256_hex":"Rtrj9v3xXhrAi1741HAojtGxAQEOZ7mDyhzskIF4PJc=",)"
- R"("size":233,)"
- R"("source_version":"123.0.0",)"
- R"("target_version":"456.7.8",)"
+ R"("metadata_size":165,)"
+ R"("sha256_hex":"cV7kfZBH3K0B6QJHxxykDh6b6x0WgVOmc63whPLOy7U=",)"
+ R"("size":211,)"
R"("version":2)"
"}";
string json;
EXPECT_TRUE(
- PayloadProperties(payload_file.path()).GetPropertiesAsJson(&json));
+ PayloadProperties(payload_file_.path()).GetPropertiesAsJson(&json));
EXPECT_EQ(kJsonProperties, json) << "JSON contents:\n" << json;
}
// Validate the hash of file and metadata are within the output.
TEST_F(PayloadPropertiesTest, GetPropertiesAsKeyValueTestHash) {
constexpr char kKeyValueProperties[] =
- "FILE_HASH=Rtrj9v3xXhrAi1741HAojtGxAQEOZ7mDyhzskIF4PJc=\n"
- "FILE_SIZE=233\n"
- "METADATA_HASH=kiXTexy/s2aPttf4+r8KRZWYZ6FYvwhU6rJGcnnI+U0=\n"
- "METADATA_SIZE=187\n";
+ "FILE_HASH=cV7kfZBH3K0B6QJHxxykDh6b6x0WgVOmc63whPLOy7U=\n"
+ "FILE_SIZE=211\n"
+ "METADATA_HASH=aEKYyzJt2E8Gz8fzB+gmekN5mriotZCSq6R+kDfdeV4=\n"
+ "METADATA_SIZE=165\n";
string key_value;
- EXPECT_TRUE(PayloadProperties{payload_file.path()}.GetPropertiesAsKeyValue(
+ EXPECT_TRUE(PayloadProperties{payload_file_.path()}.GetPropertiesAsKeyValue(
&key_value));
EXPECT_EQ(kKeyValueProperties, key_value) << "Key Value contents:\n"
<< key_value;
diff --git a/payload_generator/payload_signer.cc b/payload_generator/payload_signer.cc
index c3264c1..dd87ab7 100644
--- a/payload_generator/payload_signer.cc
+++ b/payload_generator/payload_signer.cc
@@ -321,7 +321,6 @@
signature.data(),
rsa,
RSA_NO_PADDING);
-
if (signature_size < 0) {
LOG(ERROR) << "Signing hash failed: "
<< ERR_error_string(ERR_get_error(), nullptr);
diff --git a/payload_generator/payload_signer_unittest.cc b/payload_generator/payload_signer_unittest.cc
index fe62997..2a0b394 100644
--- a/payload_generator/payload_signer_unittest.cc
+++ b/payload_generator/payload_signer_unittest.cc
@@ -167,7 +167,7 @@
}
TEST_F(PayloadSignerTest, SkipMetadataSignatureTest) {
- test_utils::ScopedTempFile payload_file("payload.XXXXXX");
+ ScopedTempFile payload_file("payload.XXXXXX");
PayloadGenerationConfig config;
config.version.major = kBrilloMajorPayloadVersion;
PayloadFile payload;
@@ -194,7 +194,7 @@
}
TEST_F(PayloadSignerTest, VerifySignedPayloadTest) {
- test_utils::ScopedTempFile payload_file("payload.XXXXXX");
+ ScopedTempFile payload_file("payload.XXXXXX");
PayloadGenerationConfig config;
config.version.major = kBrilloMajorPayloadVersion;
PayloadFile payload;
diff --git a/payload_generator/squashfs_filesystem.cc b/payload_generator/squashfs_filesystem.cc
index 6152d7d..a41e283 100644
--- a/payload_generator/squashfs_filesystem.cc
+++ b/payload_generator/squashfs_filesystem.cc
@@ -72,15 +72,10 @@
}
bool GetFileMapContent(const string& sqfs_path, string* map) {
- // Create a tmp file
- string map_file;
- TEST_AND_RETURN_FALSE(
- utils::MakeTempFile("squashfs_file_map.XXXXXX", &map_file, nullptr));
- ScopedPathUnlinker map_unlinker(map_file);
-
+ ScopedTempFile map_file("squashfs_file_map.XXXXXX");
// Run unsquashfs to get the system file map.
// unsquashfs -m <map-file> <squashfs-file>
- vector<string> cmd = {"unsquashfs", "-m", map_file, sqfs_path};
+ vector<string> cmd = {"unsquashfs", "-m", map_file.path(), sqfs_path};
string stdout, stderr;
int exit_code;
if (!Subprocess::SynchronousExec(cmd, &exit_code, &stdout, &stderr) ||
@@ -89,7 +84,7 @@
<< stdout << " and stderr content: " << stderr;
return false;
}
- TEST_AND_RETURN_FALSE(utils::ReadFile(map_file, map));
+ TEST_AND_RETURN_FALSE(utils::ReadFile(map_file.path(), map));
return true;
}
diff --git a/payload_state.cc b/payload_state.cc
index 4945fe7..1d1583b 100644
--- a/payload_state.cc
+++ b/payload_state.cc
@@ -375,6 +375,7 @@
case ErrorCode::kUnresolvedHostRecovered:
case ErrorCode::kNotEnoughSpace:
case ErrorCode::kDeviceCorrupted:
+ case ErrorCode::kPackageExcludedFromUpdate:
LOG(INFO) << "Not incrementing URL index or failure count for this error";
break;
@@ -463,6 +464,7 @@
}
void PayloadState::IncrementFullPayloadAttemptNumber() {
+ DCHECK(payload_index_ < response_.packages.size());
// Update the payload attempt number for full payloads and the backoff time.
if (response_.packages[payload_index_].is_delta) {
LOG(INFO) << "Not incrementing payload attempt number for delta payloads";
@@ -475,6 +477,7 @@
}
void PayloadState::IncrementUrlIndex() {
+ DCHECK(payload_index_ < candidate_urls_.size());
size_t next_url_index = url_index_ + 1;
size_t max_url_size = candidate_urls_[payload_index_].size();
if (next_url_index < max_url_size) {
@@ -511,6 +514,10 @@
}
void PayloadState::ExcludeCurrentPayload() {
+ if (payload_index_ >= response_.packages.size()) {
+ LOG(INFO) << "Skipping exclusion of the current payload.";
+ return;
+ }
const auto& package = response_.packages[payload_index_];
if (!package.can_exclude) {
LOG(INFO) << "Not excluding as marked non-excludable for package hash="
@@ -613,10 +620,6 @@
return kPayloadTypeForcedFull;
}
-// TODO(zeuthen): Currently we don't report the UpdateEngine.Attempt.*
-// metrics if the attempt ends abnormally, e.g. if the update_engine
-// process crashes or the device is rebooted. See
-// http://crbug.com/357676
void PayloadState::CollectAndReportAttemptMetrics(ErrorCode code) {
int attempt_number = GetPayloadAttemptNumber();
@@ -671,6 +674,7 @@
case metrics::AttemptResult::kAbnormalTermination:
case metrics::AttemptResult::kUpdateCanceled:
case metrics::AttemptResult::kUpdateSucceededNotActive:
+ case metrics::AttemptResult::kUpdateSkipped:
case metrics::AttemptResult::kNumConstants:
case metrics::AttemptResult::kUnset:
break;
@@ -924,10 +928,12 @@
}
bool PayloadState::NextPayload() {
- if (payload_index_ + 1 >= candidate_urls_.size())
+ if (payload_index_ >= candidate_urls_.size())
+ return false;
+ SetPayloadIndex(payload_index_ + 1);
+ if (payload_index_ >= candidate_urls_.size())
return false;
SetUrlIndex(0);
- SetPayloadIndex(payload_index_ + 1);
return true;
}
diff --git a/payload_state.h b/payload_state.h
index 427836b..77197a7 100644
--- a/payload_state.h
+++ b/payload_state.h
@@ -161,6 +161,8 @@
FRIEND_TEST(PayloadStateTest, ExcludeNoopForNonExcludables);
FRIEND_TEST(PayloadStateTest, ExcludeOnlyCanExcludables);
FRIEND_TEST(PayloadStateTest, IncrementFailureExclusionTest);
+ FRIEND_TEST(PayloadStateTest, HaltExclusionPostPayloadExhaustion);
+ FRIEND_TEST(PayloadStateTest, NonInfinitePayloadIndexIncrement);
// Helper called when an attempt has begun, is called by
// UpdateResumed(), UpdateRestarted() and Rollback().
diff --git a/payload_state_unittest.cc b/payload_state_unittest.cc
index c33bda4..2d571c1 100644
--- a/payload_state_unittest.cc
+++ b/payload_state_unittest.cc
@@ -630,7 +630,7 @@
PayloadState payload_state;
FakeSystemState fake_system_state;
OmahaRequestParams params(&fake_system_state);
- params.Init("", "", true); // interactive = True.
+ params.Init("", "", {.interactive = true});
fake_system_state.set_request_params(¶ms);
EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
@@ -653,7 +653,7 @@
PayloadState payload_state;
FakeSystemState fake_system_state;
OmahaRequestParams params(&fake_system_state);
- params.Init("", "", false); // interactive = False.
+ params.Init("", "", {});
fake_system_state.set_request_params(¶ms);
EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
@@ -1019,7 +1019,7 @@
// Mock out the os version and make sure it's excluded correctly.
string rollback_version = "2345.0.0";
OmahaRequestParams params(&fake_system_state);
- params.Init(rollback_version, "", false);
+ params.Init(rollback_version, "", {});
fake_system_state.set_request_params(¶ms);
EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
@@ -1778,4 +1778,49 @@
payload_state.IncrementFailureCount();
}
+TEST(PayloadStateTest, HaltExclusionPostPayloadExhaustion) {
+ PayloadState payload_state;
+ FakeSystemState fake_system_state;
+ StrictMock<MockExcluder> mock_excluder;
+ EXPECT_CALL(*fake_system_state.mock_update_attempter(), GetExcluder())
+ .WillOnce(Return(&mock_excluder));
+ EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
+
+ OmahaResponse response;
+ // Non-critical package.
+ response.packages.push_back(
+ {.payload_urls = {"http://test1a", "http://test2a"},
+ .size = 123456789,
+ .metadata_size = 58123,
+ .metadata_signature = "msign",
+ .hash = "hash",
+ .can_exclude = true});
+ payload_state.SetResponse(response);
+
+ // Exclusion should be called when excluded.
+ EXPECT_CALL(mock_excluder, Exclude(utils::GetExclusionName("http://test1a")))
+ .WillOnce(Return(true));
+ payload_state.ExcludeCurrentPayload();
+
+ // No more paylods to go through.
+ EXPECT_FALSE(payload_state.NextPayload());
+
+ // Exclusion should not be called as all |Payload|s are exhausted.
+ payload_state.ExcludeCurrentPayload();
+}
+
+TEST(PayloadStateTest, NonInfinitePayloadIndexIncrement) {
+ PayloadState payload_state;
+ FakeSystemState fake_system_state;
+ EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
+
+ payload_state.SetResponse({});
+
+ EXPECT_FALSE(payload_state.NextPayload());
+ int payload_index = payload_state.payload_index_;
+
+ EXPECT_FALSE(payload_state.NextPayload());
+ EXPECT_EQ(payload_index, payload_state.payload_index_);
+}
+
} // namespace chromeos_update_engine
diff --git a/real_system_state.cc b/real_system_state.cc
index 74a37f3..924271e 100644
--- a/real_system_state.cc
+++ b/real_system_state.cc
@@ -138,7 +138,7 @@
// will be re-initialized before every request using the actual request
// options. This initialization here pre-loads current channel and version, so
// the DBus service can access it.
- if (!request_params_.Init("", "", false)) {
+ if (!request_params_.Init("", "", {})) {
LOG(WARNING) << "Ignoring OmahaRequestParams initialization error. Some "
"features might not work properly.";
}
diff --git a/requisition_util.cc b/requisition_util.cc
new file mode 100644
index 0000000..5445bce
--- /dev/null
+++ b/requisition_util.cc
@@ -0,0 +1,69 @@
+//
+// Copyright (C) 2020 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/requisition_util.h"
+
+#include <memory>
+#include <vector>
+
+#include <base/files/file_util.h>
+#include <base/json/json_file_value_serializer.h>
+#include <base/logging.h>
+#include <base/strings/string_util.h>
+
+#include "update_engine/common/subprocess.h"
+#include "update_engine/common/utils.h"
+
+using std::string;
+using std::vector;
+
+namespace {
+
+constexpr char kOemRequisitionKey[] = "oem_device_requisition";
+
+} // namespace
+
+namespace chromeos_update_engine {
+
+string ReadDeviceRequisition(const base::FilePath& local_state) {
+ string requisition;
+ bool vpd_retval = utils::GetVpdValue(kOemRequisitionKey, &requisition);
+
+ // Some users manually convert non-CfM hardware at enrollment time, so VPD
+ // value may be missing. So check the Local State JSON as well.
+ if ((requisition.empty() || !vpd_retval) && base::PathExists(local_state)) {
+ int error_code;
+ std::string error_msg;
+ JSONFileValueDeserializer deserializer(local_state);
+ std::unique_ptr<base::Value> root =
+ deserializer.Deserialize(&error_code, &error_msg);
+ if (!root) {
+ if (error_code != 0) {
+ LOG(ERROR) << "Unable to deserialize Local State with exit code: "
+ << error_code << " and error: " << error_msg;
+ }
+ return "";
+ }
+ auto* path = root->FindPath({"enrollment", "device_requisition"});
+ if (!path || !path->is_string()) {
+ return "";
+ }
+ path->GetAsString(&requisition);
+ }
+ return requisition;
+}
+
+} // namespace chromeos_update_engine
diff --git a/requisition_util.h b/requisition_util.h
new file mode 100644
index 0000000..8577ee7
--- /dev/null
+++ b/requisition_util.h
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2020 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_REQUISITION_UTIL_H_
+#define UPDATE_ENGINE_REQUISITION_UTIL_H_
+
+#include <string>
+
+#include <base/files/file_path.h>
+
+namespace chromeos_update_engine {
+
+// Checks the VPD and Local State for the device's requisition and returns it,
+// or an empty string if the device has no requisition.
+std::string ReadDeviceRequisition(const base::FilePath& local_state);
+
+} // namespace chromeos_update_engine
+
+#endif // UPDATE_ENGINE_REQUISITION_UTIL_H_
diff --git a/requisition_util_unittest.cc b/requisition_util_unittest.cc
new file mode 100644
index 0000000..c21c9c7
--- /dev/null
+++ b/requisition_util_unittest.cc
@@ -0,0 +1,94 @@
+//
+// Copyright (C) 2020 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/requisition_util.h"
+
+#include <string>
+
+#include <base/files/file_path.h>
+#include <base/files/file_util.h>
+#include <base/files/scoped_temp_dir.h>
+#include <gtest/gtest.h>
+
+#include "update_engine/common/test_utils.h"
+
+using chromeos_update_engine::test_utils::WriteFileString;
+using std::string;
+
+namespace {
+
+const char kRemoraJSON[] =
+ "{\n"
+ " \"the_list\": [ \"val1\", \"val2\" ],\n"
+ " \"enrollment\": {\n"
+ " \"autostart\": true,\n"
+ " \"can_exit\": false,\n"
+ " \"device_requisition\": \"remora\"\n"
+ " },\n"
+ " \"some_String\": \"1337\",\n"
+ " \"some_int\": 42\n"
+ "}\n";
+
+const char kNoEnrollmentJSON[] =
+ "{\n"
+ " \"the_list\": [ \"val1\", \"val2\" ],\n"
+ " \"enrollment\": {\n"
+ " \"autostart\": true,\n"
+ " \"can_exit\": false,\n"
+ " \"device_requisition\": \"\"\n"
+ " },\n"
+ " \"some_String\": \"1337\",\n"
+ " \"some_int\": 42\n"
+ "}\n";
+} // namespace
+
+namespace chromeos_update_engine {
+
+class RequisitionUtilTest : public ::testing::Test {
+ protected:
+ void SetUp() override { ASSERT_TRUE(root_dir_.CreateUniqueTempDir()); }
+
+ void WriteJsonToFile(const string& json) {
+ path_ =
+ base::FilePath(root_dir_.GetPath().value() + "/chronos/Local State");
+ ASSERT_TRUE(base::CreateDirectory(path_.DirName()));
+ ASSERT_TRUE(WriteFileString(path_.value(), json));
+ }
+
+ base::ScopedTempDir root_dir_;
+ base::FilePath path_;
+};
+
+TEST_F(RequisitionUtilTest, BadJsonReturnsEmpty) {
+ WriteJsonToFile("this isn't JSON");
+ EXPECT_EQ("", ReadDeviceRequisition(path_));
+}
+
+TEST_F(RequisitionUtilTest, NoFileReturnsEmpty) {
+ EXPECT_EQ("", ReadDeviceRequisition(path_));
+}
+
+TEST_F(RequisitionUtilTest, EnrollmentRequisition) {
+ WriteJsonToFile(kRemoraJSON);
+ EXPECT_EQ("remora", ReadDeviceRequisition(path_));
+}
+
+TEST_F(RequisitionUtilTest, BlankEnrollment) {
+ WriteJsonToFile(kNoEnrollmentJSON);
+ EXPECT_EQ("", ReadDeviceRequisition(path_));
+}
+
+} // namespace chromeos_update_engine
diff --git a/sample_images/generate_payloads.sh b/sample_images/generate_payloads.sh
new file mode 100755
index 0000000..ee64229
--- /dev/null
+++ b/sample_images/generate_payloads.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+#
+# Copyright (C) 2020 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.
+#
+
+# This script generates some sample payloads from the images in
+# sample_images.tar.bz2. and packages them in the sample_payloads.tar.xz file.
+# The payloads are then used in paycheck_unittests.py. The file names
+# must match the ones used in update_payload ebuild and paycheck_unittests.py.
+
+set -e
+
+TEMP_IMG_DIR=./sample_images
+OLD_KERNEL="${TEMP_IMG_DIR}/disk_ext2_4k_empty.img"
+OLD_ROOT="${TEMP_IMG_DIR}/disk_sqfs_empty.img"
+NEW_KERNEL="${TEMP_IMG_DIR}/disk_ext2_4k.img"
+NEW_ROOT="${TEMP_IMG_DIR}/disk_sqfs_default.img"
+
+
+mkdir -p "${TEMP_IMG_DIR}"
+tar -xvf sample_images.tar.bz2 -C "${TEMP_IMG_DIR}"
+
+echo "Generating full payload"
+delta_generator --out_file=full_payload.bin \
+ --partition_names=kernel:root \
+ --new_partitions="${NEW_KERNEL}":"${NEW_ROOT}"
+
+echo "Generating delta payload"
+delta_generator --out_file=delta_payload.bin \
+ --partition_names=kernel:root \
+ --new_partitions="${NEW_KERNEL}":"${NEW_ROOT}" \
+ --old_partitions="${OLD_KERNEL}":"${OLD_ROOT}" --minor_version=6
+
+echo "Creating sample_payloads.tar"
+tar -cJf sample_payloads.tar.xz {delta,full}_payload.bin
+
+rm -rf "${TEMP_IMG_DIR}" {delta,full}_payload.bin
+
+echo "Done"
diff --git a/sample_images/sample_payloads.tar.xz b/sample_images/sample_payloads.tar.xz
new file mode 100644
index 0000000..d0bf6d9
--- /dev/null
+++ b/sample_images/sample_payloads.tar.xz
Binary files differ
diff --git a/scripts/paycheck.py b/scripts/paycheck.py
index f4ccca2..cb1713f 100755
--- a/scripts/paycheck.py
+++ b/scripts/paycheck.py
@@ -27,6 +27,7 @@
import sys
import tempfile
+# pylint: disable=redefined-builtin
from six.moves import zip
from update_payload import error
@@ -92,9 +93,6 @@
check_args.add_argument('-c', '--check', action='store_true', default=False,
help=('force payload integrity check (e.g. before '
'applying)'))
- check_args.add_argument('-D', '--describe', action='store_true',
- default=False,
- help='Print a friendly description of the payload.')
check_args.add_argument('-r', '--report', metavar='FILE',
help="dump payload report (`-' for stdout)")
check_args.add_argument('-t', '--type', dest='assert_type',
@@ -209,9 +207,6 @@
# Initialize payload.
payload.Init()
- if args.describe:
- payload.Describe()
-
# Perform payload integrity checks.
if args.check:
report_file = None
diff --git a/scripts/paycheck_unittest.py b/scripts/paycheck_unittest.py
new file mode 100755
index 0000000..a90d269
--- /dev/null
+++ b/scripts/paycheck_unittest.py
@@ -0,0 +1,105 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2020 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.
+#
+
+"""Unit testing paycheck.py."""
+
+# This test requires new (Y) and old (X) images, as well as a full payload
+# from image Y and a delta payload from Y to X for each partition.
+# Payloads are from sample_images/generate_payloads.
+#
+# The test performs the following:
+#
+# - It statically applies the full and delta payloads.
+#
+# - It applies full_payload to yield a new kernel (kern.part) and rootfs
+# (root.part) and compares them to the new image partitions.
+#
+# - It applies delta_payload to the old image to yield a new kernel and rootfs
+# and compares them to the new image partitions.
+#
+# Previously test_paycheck.sh. Run with update_payload ebuild.
+
+# Disable check for function names to avoid errors based on old code
+# pylint: disable=invalid-name
+
+import filecmp
+import os
+import subprocess
+import unittest
+
+
+class PaycheckTest(unittest.TestCase):
+ """Test paycheck functions."""
+
+ def setUp(self):
+ self.tmpdir = os.getenv('T')
+
+ self._full_payload = os.path.join(self.tmpdir, 'full_payload.bin')
+ self._delta_payload = os.path.join(self.tmpdir, 'delta_payload.bin')
+
+ self._new_kernel = os.path.join(self.tmpdir, 'disk_ext2_4k.img')
+ self._new_root = os.path.join(self.tmpdir, 'disk_sqfs_default.img')
+ self._old_kernel = os.path.join(self.tmpdir,
+ 'disk_ext2_4k_empty.img')
+ self._old_root = os.path.join(self.tmpdir, 'disk_sqfs_empty.img')
+
+ # Temp output files.
+ self._kernel_part = os.path.join(self.tmpdir, 'kern.part')
+ self._root_part = os.path.join(self.tmpdir, 'root.part')
+
+ def checkPayload(self, type_arg, payload):
+ """Checks Payload."""
+ self.assertEqual(0, subprocess.check_call(['./paycheck.py', '-t',
+ type_arg, payload]))
+
+ def testFullPayload(self):
+ """Checks the full payload statically."""
+ self.checkPayload('full', self._full_payload)
+
+ def testDeltaPayload(self):
+ """Checks the delta payload statically."""
+ self.checkPayload('delta', self._delta_payload)
+
+ def testApplyFullPayload(self):
+ """Applies full payloads and compares results to new sample images."""
+ self.assertEqual(0, subprocess.check_call(['./paycheck.py',
+ self._full_payload,
+ '--part_names', 'kernel', 'root',
+ '--out_dst_part_paths',
+ self._kernel_part,
+ self._root_part]))
+
+ # Check if generated full image is equal to sample image.
+ self.assertTrue(filecmp.cmp(self._kernel_part, self._new_kernel))
+ self.assertTrue(filecmp.cmp(self._root_part, self._new_root))
+
+ def testApplyDeltaPayload(self):
+ """Applies delta to old image and checks against new sample images."""
+ self.assertEqual(0, subprocess.check_call(['./paycheck.py',
+ self._delta_payload,
+ '--part_names', 'kernel', 'root',
+ '--src_part_paths',
+ self._old_kernel, self._old_root,
+ '--out_dst_part_paths',
+ self._kernel_part,
+ self._root_part]))
+
+ self.assertTrue(filecmp.cmp(self._kernel_part, self._new_kernel))
+ self.assertTrue(filecmp.cmp(self._root_part, self._new_root))
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/scripts/run_unittests b/scripts/run_unittests
index 0d301ba..db5ed73 100755
--- a/scripts/run_unittests
+++ b/scripts/run_unittests
@@ -26,5 +26,6 @@
done
./payload_info_unittest.py
+./paycheck_unittest.py
exit 0
diff --git a/scripts/test_paycheck.sh b/scripts/test_paycheck.sh
deleted file mode 100755
index 239b984..0000000
--- a/scripts/test_paycheck.sh
+++ /dev/null
@@ -1,169 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2013 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.
-#
-
-# A test script for paycheck.py and the update_payload.py library.
-#
-# This script requires three payload files, along with a metadata signature for
-# each, and a public key for verifying signatures. Payload include:
-#
-# - A full payload for release X (old_full_payload)
-#
-# - A full payload for release Y (new_full_payload), where Y > X
-#
-# - A delta payload from X to Y (delta_payload)
-#
-# The test performs the following:
-#
-# - It verifies each payload against its metadata signature, also asserting the
-# payload type. Another artifact is a human-readable payload report, which
-# is output to stdout to be inspected by the user.
-#
-# - It applies old_full_payload to yield old kernel (old_kern.part) and rootfs
-# (old_root.part) partitions.
-#
-# - It applies delta_payload to old_{kern,root}.part to yield new kernel
-# (new_delta_kern.part) and rootfs (new_delta_root.part) partitions.
-#
-# - It applies new_full_payload to yield reference new kernel
-# (new_full_kern.part) and rootfs (new_full_root.part) partitions.
-#
-# - It compares new_{delta,full}_kern.part and new_{delta,full}_root.part to
-# ensure that they are binary identical.
-#
-# If all steps have completed successfully we know with high certainty that
-# paycheck.py (and hence update_payload.py) correctly parses both full and delta
-# payloads, and applies them to yield the expected result. Finally, each
-# paycheck.py execution is timed.
-
-
-# Stop on errors, unset variables.
-set -e
-set -u
-
-# Temporary image files.
-OLD_KERN_PART=old_kern.part
-OLD_ROOT_PART=old_root.part
-NEW_DELTA_KERN_PART=new_delta_kern.part
-NEW_DELTA_ROOT_PART=new_delta_root.part
-NEW_FULL_KERN_PART=new_full_kern.part
-NEW_FULL_ROOT_PART=new_full_root.part
-CROS_PARTS="kernel root"
-
-
-log() {
- echo "$@" >&2
-}
-
-die() {
- log "$@"
- exit 1
-}
-
-usage_and_exit() {
- cat >&2 <<EOF
-Usage: ${0##*/} old_full_payload delta_payload new_full_payload
-EOF
- exit
-}
-
-check_payload() {
- payload_file=$1
- payload_type=$2
-
- time ${paycheck} -t ${payload_type} ${payload_file}
-}
-
-apply_full_payload() {
- payload_file=$1
- out_dst_kern_part="$2/$3"
- out_dst_root_part="$2/$4"
-
- time ${paycheck} ${payload_file} \
- --part_names ${CROS_PARTS} \
- --out_dst_part_paths ${out_dst_kern_part} ${out_dst_root_part}
-}
-
-apply_delta_payload() {
- payload_file=$1
- out_dst_kern_part="$2/$3"
- out_dst_root_part="$2/$4"
- dst_kern_part="$2/$5"
- dst_root_part="$2/$6"
- src_kern_part="$2/$7"
- src_root_part="$2/$8"
-
- time ${paycheck} ${payload_file} \
- --part_names ${CROS_PARTS} \
- --out_dst_part_paths ${out_dst_kern_part} ${out_dst_root_part} \
- --dst_part_paths ${dst_kern_part} ${dst_root_part} \
- --src_part_paths ${src_kern_part} ${src_root_part}
-}
-
-main() {
- # Read command-line arguments.
- if [ $# == 1 ] && [ "$1" == "-h" ]; then
- usage_and_exit
- elif [ $# != 3 ]; then
- die "Error: unexpected number of arguments"
- fi
- old_full_payload="$1"
- delta_payload="$2"
- new_full_payload="$3"
-
- # Find paycheck.py
- paycheck=${0%/*}/paycheck.py
- if [ -z "${paycheck}" ] || [ ! -x ${paycheck} ]; then
- die "cannot find ${paycheck} or file is not executable"
- fi
-
- # Check the payloads statically.
- log "Checking payloads..."
- check_payload "${old_full_payload}" full
- check_payload "${new_full_payload}" full
- check_payload "${delta_payload}" delta
- log "Done"
-
- # Apply full/delta payloads and verify results are identical.
- tmpdir="$(mktemp -d --tmpdir test_paycheck.XXXXXXXX)"
- log "Initiating application of payloads at $tmpdir"
-
- log "Applying old full payload..."
- apply_full_payload "${old_full_payload}" "${tmpdir}" "${OLD_KERN_PART}" \
- "${OLD_ROOT_PART}"
- log "Done"
-
- log "Applying new full payload..."
- apply_full_payload "${new_full_payload}" "${tmpdir}" "${NEW_FULL_KERN_PART}" \
- "${NEW_FULL_ROOT_PART}"
- log "Done"
-
- log "Applying delta payload to old partitions..."
- apply_delta_payload "${delta_payload}" "${tmpdir}" "${NEW_DELTA_KERN_PART}" \
- "${NEW_DELTA_ROOT_PART}" "${NEW_FULL_KERN_PART}" \
- "${NEW_FULL_ROOT_PART}" "${OLD_KERN_PART}" "${OLD_ROOT_PART}"
- log "Done"
-
- log "Comparing results of delta and new full updates..."
- diff "${tmpdir}/${NEW_FULL_KERN_PART}" "${tmpdir}/${NEW_DELTA_KERN_PART}"
- diff "${tmpdir}/${NEW_FULL_ROOT_PART}" "${tmpdir}/${NEW_DELTA_ROOT_PART}"
- log "Done"
-
- log "Cleaning up"
- rm -fr "${tmpdir}"
-}
-
-main "$@"
diff --git a/scripts/update_payload/checker.py b/scripts/update_payload/checker.py
index 4c65516..56a9370 100644
--- a/scripts/update_payload/checker.py
+++ b/scripts/update_payload/checker.py
@@ -35,6 +35,7 @@
import os
import subprocess
+# pylint: disable=redefined-builtin
from six.moves import range
from update_payload import common
@@ -71,6 +72,7 @@
4: (_TYPE_DELTA,),
5: (_TYPE_DELTA,),
6: (_TYPE_DELTA,),
+ 7: (_TYPE_DELTA,),
}
@@ -1148,17 +1150,13 @@
sig_report = report.AddSubReport(sig_name)
# Check: Signature contains mandatory fields.
- self._CheckMandatoryField(sig, 'version', sig_report, sig_name)
self._CheckMandatoryField(sig, 'data', None, sig_name)
sig_report.AddField('data len', len(sig.data))
# Check: Signatures pertains to actual payload hash.
- if sig.version == 1:
+ if sig.data:
self._CheckSha256Signature(sig.data, pubkey_file_name,
payload_hasher.digest(), sig_name)
- else:
- raise error.PayloadError('Unknown signature version (%d).' %
- sig.version)
def Run(self, pubkey_file_name=None, metadata_sig_file=None, metadata_size=0,
part_sizes=None, report_out_file=None):
diff --git a/scripts/update_payload/payload.py b/scripts/update_payload/payload.py
index 78b8e2c..fe3a450 100644
--- a/scripts/update_payload/payload.py
+++ b/scripts/update_payload/payload.py
@@ -232,31 +232,6 @@
self.is_init = True
- def Describe(self):
- """Emits the payload embedded description data to standard output."""
- def _DescribeImageInfo(description, image_info):
- """Display info about the image."""
- def _DisplayIndentedValue(name, value):
- print(' {:<14} {}'.format(name+':', value))
-
- print('%s:' % description)
- _DisplayIndentedValue('Channel', image_info.channel)
- _DisplayIndentedValue('Board', image_info.board)
- _DisplayIndentedValue('Version', image_info.version)
- _DisplayIndentedValue('Key', image_info.key)
-
- if image_info.build_channel != image_info.channel:
- _DisplayIndentedValue('Build channel', image_info.build_channel)
-
- if image_info.build_version != image_info.version:
- _DisplayIndentedValue('Build version', image_info.build_version)
-
- if self.manifest.HasField('old_image_info'):
- _DescribeImageInfo('Old Image', self.manifest.old_image_info)
-
- if self.manifest.HasField('new_image_info'):
- _DescribeImageInfo('New Image', self.manifest.new_image_info)
-
def _AssertInit(self):
"""Raises an exception if the object was not initialized."""
if not self.is_init:
diff --git a/test_http_server.cc b/test_http_server.cc
index 1c3a2e0..a2f1e05 100644
--- a/test_http_server.cc
+++ b/test_http_server.cc
@@ -190,7 +190,7 @@
string("HTTP/1.1 ") + Itoa(return_code) + " " +
GetHttpResponseDescription(return_code) +
EOL "Content-Type: application/octet-stream" EOL
- "Connection: close" EOL);
+ "Connection: close" EOL);
if (ret < 0)
return -1;
written += ret;
@@ -409,7 +409,6 @@
return;
WriteString(fd, "Connection: close" EOL);
WriteString(fd, "Location: " + url + EOL);
-
}
// Generate a page not found error response with actual text payload. Return
diff --git a/update_attempter.cc b/update_attempter.cc
index c4fe348..38b0f82 100644
--- a/update_attempter.cc
+++ b/update_attempter.cc
@@ -244,15 +244,7 @@
system_state_->metrics_reporter()->ReportDailyMetrics(age);
}
-void UpdateAttempter::Update(const string& app_version,
- const string& omaha_url,
- const string& target_channel,
- const string& target_version_prefix,
- bool rollback_allowed,
- bool rollback_data_save_requested,
- int rollback_allowed_milestones,
- bool obey_proxies,
- bool interactive) {
+void UpdateAttempter::Update(const UpdateCheckParams& params) {
// This is normally called frequently enough so it's appropriate to use as a
// hook for reporting daily metrics.
// TODO(garnold) This should be hooked to a separate (reliable and consistent)
@@ -281,19 +273,11 @@
return;
}
- if (!CalculateUpdateParams(app_version,
- omaha_url,
- target_channel,
- target_version_prefix,
- rollback_allowed,
- rollback_data_save_requested,
- rollback_allowed_milestones,
- obey_proxies,
- interactive)) {
+ if (!CalculateUpdateParams(params)) {
return;
}
- BuildUpdateActions(interactive);
+ BuildUpdateActions(params.interactive);
SetStatusAndNotify(UpdateStatus::CHECKING_FOR_UPDATE);
@@ -356,15 +340,7 @@
payload_state->SetUsingP2PForSharing(use_p2p_for_sharing);
}
-bool UpdateAttempter::CalculateUpdateParams(const string& app_version,
- const string& omaha_url,
- const string& target_channel,
- const string& target_version_prefix,
- bool rollback_allowed,
- bool rollback_data_save_requested,
- int rollback_allowed_milestones,
- bool obey_proxies,
- bool interactive) {
+bool UpdateAttempter::CalculateUpdateParams(const UpdateCheckParams& params) {
http_response_code_ = 0;
PayloadStateInterface* const payload_state = system_state_->payload_state();
@@ -375,27 +351,13 @@
// policy is available again.
UpdateRollbackHappened();
- // Update the target version prefix.
- omaha_request_params_->set_target_version_prefix(target_version_prefix);
-
- // Set whether rollback is allowed.
- omaha_request_params_->set_rollback_allowed(rollback_allowed);
-
- // Set whether saving data over rollback is requested.
- omaha_request_params_->set_rollback_data_save_requested(
- rollback_data_save_requested);
-
- CalculateStagingParams(interactive);
+ CalculateStagingParams(params.interactive);
// If staging_wait_time_ wasn't set, staging is off, use scattering instead.
if (staging_wait_time_.InSeconds() == 0) {
- CalculateScatteringParams(interactive);
+ CalculateScatteringParams(params.interactive);
}
- // Set how many milestones of rollback are allowed.
- omaha_request_params_->set_rollback_allowed_milestones(
- rollback_allowed_milestones);
-
- CalculateP2PParams(interactive);
+ CalculateP2PParams(params.interactive);
if (payload_state->GetUsingP2PForDownloading() ||
payload_state->GetUsingP2PForSharing()) {
// OK, p2p is to be used - start it and perform housekeeping.
@@ -408,32 +370,12 @@
}
}
- if (!omaha_request_params_->Init(app_version, omaha_url, interactive)) {
+ if (!omaha_request_params_->Init(
+ forced_app_version_, forced_omaha_url_, params)) {
LOG(ERROR) << "Unable to initialize Omaha request params.";
return false;
}
- // Set the target channel, if one was provided.
- if (target_channel.empty()) {
- LOG(INFO) << "No target channel mandated by policy.";
- } else {
- LOG(INFO) << "Setting target channel as mandated: " << target_channel;
- // Pass in false for powerwash_allowed until we add it to the policy
- // protobuf.
- string error_message;
- if (!omaha_request_params_->SetTargetChannel(
- target_channel, false, &error_message)) {
- LOG(ERROR) << "Setting the channel failed: " << error_message;
- }
-
- // Since this is the beginning of a new attempt, update the download
- // channel. The download channel won't be updated until the next attempt,
- // even if target channel changes meanwhile, so that how we'll know if we
- // should cancel the current download attempt if there's such a change in
- // target channel.
- omaha_request_params_->UpdateDownloadChannel();
- }
-
// The function |CalculateDlcParams| makes use of the function |GetAppId| from
// |OmahaRequestParams|, so to ensure that the return from |GetAppId|
// doesn't change, no changes to the values |download_channel_|,
@@ -441,8 +383,6 @@
// |omaha_request_params_| shall be made below this line.
CalculateDlcParams();
- omaha_request_params_->set_is_install(is_install_);
-
// Set Quick Fix Build token if policy is set and the device is enterprise
// enrolled.
string token;
@@ -473,7 +413,7 @@
<< payload_state->GetUsingP2PForSharing();
obeying_proxies_ = true;
- if (obey_proxies || proxy_manual_checks_ == 0) {
+ if (proxy_manual_checks_ == 0) {
LOG(INFO) << "forced to obey proxies";
// If forced to obey proxies, every 20th request will not use proxies
proxy_manual_checks_++;
@@ -760,6 +700,7 @@
dlc_apps_params[omaha_request_params_->GetDlcAppId(dlc_id)] = dlc_params;
}
omaha_request_params_->set_dlc_apps_params(dlc_apps_params);
+ omaha_request_params_->set_is_install(is_install_);
}
void UpdateAttempter::BuildUpdateActions(bool interactive) {
@@ -874,7 +815,7 @@
processor_->set_delegate(this);
// Initialize the default request params.
- if (!omaha_request_params_->Init("", "", true)) {
+ if (!omaha_request_params_->Init("", "", {.interactive = true})) {
LOG(ERROR) << "Unable to initialize Omaha request params.";
return false;
}
@@ -1100,15 +1041,7 @@
LOG(INFO) << "Update attempt flags in use = 0x" << std::hex
<< current_update_attempt_flags_;
- Update(forced_app_version_,
- forced_omaha_url_,
- params.target_channel,
- params.target_version_prefix,
- params.rollback_allowed,
- params.rollback_data_save_requested,
- params.rollback_allowed_milestones,
- /*obey_proxies=*/false,
- params.interactive);
+ Update(params);
// Always clear the forced app_version and omaha_url after an update attempt
// so the next update uses the defaults.
forced_app_version_.clear();
diff --git a/update_attempter.h b/update_attempter.h
index dd958f5..3a1bef4 100644
--- a/update_attempter.h
+++ b/update_attempter.h
@@ -76,21 +76,8 @@
virtual bool ScheduleUpdates();
// Checks for update and, if a newer version is available, attempts to update
- // the system. Non-empty |in_app_version| or |in_update_url| prevents
- // automatic detection of the parameter. |target_channel| denotes a
- // policy-mandated channel we are updating to, if not empty. If |obey_proxies|
- // is true, the update will likely respect Chrome's proxy setting. For
- // security reasons, we may still not honor them. |interactive| should be true
- // if this was called from the user (ie dbus).
- virtual void Update(const std::string& app_version,
- const std::string& omaha_url,
- const std::string& target_channel,
- const std::string& target_version_prefix,
- bool rollback_allowed,
- bool rollback_data_save_requested,
- int rollback_allowed_milestones,
- bool obey_proxies,
- bool interactive);
+ // the system.
+ virtual void Update(const chromeos_update_manager::UpdateCheckParams& params);
// ActionProcessorDelegate methods:
void ProcessingDone(const ActionProcessor* processor,
@@ -283,6 +270,8 @@
FRIEND_TEST(UpdateAttempterTest, RollbackAfterInstall);
FRIEND_TEST(UpdateAttempterTest, RollbackAllowed);
FRIEND_TEST(UpdateAttempterTest, RollbackAllowedSetAndReset);
+ FRIEND_TEST(UpdateAttempterTest, ChannelDowngradeNoRollback);
+ FRIEND_TEST(UpdateAttempterTest, ChannelDowngradeRollback);
FRIEND_TEST(UpdateAttempterTest, RollbackMetricsNotRollbackFailure);
FRIEND_TEST(UpdateAttempterTest, RollbackMetricsNotRollbackSuccess);
FRIEND_TEST(UpdateAttempterTest, RollbackMetricsRollbackFailure);
@@ -293,6 +282,7 @@
FRIEND_TEST(UpdateAttempterTest, SessionIdTestOnOmahaRequestActions);
FRIEND_TEST(UpdateAttempterTest, SetRollbackHappenedNotRollback);
FRIEND_TEST(UpdateAttempterTest, SetRollbackHappenedRollback);
+ FRIEND_TEST(UpdateAttempterTest, TargetChannelHintSetAndReset);
FRIEND_TEST(UpdateAttempterTest, TargetVersionPrefixSetAndReset);
FRIEND_TEST(UpdateAttempterTest, UpdateAfterInstall);
FRIEND_TEST(UpdateAttempterTest, UpdateAttemptFlagsCachedAtUpdateStart);
@@ -366,15 +356,8 @@
// Helper method of Update() to calculate the update-related parameters
// from various sources and set the appropriate state. Please refer to
// Update() method for the meaning of the parameters.
- bool CalculateUpdateParams(const std::string& app_version,
- const std::string& omaha_url,
- const std::string& target_channel,
- const std::string& target_version_prefix,
- bool rollback_allowed,
- bool rollback_data_save_requested,
- int rollback_allowed_milestones,
- bool obey_proxies,
- bool interactive);
+ bool CalculateUpdateParams(
+ const chromeos_update_manager::UpdateCheckParams& params);
// Calculates all the scattering related parameters (such as waiting period,
// which type of scattering is enabled, etc.) and also updates/deletes
diff --git a/update_attempter_unittest.cc b/update_attempter_unittest.cc
index 305dbdb..767bb82 100644
--- a/update_attempter_unittest.cc
+++ b/update_attempter_unittest.cc
@@ -25,7 +25,8 @@
#include <unordered_set>
#include <base/files/file_util.h>
-#include <base/message_loop/message_loop.h>
+#include <base/files/scoped_temp_dir.h>
+#include <base/task/single_thread_task_executor.h>
#include <brillo/message_loops/base_message_loop.h>
#include <brillo/message_loops/message_loop.h>
#include <brillo/message_loops/message_loop_utils.h>
@@ -171,26 +172,10 @@
explicit UpdateAttempterUnderTest(SystemState* system_state)
: UpdateAttempter(system_state, nullptr) {}
- void Update(const std::string& app_version,
- const std::string& omaha_url,
- const std::string& target_channel,
- const std::string& target_version_prefix,
- bool rollback_allowed,
- bool rollback_data_save_requested,
- int rollback_allowed_milestones,
- bool obey_proxies,
- bool interactive) override {
+ void Update(const UpdateCheckParams& params) override {
update_called_ = true;
if (do_update_) {
- UpdateAttempter::Update(app_version,
- omaha_url,
- target_channel,
- target_version_prefix,
- rollback_allowed,
- rollback_data_save_requested,
- rollback_allowed_milestones,
- obey_proxies,
- interactive);
+ UpdateAttempter::Update(params);
return;
}
LOG(INFO) << "[TEST] Update() disabled.";
@@ -332,8 +317,8 @@
// |ProcessingDone()| related member functions.
void TestProcessingDone();
- base::MessageLoopForIO base_loop_;
- brillo::BaseMessageLoop loop_{&base_loop_};
+ base::SingleThreadTaskExecutor base_loop_{base::MessagePumpType::IO};
+ brillo::BaseMessageLoop loop_{base_loop_.task_runner()};
FakeSystemState fake_system_state_;
UpdateAttempterUnderTest attempter_{&fake_system_state_};
@@ -425,7 +410,7 @@
void UpdateAttempterTest::SessionIdTestChange() {
EXPECT_NE(UpdateStatus::UPDATED_NEED_REBOOT, attempter_.status());
const auto old_session_id = attempter_.session_id_;
- attempter_.Update("", "", "", "", false, false, 0, false, false);
+ attempter_.Update({});
EXPECT_NE(old_session_id, attempter_.session_id_);
ScheduleQuitMainLoop();
}
@@ -796,7 +781,7 @@
EXPECT_CALL(*processor_, StartProcessing());
}
- attempter_.Update("", "", "", "", false, false, 0, false, false);
+ attempter_.Update({});
loop_.PostTask(FROM_HERE,
base::Bind(&UpdateAttempterTest::UpdateTestVerify,
base::Unretained(this)));
@@ -996,7 +981,7 @@
fake_system_state_.set_p2p_manager(&mock_p2p_manager);
mock_p2p_manager.fake().SetP2PEnabled(false);
EXPECT_CALL(mock_p2p_manager, PerformHousekeeping()).Times(0);
- attempter_.Update("", "", "", "", false, false, 0, false, false);
+ attempter_.Update({});
EXPECT_FALSE(actual_using_p2p_for_downloading_);
EXPECT_FALSE(actual_using_p2p_for_sharing());
ScheduleQuitMainLoop();
@@ -1018,7 +1003,7 @@
mock_p2p_manager.fake().SetEnsureP2PRunningResult(false);
mock_p2p_manager.fake().SetPerformHousekeepingResult(false);
EXPECT_CALL(mock_p2p_manager, PerformHousekeeping()).Times(0);
- attempter_.Update("", "", "", "", false, false, 0, false, false);
+ attempter_.Update({});
EXPECT_FALSE(actual_using_p2p_for_downloading());
EXPECT_FALSE(actual_using_p2p_for_sharing());
ScheduleQuitMainLoop();
@@ -1041,7 +1026,7 @@
mock_p2p_manager.fake().SetEnsureP2PRunningResult(true);
mock_p2p_manager.fake().SetPerformHousekeepingResult(false);
EXPECT_CALL(mock_p2p_manager, PerformHousekeeping());
- attempter_.Update("", "", "", "", false, false, 0, false, false);
+ attempter_.Update({});
EXPECT_FALSE(actual_using_p2p_for_downloading());
EXPECT_FALSE(actual_using_p2p_for_sharing());
ScheduleQuitMainLoop();
@@ -1063,7 +1048,7 @@
mock_p2p_manager.fake().SetEnsureP2PRunningResult(true);
mock_p2p_manager.fake().SetPerformHousekeepingResult(true);
EXPECT_CALL(mock_p2p_manager, PerformHousekeeping());
- attempter_.Update("", "", "", "", false, false, 0, false, false);
+ attempter_.Update({});
EXPECT_TRUE(actual_using_p2p_for_downloading());
EXPECT_TRUE(actual_using_p2p_for_sharing());
ScheduleQuitMainLoop();
@@ -1086,15 +1071,7 @@
mock_p2p_manager.fake().SetEnsureP2PRunningResult(true);
mock_p2p_manager.fake().SetPerformHousekeepingResult(true);
EXPECT_CALL(mock_p2p_manager, PerformHousekeeping());
- attempter_.Update("",
- "",
- "",
- "",
- false,
- false,
- /*rollback_allowed_milestones=*/0,
- false,
- /*interactive=*/true);
+ attempter_.Update({.interactive = true});
EXPECT_FALSE(actual_using_p2p_for_downloading());
EXPECT_TRUE(actual_using_p2p_for_sharing());
ScheduleQuitMainLoop();
@@ -1124,7 +1101,7 @@
attempter_.policy_provider_.reset(
new policy::PolicyProvider(std::move(device_policy)));
- attempter_.Update("", "", "", "", false, false, 0, false, false);
+ attempter_.Update({});
EXPECT_EQ(scatter_factor_in_seconds, attempter_.scatter_factor_.InSeconds());
ScheduleQuitMainLoop();
@@ -1162,7 +1139,7 @@
attempter_.policy_provider_.reset(
new policy::PolicyProvider(std::move(device_policy)));
- attempter_.Update("", "", "", "", false, false, 0, false, false);
+ attempter_.Update({});
EXPECT_EQ(scatter_factor_in_seconds, attempter_.scatter_factor_.InSeconds());
// Make sure the file still exists.
@@ -1178,7 +1155,7 @@
// However, if the count is already 0, it's not decremented. Test that.
initial_value = 0;
EXPECT_TRUE(fake_prefs.SetInt64(kPrefsUpdateCheckCount, initial_value));
- attempter_.Update("", "", "", "", false, false, 0, false, false);
+ attempter_.Update({});
EXPECT_TRUE(fake_prefs.Exists(kPrefsUpdateCheckCount));
EXPECT_TRUE(fake_prefs.GetInt64(kPrefsUpdateCheckCount, &new_value));
EXPECT_EQ(initial_value, new_value);
@@ -1225,15 +1202,7 @@
new policy::PolicyProvider(std::move(device_policy)));
// Trigger an interactive check so we can test that scattering is disabled.
- attempter_.Update("",
- "",
- "",
- "",
- false,
- false,
- /*rollback_allowed_milestones=*/0,
- false,
- /*interactive=*/true);
+ attempter_.Update({.interactive = true});
EXPECT_EQ(scatter_factor_in_seconds, attempter_.scatter_factor_.InSeconds());
// Make sure scattering is disabled for manual (i.e. user initiated) update
@@ -1285,7 +1254,7 @@
FakePrefs fake_prefs;
SetUpStagingTest(kValidStagingSchedule, &fake_prefs);
- attempter_.Update("", "", "", "", false, false, 0, false, false);
+ attempter_.Update({});
// Check that prefs have the correct values.
int64_t update_count;
EXPECT_TRUE(fake_prefs.GetInt64(kPrefsUpdateCheckCount, &update_count));
@@ -1342,8 +1311,7 @@
FakePrefs fake_prefs;
SetUpStagingTest(kValidStagingSchedule, &fake_prefs);
- attempter_.Update(
- "", "", "", "", false, false, 0, false, /* interactive = */ true);
+ attempter_.Update({.interactive = true});
CheckStagingOff();
ScheduleQuitMainLoop();
@@ -1363,8 +1331,7 @@
FakePrefs fake_prefs;
SetUpStagingTest(kValidStagingSchedule, &fake_prefs);
- attempter_.Update(
- "", "", "", "", false, false, 0, false, /* interactive = */ true);
+ attempter_.Update({.interactive = true});
CheckStagingOff();
ScheduleQuitMainLoop();
@@ -1692,45 +1659,64 @@
}
TEST_F(UpdateAttempterTest, TargetVersionPrefixSetAndReset) {
- attempter_.CalculateUpdateParams(
- "", "", "", "1234", false, false, 4, false, false);
+ UpdateCheckParams params;
+ attempter_.CalculateUpdateParams({.target_version_prefix = "1234"});
EXPECT_EQ("1234",
fake_system_state_.request_params()->target_version_prefix());
- attempter_.CalculateUpdateParams(
- "", "", "", "", false, 4, false, false, false);
+ attempter_.CalculateUpdateParams({});
EXPECT_TRUE(
fake_system_state_.request_params()->target_version_prefix().empty());
}
+TEST_F(UpdateAttempterTest, TargetChannelHintSetAndReset) {
+ attempter_.CalculateUpdateParams({.lts_tag = "hint"});
+ EXPECT_EQ("hint", fake_system_state_.request_params()->lts_tag());
+
+ attempter_.CalculateUpdateParams({});
+ EXPECT_TRUE(fake_system_state_.request_params()->lts_tag().empty());
+}
+
TEST_F(UpdateAttempterTest, RollbackAllowedSetAndReset) {
- attempter_.CalculateUpdateParams("",
- "",
- "",
- "1234",
- /*rollback_allowed=*/true,
- /*rollback_data_save_requested=*/false,
- /*rollback_allowed_milestones=*/4,
- false,
- false);
+ attempter_.CalculateUpdateParams({
+ .target_version_prefix = "1234",
+ .rollback_allowed = true,
+ .rollback_allowed_milestones = 4,
+ });
EXPECT_TRUE(fake_system_state_.request_params()->rollback_allowed());
EXPECT_EQ(4,
fake_system_state_.request_params()->rollback_allowed_milestones());
- attempter_.CalculateUpdateParams("",
- "",
- "",
- "1234",
- /*rollback_allowed=*/false,
- /*rollback_data_save_requested=*/false,
- /*rollback_allowed_milestones=*/4,
- false,
- false);
+ attempter_.CalculateUpdateParams({
+ .target_version_prefix = "1234",
+ .rollback_allowed_milestones = 4,
+ });
EXPECT_FALSE(fake_system_state_.request_params()->rollback_allowed());
EXPECT_EQ(4,
fake_system_state_.request_params()->rollback_allowed_milestones());
}
+TEST_F(UpdateAttempterTest, ChannelDowngradeNoRollback) {
+ base::ScopedTempDir tempdir;
+ ASSERT_TRUE(tempdir.CreateUniqueTempDir());
+ fake_system_state_.request_params()->set_root(tempdir.GetPath().value());
+ attempter_.CalculateUpdateParams({
+ .target_channel = "stable-channel",
+ });
+ EXPECT_FALSE(fake_system_state_.request_params()->is_powerwash_allowed());
+}
+
+TEST_F(UpdateAttempterTest, ChannelDowngradeRollback) {
+ base::ScopedTempDir tempdir;
+ ASSERT_TRUE(tempdir.CreateUniqueTempDir());
+ fake_system_state_.request_params()->set_root(tempdir.GetPath().value());
+ attempter_.CalculateUpdateParams({
+ .rollback_on_channel_downgrade = true,
+ .target_channel = "stable-channel",
+ });
+ EXPECT_TRUE(fake_system_state_.request_params()->is_powerwash_allowed());
+}
+
TEST_F(UpdateAttempterTest, UpdateDeferredByPolicyTest) {
// Construct an OmahaResponseHandlerAction that has processed an InstallPlan,
// but the update is being deferred by the Policy.
@@ -1845,7 +1831,7 @@
SetRollbackHappened(false))
.Times(expected_reset ? 1 : 0);
attempter_.policy_provider_ = std::move(mock_policy_provider);
- attempter_.Update("", "", "", "", false, false, 0, false, false);
+ attempter_.Update({});
ScheduleQuitMainLoop();
}
@@ -2186,7 +2172,7 @@
.WillOnce(Return(false));
attempter_.policy_provider_.reset(
new policy::PolicyProvider(std::move(device_policy)));
- attempter_.Update("", "", "", "", false, false, 0, false, false);
+ attempter_.Update({});
EXPECT_EQ(token, attempter_.omaha_request_params_->autoupdate_token());
ScheduleQuitMainLoop();
diff --git a/update_engine.conf.chromeos b/update_engine.conf.chromeos
new file mode 100644
index 0000000..af213ad
--- /dev/null
+++ b/update_engine.conf.chromeos
@@ -0,0 +1,2 @@
+PAYLOAD_MAJOR_VERSION=2
+PAYLOAD_MINOR_VERSION=6
diff --git a/update_manager/android_things_policy.cc b/update_manager/android_things_policy.cc
index a76ea48..c4fa75a 100644
--- a/update_manager/android_things_policy.cc
+++ b/update_manager/android_things_policy.cc
@@ -58,10 +58,12 @@
// Set the default return values.
result->updates_enabled = true;
result->target_channel.clear();
+ result->lts_tag.clear();
result->target_version_prefix.clear();
result->rollback_allowed = false;
result->rollback_data_save_requested = false;
result->rollback_allowed_milestones = -1;
+ result->rollback_on_channel_downgrade = false;
result->interactive = false;
// Build a list of policies to consult. Note that each policy may modify the
diff --git a/update_manager/boxed_value.cc b/update_manager/boxed_value.cc
index b031dfc..ba84a41 100644
--- a/update_manager/boxed_value.cc
+++ b/update_manager/boxed_value.cc
@@ -23,6 +23,7 @@
#include <base/strings/string_number_conversions.h>
#include <base/time/time.h>
+#include <base/version.h>
#include "update_engine/common/utils.h"
#include "update_engine/connection_utils.h"
@@ -234,4 +235,30 @@
return retval;
}
+template <>
+string BoxedValue::ValuePrinter<ChannelDowngradeBehavior>(const void* value) {
+ const ChannelDowngradeBehavior* val =
+ reinterpret_cast<const ChannelDowngradeBehavior*>(value);
+ switch (*val) {
+ case ChannelDowngradeBehavior::kUnspecified:
+ return "Unspecified";
+ case ChannelDowngradeBehavior::kWaitForVersionToCatchUp:
+ return "Wait for the target channel to catch up";
+ case ChannelDowngradeBehavior::kRollback:
+ return "Roll back and powerwash on channel downgrade";
+ case ChannelDowngradeBehavior::kAllowUserToConfigure:
+ return "User decides on channel downgrade behavior";
+ }
+ NOTREACHED();
+ return "Unknown";
+}
+
+template <>
+string BoxedValue::ValuePrinter<base::Version>(const void* value) {
+ const base::Version* val = reinterpret_cast<const base::Version*>(value);
+ if (val->IsValid())
+ return val->GetString();
+ return "Unknown";
+}
+
} // namespace chromeos_update_manager
diff --git a/update_manager/chromeos_policy.cc b/update_manager/chromeos_policy.cc
index be5f914..4c651b7 100644
--- a/update_manager/chromeos_policy.cc
+++ b/update_manager/chromeos_policy.cc
@@ -156,6 +156,7 @@
case ErrorCode::kUnresolvedHostRecovered:
case ErrorCode::kNotEnoughSpace:
case ErrorCode::kDeviceCorrupted:
+ case ErrorCode::kPackageExcludedFromUpdate:
LOG(INFO) << "Not changing URL index or failure count due to error "
<< chromeos_update_engine::utils::ErrorCodeToString(err_code)
<< " (" << static_cast<int>(err_code) << ")";
@@ -216,9 +217,11 @@
// Set the default return values.
result->updates_enabled = true;
result->target_channel.clear();
+ result->lts_tag.clear();
result->target_version_prefix.clear();
result->rollback_allowed = false;
result->rollback_allowed_milestones = -1;
+ result->rollback_on_channel_downgrade = false;
result->interactive = false;
EnoughSlotsAbUpdatesPolicyImpl enough_slots_ab_updates_policy;
diff --git a/update_manager/chromeos_policy_unittest.cc b/update_manager/chromeos_policy_unittest.cc
index 414ac0d..996db2b 100644
--- a/update_manager/chromeos_policy_unittest.cc
+++ b/update_manager/chromeos_policy_unittest.cc
@@ -262,6 +262,8 @@
new bool(false));
fake_state_.device_policy_provider()->var_release_channel()->reset(
new string("foo-channel"));
+ fake_state_.device_policy_provider()->var_release_lts_tag()->reset(
+ new string("foo-hint"));
UpdateCheckParams result;
ExpectPolicyStatus(
@@ -270,6 +272,7 @@
EXPECT_EQ("1.2", result.target_version_prefix);
EXPECT_EQ(5, result.rollback_allowed_milestones);
EXPECT_EQ("foo-channel", result.target_channel);
+ EXPECT_EQ("foo-hint", result.lts_tag);
EXPECT_FALSE(result.interactive);
}
@@ -338,6 +341,26 @@
EvalStatus::kAskMeAgainLater, &Policy::UpdateCheckAllowed, &result);
}
+TEST_F(UmChromeOSPolicyTest, TestUpdateCheckIntervalTimeout) {
+ fake_state_.updater_provider()
+ ->var_test_update_check_interval_timeout()
+ ->reset(new int64_t(10));
+ fake_state_.system_provider()->var_is_official_build()->reset(
+ new bool(false));
+
+ // The first time, update should not be allowed.
+ UpdateCheckParams result;
+ ExpectPolicyStatus(
+ EvalStatus::kAskMeAgainLater, &Policy::UpdateCheckAllowed, &result);
+
+ // After moving the time forward more than the update check interval, it
+ // should now allow for update.
+ fake_clock_.SetWallclockTime(fake_clock_.GetWallclockTime() +
+ TimeDelta::FromSeconds(11));
+ ExpectPolicyStatus(
+ EvalStatus::kSucceeded, &Policy::UpdateCheckAllowed, &result);
+}
+
TEST_F(UmChromeOSPolicyTest,
UpdateCheckAllowedUpdatesDisabledWhenNotEnoughSlotsAbUpdates) {
// UpdateCheckAllowed should return false (kSucceeded) if the image booted
diff --git a/update_manager/default_policy.cc b/update_manager/default_policy.cc
index 81ab795..7ca414b 100644
--- a/update_manager/default_policy.cc
+++ b/update_manager/default_policy.cc
@@ -40,9 +40,11 @@
UpdateCheckParams* result) const {
result->updates_enabled = true;
result->target_channel.clear();
+ result->lts_tag.clear();
result->target_version_prefix.clear();
result->rollback_allowed = false;
result->rollback_allowed_milestones = -1; // No version rolls should happen.
+ result->rollback_on_channel_downgrade = false;
result->interactive = false;
// Ensure that the minimum interval is set. If there's no clock, this defaults
diff --git a/update_manager/device_policy_provider.h b/update_manager/device_policy_provider.h
index b68fe96..a59f2a3 100644
--- a/update_manager/device_policy_provider.h
+++ b/update_manager/device_policy_provider.h
@@ -21,6 +21,7 @@
#include <string>
#include <base/time/time.h>
+#include <base/version.h>
#include <policy/libpolicy.h>
#include "update_engine/update_manager/provider.h"
@@ -44,6 +45,8 @@
virtual Variable<bool>* var_release_channel_delegated() = 0;
+ virtual Variable<std::string>* var_release_lts_tag() = 0;
+
virtual Variable<bool>* var_update_disabled() = 0;
virtual Variable<std::string>* var_target_version_prefix() = 0;
@@ -85,6 +88,15 @@
virtual Variable<WeeklyTimeIntervalVector>*
var_disallowed_time_intervals() = 0;
+ // Variable that determins whether we should powerwash and rollback on channel
+ // downgrade for enrolled devices.
+ virtual Variable<ChannelDowngradeBehavior>*
+ var_channel_downgrade_behavior() = 0;
+
+ // Variable that contains Chrome OS minimum required version. It contains a
+ // Chrome OS version number.
+ virtual Variable<base::Version>* var_device_minimum_version() = 0;
+
protected:
DevicePolicyProvider() {}
diff --git a/update_manager/enterprise_device_policy_impl.cc b/update_manager/enterprise_device_policy_impl.cc
index dea38ba..ce8150e 100644
--- a/update_manager/enterprise_device_policy_impl.cc
+++ b/update_manager/enterprise_device_policy_impl.cc
@@ -62,13 +62,37 @@
ec->GetValue(system_provider->var_kiosk_required_platform_version());
if (!kiosk_required_platform_version_p) {
LOG(INFO) << "Kiosk app required platform version is not fetched, "
- "blocking update checks";
+ "blocking update checks.";
return EvalStatus::kAskMeAgainLater;
+ } else if (kiosk_required_platform_version_p->empty()) {
+ // The platform version could not be fetched several times. Update
+ // based on |DeviceMinimumVersion| instead (crbug.com/1048931).
+ const base::Version* device_minimum_version_p =
+ ec->GetValue(dp_provider->var_device_minimum_version());
+ const base::Version* current_version_p(
+ ec->GetValue(system_provider->var_chromeos_version()));
+ if (device_minimum_version_p && device_minimum_version_p->IsValid() &&
+ current_version_p && current_version_p->IsValid() &&
+ *current_version_p > *device_minimum_version_p) {
+ // Do not update if the current version is newer than the minimum
+ // version.
+ LOG(INFO) << "Reading kiosk app required platform version failed "
+ "repeatedly but current version is newer than "
+ "DeviceMinimumVersion. Blocking update checks. "
+ "Current version: "
+ << *current_version_p
+ << " DeviceMinimumVersion: " << *device_minimum_version_p;
+ return EvalStatus::kAskMeAgainLater;
+ }
+ LOG(WARNING) << "Reading kiosk app required platform version failed "
+ "repeatedly. Attempting an update without it now.";
+ // An empty string for |target_version_prefix| allows arbitrary updates.
+ result->target_version_prefix = "";
+ } else {
+ result->target_version_prefix = *kiosk_required_platform_version_p;
+ LOG(INFO) << "Allow kiosk app to control Chrome version policy is set, "
+ << "target version is " << result->target_version_prefix;
}
-
- result->target_version_prefix = *kiosk_required_platform_version_p;
- LOG(INFO) << "Allow kiosk app to control Chrome version policy is set, "
- << "target version is " << result->target_version_prefix;
// TODO(hunyadym): Add support for allowing rollback using the manifest
// (if policy doesn't specify otherwise).
} else {
@@ -117,14 +141,29 @@
if (rollback_allowed_milestones_p)
result->rollback_allowed_milestones = *rollback_allowed_milestones_p;
- // Determine whether a target channel is dictated by policy.
+ // Determine whether a target channel is dictated by policy and whether we
+ // should rollback in case that channel is more stable.
const bool* release_channel_delegated_p =
ec->GetValue(dp_provider->var_release_channel_delegated());
if (release_channel_delegated_p && !(*release_channel_delegated_p)) {
const string* release_channel_p =
ec->GetValue(dp_provider->var_release_channel());
- if (release_channel_p)
+ if (release_channel_p) {
result->target_channel = *release_channel_p;
+ const ChannelDowngradeBehavior* channel_downgrade_behavior_p =
+ ec->GetValue(dp_provider->var_channel_downgrade_behavior());
+ if (channel_downgrade_behavior_p &&
+ *channel_downgrade_behavior_p ==
+ ChannelDowngradeBehavior::kRollback) {
+ result->rollback_on_channel_downgrade = true;
+ }
+ }
+ }
+
+ const string* release_lts_tag_p =
+ ec->GetValue(dp_provider->var_release_lts_tag());
+ if (release_lts_tag_p) {
+ result->lts_tag = *release_lts_tag_p;
}
}
return EvalStatus::kContinue;
diff --git a/update_manager/enterprise_device_policy_impl_unittest.cc b/update_manager/enterprise_device_policy_impl_unittest.cc
new file mode 100644
index 0000000..f27715e
--- /dev/null
+++ b/update_manager/enterprise_device_policy_impl_unittest.cc
@@ -0,0 +1,161 @@
+//
+// Copyright (C) 2020 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/update_manager/enterprise_device_policy_impl.h"
+
+#include <memory>
+
+#include "update_engine/update_manager/policy_test_utils.h"
+
+namespace chromeos_update_manager {
+
+class UmEnterpriseDevicePolicyImplTest : public UmPolicyTestBase {
+ protected:
+ UmEnterpriseDevicePolicyImplTest() : UmPolicyTestBase() {
+ policy_ = std::make_unique<EnterpriseDevicePolicyImpl>();
+ }
+
+ void SetUpDefaultState() override {
+ UmPolicyTestBase::SetUpDefaultState();
+
+ fake_state_.device_policy_provider()->var_device_policy_is_loaded()->reset(
+ new bool(true));
+ }
+};
+
+TEST_F(UmEnterpriseDevicePolicyImplTest, KioskAppVersionSet) {
+ fake_state_.device_policy_provider()->var_update_disabled()->reset(
+ new bool(true));
+ fake_state_.device_policy_provider()
+ ->var_allow_kiosk_app_control_chrome_version()
+ ->reset(new bool(true));
+
+ fake_state_.system_provider()->var_kiosk_required_platform_version()->reset(
+ new std::string("1234.5.6"));
+
+ UpdateCheckParams result;
+ ExpectPolicyStatus(
+ EvalStatus::kContinue, &Policy::UpdateCheckAllowed, &result);
+ EXPECT_EQ(result.target_version_prefix, "1234.5.6");
+}
+
+TEST_F(UmEnterpriseDevicePolicyImplTest, KioskAppVersionUnreadableNoUpdate) {
+ fake_state_.device_policy_provider()->var_update_disabled()->reset(
+ new bool(true));
+ fake_state_.device_policy_provider()
+ ->var_allow_kiosk_app_control_chrome_version()
+ ->reset(new bool(true));
+
+ fake_state_.system_provider()->var_kiosk_required_platform_version()->reset(
+ nullptr);
+
+ UpdateCheckParams result;
+ ExpectPolicyStatus(
+ EvalStatus::kAskMeAgainLater, &Policy::UpdateCheckAllowed, &result);
+}
+
+TEST_F(UmEnterpriseDevicePolicyImplTest, KioskAppVersionUnreadableUpdate) {
+ fake_state_.device_policy_provider()->var_update_disabled()->reset(
+ new bool(true));
+ fake_state_.device_policy_provider()
+ ->var_allow_kiosk_app_control_chrome_version()
+ ->reset(new bool(true));
+
+ // The real variable returns an empty string after several unsuccessful
+ // reading attempts. Fake this by setting it directly to empty string.
+ fake_state_.system_provider()->var_kiosk_required_platform_version()->reset(
+ new std::string(""));
+
+ UpdateCheckParams result;
+ ExpectPolicyStatus(
+ EvalStatus::kContinue, &Policy::UpdateCheckAllowed, &result);
+ EXPECT_EQ(result.target_version_prefix, "");
+}
+
+TEST_F(UmEnterpriseDevicePolicyImplTest,
+ KioskAppVersionUnreadableUpdateWithMinVersion) {
+ fake_state_.device_policy_provider()->var_update_disabled()->reset(
+ new bool(true));
+ fake_state_.device_policy_provider()
+ ->var_allow_kiosk_app_control_chrome_version()
+ ->reset(new bool(true));
+
+ // The real variable returns an empty string after several unsuccessful
+ // reading attempts. Fake this by setting it directly to empty string.
+ fake_state_.system_provider()->var_kiosk_required_platform_version()->reset(
+ new std::string(""));
+ // Update if the minimum version is above the current OS version.
+ fake_state_.device_policy_provider()->var_device_minimum_version()->reset(
+ new base::Version("2.0.0"));
+ fake_state_.system_provider()->var_chromeos_version()->reset(
+ new base::Version("1.0.0"));
+
+ UpdateCheckParams result;
+ ExpectPolicyStatus(
+ EvalStatus::kContinue, &Policy::UpdateCheckAllowed, &result);
+ EXPECT_EQ(result.target_version_prefix, "");
+}
+
+TEST_F(UmEnterpriseDevicePolicyImplTest,
+ KioskAppVersionUnreadableNoUpdateWithMinVersion) {
+ fake_state_.device_policy_provider()->var_update_disabled()->reset(
+ new bool(true));
+ fake_state_.device_policy_provider()
+ ->var_allow_kiosk_app_control_chrome_version()
+ ->reset(new bool(true));
+
+ // The real variable returns an empty string after several unsuccessful
+ // reading attempts. Fake this by setting it directly to empty string.
+ fake_state_.system_provider()->var_kiosk_required_platform_version()->reset(
+ new std::string(""));
+ // Block update if the minimum version is below the current OS version.
+ fake_state_.device_policy_provider()->var_device_minimum_version()->reset(
+ new base::Version("1.0.0"));
+ fake_state_.system_provider()->var_chromeos_version()->reset(
+ new base::Version("2.0.0"));
+
+ UpdateCheckParams result;
+ ExpectPolicyStatus(
+ EvalStatus::kAskMeAgainLater, &Policy::UpdateCheckAllowed, &result);
+}
+
+TEST_F(UmEnterpriseDevicePolicyImplTest, ChannelDowngradeBehaviorNoRollback) {
+ fake_state_.device_policy_provider()->var_release_channel_delegated()->reset(
+ new bool(false));
+ fake_state_.device_policy_provider()->var_release_channel()->reset(
+ new std::string("stable-channel"));
+
+ UpdateCheckParams result;
+ ExpectPolicyStatus(
+ EvalStatus::kContinue, &Policy::UpdateCheckAllowed, &result);
+ EXPECT_FALSE(result.rollback_on_channel_downgrade);
+}
+
+TEST_F(UmEnterpriseDevicePolicyImplTest, ChannelDowngradeBehaviorRollback) {
+ fake_state_.device_policy_provider()->var_release_channel_delegated()->reset(
+ new bool(false));
+ fake_state_.device_policy_provider()->var_release_channel()->reset(
+ new std::string("stable-channel"));
+ fake_state_.device_policy_provider()->var_channel_downgrade_behavior()->reset(
+ new ChannelDowngradeBehavior(ChannelDowngradeBehavior::kRollback));
+
+ UpdateCheckParams result;
+ ExpectPolicyStatus(
+ EvalStatus::kContinue, &Policy::UpdateCheckAllowed, &result);
+ EXPECT_TRUE(result.rollback_on_channel_downgrade);
+}
+
+} // namespace chromeos_update_manager
diff --git a/update_manager/evaluation_context-inl.h b/update_manager/evaluation_context-inl.h
index 59d85da..82861fa 100644
--- a/update_manager/evaluation_context-inl.h
+++ b/update_manager/evaluation_context-inl.h
@@ -39,7 +39,7 @@
std::string errmsg;
const T* result =
var->GetValue(RemainingTime(evaluation_monotonic_deadline_), &errmsg);
- if (result == nullptr) {
+ if (result == nullptr && !var->IsMissingOk()) {
LOG(WARNING) << "Error reading Variable " << var->GetName() << ": \""
<< errmsg << "\"";
}
diff --git a/update_manager/fake_device_policy_provider.h b/update_manager/fake_device_policy_provider.h
index 86bdef1..55d66b3 100644
--- a/update_manager/fake_device_policy_provider.h
+++ b/update_manager/fake_device_policy_provider.h
@@ -42,6 +42,10 @@
return &var_release_channel_delegated_;
}
+ FakeVariable<std::string>* var_release_lts_tag() override {
+ return &var_release_lts_tag_;
+ }
+
FakeVariable<bool>* var_update_disabled() override {
return &var_update_disabled_;
}
@@ -91,6 +95,15 @@
return &var_disallowed_time_intervals_;
}
+ FakeVariable<ChannelDowngradeBehavior>* var_channel_downgrade_behavior()
+ override {
+ return &var_channel_downgrade_behavior_;
+ }
+
+ FakeVariable<base::Version>* var_device_minimum_version() override {
+ return &var_device_minimum_version_;
+ }
+
private:
FakeVariable<bool> var_device_policy_is_loaded_{"policy_is_loaded",
kVariableModePoll};
@@ -98,6 +111,8 @@
kVariableModePoll};
FakeVariable<bool> var_release_channel_delegated_{"release_channel_delegated",
kVariableModePoll};
+ FakeVariable<std::string> var_release_lts_tag_{"release_lts_tag",
+ kVariableModePoll};
FakeVariable<bool> var_update_disabled_{"update_disabled", kVariableModePoll};
FakeVariable<std::string> var_target_version_prefix_{"target_version_prefix",
kVariableModePoll};
@@ -120,6 +135,10 @@
"auto_launched_kiosk_app_id", kVariableModePoll};
FakeVariable<WeeklyTimeIntervalVector> var_disallowed_time_intervals_{
"disallowed_time_intervals", kVariableModePoll};
+ FakeVariable<ChannelDowngradeBehavior> var_channel_downgrade_behavior_{
+ "channel_downgrade_behavior", kVariableModePoll};
+ FakeVariable<base::Version> var_device_minimum_version_{
+ "device_minimum_version", kVariableModePoll};
DISALLOW_COPY_AND_ASSIGN(FakeDevicePolicyProvider);
};
diff --git a/update_manager/fake_system_provider.h b/update_manager/fake_system_provider.h
index f54951b..b320c01 100644
--- a/update_manager/fake_system_provider.h
+++ b/update_manager/fake_system_provider.h
@@ -50,6 +50,10 @@
return &var_kiosk_required_platform_version_;
}
+ FakeVariable<base::Version>* var_chromeos_version() override {
+ return &var_version_;
+ }
+
private:
FakeVariable<bool> var_is_normal_boot_mode_{"is_normal_boot_mode",
kVariableModeConst};
@@ -60,6 +64,8 @@
FakeVariable<unsigned int> var_num_slots_{"num_slots", kVariableModePoll};
FakeVariable<std::string> var_kiosk_required_platform_version_{
"kiosk_required_platform_version", kVariableModePoll};
+ FakeVariable<base::Version> var_version_{"chromeos_version",
+ kVariableModePoll};
DISALLOW_COPY_AND_ASSIGN(FakeSystemProvider);
};
diff --git a/update_manager/fake_updater_provider.h b/update_manager/fake_updater_provider.h
index 7295765..d967f42 100644
--- a/update_manager/fake_updater_provider.h
+++ b/update_manager/fake_updater_provider.h
@@ -83,6 +83,10 @@
return &var_update_restrictions_;
}
+ FakeVariable<int64_t>* var_test_update_check_interval_timeout() override {
+ return &var_test_update_check_interval_timeout_;
+ }
+
private:
FakeVariable<base::Time> var_updater_started_time_{"updater_started_time",
kVariableModePoll};
@@ -108,6 +112,8 @@
"forced_update_requested", kVariableModeAsync};
FakeVariable<UpdateRestrictions> var_update_restrictions_{
"update_restrictions", kVariableModePoll};
+ FakeVariable<int64_t> var_test_update_check_interval_timeout_{
+ "test_update_check_interval_timeout", kVariableModePoll};
DISALLOW_COPY_AND_ASSIGN(FakeUpdaterProvider);
};
diff --git a/update_manager/next_update_check_policy_impl.cc b/update_manager/next_update_check_policy_impl.cc
index 6f9748e..0a78718 100644
--- a/update_manager/next_update_check_policy_impl.cc
+++ b/update_manager/next_update_check_policy_impl.cc
@@ -72,6 +72,11 @@
ec->GetValue(updater_provider->var_updater_started_time());
POLICY_CHECK_VALUE_AND_FAIL(updater_started_time, error);
+ // This value is used for testing only and it will get deleted after the first
+ // time it is read.
+ const int64_t* interval_timeout =
+ ec->GetValue(updater_provider->var_test_update_check_interval_timeout());
+
const Time* last_checked_time =
ec->GetValue(updater_provider->var_last_checked_time());
@@ -83,13 +88,21 @@
// If this is the first attempt, compute and return an initial value.
if (last_checked_time == nullptr ||
*last_checked_time < *updater_started_time) {
- *next_update_check = *updater_started_time +
- FuzzedInterval(&prng,
- constants.timeout_initial_interval,
- constants.timeout_regular_fuzz);
+ TimeDelta time_diff =
+ interval_timeout == nullptr
+ ? FuzzedInterval(&prng,
+ constants.timeout_initial_interval,
+ constants.timeout_regular_fuzz)
+ : TimeDelta::FromSeconds(*interval_timeout);
+ *next_update_check = *updater_started_time + time_diff;
return EvalStatus::kSucceeded;
}
+ if (interval_timeout != nullptr) {
+ *next_update_check =
+ *last_checked_time + TimeDelta::FromSeconds(*interval_timeout);
+ return EvalStatus::kSucceeded;
+ }
// Check whether the server is enforcing a poll interval; if not, this value
// will be zero.
const unsigned int* server_dictated_poll_interval =
diff --git a/update_manager/official_build_check_policy_impl.cc b/update_manager/official_build_check_policy_impl.cc
index 096f7bf..e80c09f 100644
--- a/update_manager/official_build_check_policy_impl.cc
+++ b/update_manager/official_build_check_policy_impl.cc
@@ -27,8 +27,16 @@
const bool* is_official_build_p =
ec->GetValue(state->system_provider()->var_is_official_build());
if (is_official_build_p != nullptr && !(*is_official_build_p)) {
- LOG(INFO) << "Unofficial build, blocking periodic update checks.";
- return EvalStatus::kAskMeAgainLater;
+ const int64_t* interval_timeout_p = ec->GetValue(
+ state->updater_provider()->var_test_update_check_interval_timeout());
+ // The |interval_timeout | is used for testing only to test periodic
+ // update checks on unofficial images.
+ if (interval_timeout_p == nullptr) {
+ LOG(INFO) << "Unofficial build, blocking periodic update checks.";
+ return EvalStatus::kAskMeAgainLater;
+ }
+ LOG(INFO) << "Unofficial build, but periodic update check interval "
+ << "timeout is defined, so update is not blocked.";
}
return EvalStatus::kContinue;
}
diff --git a/update_manager/policy.h b/update_manager/policy.h
index 844a4d0..ad6994c 100644
--- a/update_manager/policy.h
+++ b/update_manager/policy.h
@@ -43,26 +43,32 @@
// Parameters of an update check. These parameters are determined by the
// UpdateCheckAllowed policy.
struct UpdateCheckParams {
- bool updates_enabled; // Whether the auto-updates are enabled on this build.
+ // Whether the auto-updates are enabled on this build.
+ bool updates_enabled{true};
// Attributes pertaining to the case where update checks are allowed.
//
// A target version prefix, if imposed by policy; otherwise, an empty string.
std::string target_version_prefix;
// Specifies whether rollback images are allowed by device policy.
- bool rollback_allowed;
+ bool rollback_allowed{false};
// Specifies if rollbacks should attempt to preserve some system state.
- bool rollback_data_save_requested;
+ bool rollback_data_save_requested{false};
// Specifies the number of Chrome milestones rollback should be allowed,
// starting from the stable version at any time. Value is -1 if unspecified
// (e.g. no device policy is available yet), in this case no version
// roll-forward should happen.
- int rollback_allowed_milestones;
+ int rollback_allowed_milestones{0};
+ // Whether a rollback with data save should be initiated on channel
+ // downgrade (e.g. beta to stable).
+ bool rollback_on_channel_downgrade{false};
// A target channel, if so imposed by policy; otherwise, an empty string.
std::string target_channel;
+ // Specifies if the channel hint, e.g. LTS (Long Term Support) updates.
+ std::string lts_tag;
// Whether the allowed update is interactive (user-initiated) or periodic.
- bool interactive;
+ bool interactive{false};
};
// Input arguments to UpdateCanStart.
diff --git a/update_manager/policy_utils.h b/update_manager/policy_utils.h
index 3204780..dc606f2 100644
--- a/update_manager/policy_utils.h
+++ b/update_manager/policy_utils.h
@@ -55,7 +55,6 @@
EvalStatus status =
(policy->*policy_method)(ec, state, error, result, args...);
if (status != EvalStatus::kContinue) {
- LOG(INFO) << "decision by " << policy->PolicyRequestName(policy_method);
return status;
}
}
diff --git a/update_manager/real_device_policy_provider.cc b/update_manager/real_device_policy_provider.cc
index 781e2ac..0aaf20e 100644
--- a/update_manager/real_device_policy_provider.cc
+++ b/update_manager/real_device_policy_provider.cc
@@ -104,9 +104,10 @@
}
template <typename T>
-void RealDevicePolicyProvider::UpdateVariable(AsyncCopyVariable<T>* var,
- bool (DevicePolicy::*getter)(T*)
- const) {
+void RealDevicePolicyProvider::UpdateVariable(
+ AsyncCopyVariable<T>* var,
+ // NOLINTNEXTLINE(readability/casting)
+ bool (DevicePolicy::*getter)(T*) const) {
T new_value;
if (policy_provider_->device_policy_is_loaded() &&
(policy_provider_->GetDevicePolicy().*getter)(&new_value)) {
@@ -208,6 +209,21 @@
return true;
}
+bool RealDevicePolicyProvider::ConvertChannelDowngradeBehavior(
+ ChannelDowngradeBehavior* channel_downgrade_behavior) const {
+ int behavior;
+ if (!policy_provider_->GetDevicePolicy().GetChannelDowngradeBehavior(
+ &behavior)) {
+ return false;
+ }
+ if (behavior < static_cast<int>(ChannelDowngradeBehavior::kFirstValue) ||
+ behavior > static_cast<int>(ChannelDowngradeBehavior::kLastValue)) {
+ return false;
+ }
+ *channel_downgrade_behavior = static_cast<ChannelDowngradeBehavior>(behavior);
+ return true;
+}
+
void RealDevicePolicyProvider::RefreshDevicePolicy() {
if (!policy_provider_->Reload()) {
LOG(INFO) << "No device policies/settings present.";
@@ -219,6 +235,7 @@
UpdateVariable(&var_release_channel_, &DevicePolicy::GetReleaseChannel);
UpdateVariable(&var_release_channel_delegated_,
&DevicePolicy::GetReleaseChannelDelegated);
+ UpdateVariable(&var_release_lts_tag_, &DevicePolicy::GetReleaseLtsTag);
UpdateVariable(&var_update_disabled_, &DevicePolicy::GetUpdateDisabled);
UpdateVariable(&var_target_version_prefix_,
&DevicePolicy::GetTargetVersionPrefix);
@@ -245,6 +262,10 @@
&DevicePolicy::GetAutoLaunchedKioskAppId);
UpdateVariable(&var_disallowed_time_intervals_,
&RealDevicePolicyProvider::ConvertDisallowedTimeIntervals);
+ UpdateVariable(&var_channel_downgrade_behavior_,
+ &RealDevicePolicyProvider::ConvertChannelDowngradeBehavior);
+ UpdateVariable(&var_device_minimum_version_,
+ &DevicePolicy::GetHighestDeviceMinimumVersion);
}
} // namespace chromeos_update_manager
diff --git a/update_manager/real_device_policy_provider.h b/update_manager/real_device_policy_provider.h
index 9da052d..ebda8fd 100644
--- a/update_manager/real_device_policy_provider.h
+++ b/update_manager/real_device_policy_provider.h
@@ -64,6 +64,10 @@
return &var_release_channel_delegated_;
}
+ Variable<std::string>* var_release_lts_tag() override {
+ return &var_release_lts_tag_;
+ }
+
Variable<bool>* var_update_disabled() override {
return &var_update_disabled_;
}
@@ -109,6 +113,15 @@
return &var_disallowed_time_intervals_;
}
+ Variable<ChannelDowngradeBehavior>* var_channel_downgrade_behavior()
+ override {
+ return &var_channel_downgrade_behavior_;
+ }
+
+ Variable<base::Version>* var_device_minimum_version() override {
+ return &var_device_minimum_version_;
+ }
+
private:
FRIEND_TEST(UmRealDevicePolicyProviderTest, RefreshScheduledTest);
FRIEND_TEST(UmRealDevicePolicyProviderTest, NonExistentDevicePolicyReloaded);
@@ -170,6 +183,11 @@
// devices do not have an owner).
bool ConvertHasOwner(bool* has_owner) const;
+ // Wrapper for |DevicePolicy::GetChannelDowngradeBehavior| that converts the
+ // result to |ChannelDowngradeBehavior|.
+ bool ConvertChannelDowngradeBehavior(
+ ChannelDowngradeBehavior* channel_downgrade_behavior) const;
+
// Used for fetching information about the device policy.
policy::PolicyProvider* policy_provider_;
@@ -191,6 +209,7 @@
AsyncCopyVariable<std::string> var_release_channel_{"release_channel"};
AsyncCopyVariable<bool> var_release_channel_delegated_{
"release_channel_delegated"};
+ AsyncCopyVariable<std::string> var_release_lts_tag_{"release_lts_tag"};
AsyncCopyVariable<bool> var_update_disabled_{"update_disabled"};
AsyncCopyVariable<std::string> var_target_version_prefix_{
"target_version_prefix"};
@@ -211,6 +230,10 @@
"update_time_restrictions"};
AsyncCopyVariable<std::string> var_auto_launched_kiosk_app_id_{
"auto_launched_kiosk_app_id"};
+ AsyncCopyVariable<ChannelDowngradeBehavior> var_channel_downgrade_behavior_{
+ "channel_downgrade_behavior"};
+ AsyncCopyVariable<base::Version> var_device_minimum_version_{
+ "device_minimum_version"};
DISALLOW_COPY_AND_ASSIGN(RealDevicePolicyProvider);
};
diff --git a/update_manager/real_device_policy_provider_unittest.cc b/update_manager/real_device_policy_provider_unittest.cc
index 84debd1..4699ad1 100644
--- a/update_manager/real_device_policy_provider_unittest.cc
+++ b/update_manager/real_device_policy_provider_unittest.cc
@@ -177,6 +177,7 @@
UmTestUtils::ExpectVariableNotSet(provider_->var_release_channel());
UmTestUtils::ExpectVariableNotSet(provider_->var_release_channel_delegated());
+ UmTestUtils::ExpectVariableNotSet(provider_->var_release_lts_tag());
UmTestUtils::ExpectVariableNotSet(provider_->var_update_disabled());
UmTestUtils::ExpectVariableNotSet(provider_->var_target_version_prefix());
UmTestUtils::ExpectVariableNotSet(
@@ -194,6 +195,8 @@
UmTestUtils::ExpectVariableNotSet(
provider_->var_auto_launched_kiosk_app_id());
UmTestUtils::ExpectVariableNotSet(provider_->var_disallowed_time_intervals());
+ UmTestUtils::ExpectVariableNotSet(
+ provider_->var_channel_downgrade_behavior());
}
TEST_F(UmRealDevicePolicyProviderTest, ValuesUpdated) {
@@ -376,4 +379,70 @@
provider_->var_disallowed_time_intervals());
}
+TEST_F(UmRealDevicePolicyProviderTest, ChannelDowngradeBehaviorConverted) {
+ SetUpExistentDevicePolicy();
+ EXPECT_CALL(mock_device_policy_, GetChannelDowngradeBehavior(_))
+#if USE_DBUS
+ .Times(2)
+#else
+ .Times(1)
+#endif // USE_DBUS
+ .WillRepeatedly(DoAll(SetArgPointee<0>(static_cast<int>(
+ ChannelDowngradeBehavior::kRollback)),
+ Return(true)));
+ EXPECT_TRUE(provider_->Init());
+ loop_.RunOnce(false);
+
+ UmTestUtils::ExpectVariableHasValue(
+ ChannelDowngradeBehavior::kRollback,
+ provider_->var_channel_downgrade_behavior());
+}
+
+TEST_F(UmRealDevicePolicyProviderTest, ChannelDowngradeBehaviorTooSmall) {
+ SetUpExistentDevicePolicy();
+ EXPECT_CALL(mock_device_policy_, GetChannelDowngradeBehavior(_))
+#if USE_DBUS
+ .Times(2)
+#else
+ .Times(1)
+#endif // USE_DBUS
+ .WillRepeatedly(DoAll(SetArgPointee<0>(-1), Return(true)));
+ EXPECT_TRUE(provider_->Init());
+ loop_.RunOnce(false);
+
+ UmTestUtils::ExpectVariableNotSet(
+ provider_->var_channel_downgrade_behavior());
+}
+
+TEST_F(UmRealDevicePolicyProviderTest, ChannelDowngradeBehaviorTooLarge) {
+ SetUpExistentDevicePolicy();
+ EXPECT_CALL(mock_device_policy_, GetChannelDowngradeBehavior(_))
+#if USE_DBUS
+ .Times(2)
+#else
+ .Times(1)
+#endif // USE_DBUS
+ .WillRepeatedly(DoAll(SetArgPointee<0>(10), Return(true)));
+ EXPECT_TRUE(provider_->Init());
+ loop_.RunOnce(false);
+
+ UmTestUtils::ExpectVariableNotSet(
+ provider_->var_channel_downgrade_behavior());
+}
+
+TEST_F(UmRealDevicePolicyProviderTest, DeviceMinimumVersionPolicySet) {
+ SetUpExistentDevicePolicy();
+
+ base::Version device_minimum_version("13315.60.12");
+
+ EXPECT_CALL(mock_device_policy_, GetHighestDeviceMinimumVersion(_))
+ .WillRepeatedly(
+ DoAll(SetArgPointee<0>(device_minimum_version), Return(true)));
+ EXPECT_TRUE(provider_->Init());
+ loop_.RunOnce(false);
+
+ UmTestUtils::ExpectVariableHasValue(device_minimum_version,
+ provider_->var_device_minimum_version());
+}
+
} // namespace chromeos_update_manager
diff --git a/update_manager/real_system_provider.cc b/update_manager/real_system_provider.cc
index a900071..9b5bc02 100644
--- a/update_manager/real_system_provider.cc
+++ b/update_manager/real_system_provider.cc
@@ -24,7 +24,10 @@
#include <kiosk-app/dbus-proxies.h>
#endif // USE_CHROME_KIOSK_APP
+#include "update_engine/common/boot_control_interface.h"
+#include "update_engine/common/hardware_interface.h"
#include "update_engine/common/utils.h"
+#include "update_engine/omaha_request_params.h"
#include "update_engine/update_manager/generic_variables.h"
#include "update_engine/update_manager/variable.h"
@@ -64,9 +67,10 @@
std::unique_ptr<T> result(new T());
if (!func_.Run(result.get())) {
if (failed_attempts_ >= kRetryPollVariableMaxRetry) {
- // Give up on the retries, set back the desired polling interval and
- // return the default.
+ // Give up on the retries and set back the desired polling interval.
this->SetPollInterval(base_interval_);
+ // Release the result instead of returning a |nullptr| to indicate that
+ // the result could not be fetched.
return result.release();
}
this->SetPollInterval(
@@ -96,19 +100,19 @@
bool RealSystemProvider::Init() {
var_is_normal_boot_mode_.reset(new ConstCopyVariable<bool>(
- "is_normal_boot_mode", hardware_->IsNormalBootMode()));
+ "is_normal_boot_mode", system_state_->hardware()->IsNormalBootMode()));
var_is_official_build_.reset(new ConstCopyVariable<bool>(
- "is_official_build", hardware_->IsOfficialBuild()));
+ "is_official_build", system_state_->hardware()->IsOfficialBuild()));
var_is_oobe_complete_.reset(new CallCopyVariable<bool>(
"is_oobe_complete",
base::Bind(&chromeos_update_engine::HardwareInterface::IsOOBEComplete,
- base::Unretained(hardware_),
+ base::Unretained(system_state_->hardware()),
nullptr)));
var_num_slots_.reset(new ConstCopyVariable<unsigned int>(
- "num_slots", boot_control_->GetNumSlots()));
+ "num_slots", system_state_->boot_control()->GetNumSlots()));
var_kiosk_required_platform_version_.reset(new RetryPollVariable<string>(
"kiosk_required_platform_version",
@@ -116,6 +120,10 @@
base::Bind(&RealSystemProvider::GetKioskAppRequiredPlatformVersion,
base::Unretained(this))));
+ var_chromeos_version_.reset(new ConstCopyVariable<base::Version>(
+ "chromeos_version",
+ base::Version(system_state_->request_params()->app_version())));
+
return true;
}
diff --git a/update_manager/real_system_provider.h b/update_manager/real_system_provider.h
index 114c6ea..0e68997 100644
--- a/update_manager/real_system_provider.h
+++ b/update_manager/real_system_provider.h
@@ -20,8 +20,9 @@
#include <memory>
#include <string>
-#include "update_engine/common/boot_control_interface.h"
-#include "update_engine/common/hardware_interface.h"
+#include <base/version.h>
+
+#include "update_engine/system_state.h"
#include "update_engine/update_manager/system_provider.h"
namespace org {
@@ -36,16 +37,13 @@
class RealSystemProvider : public SystemProvider {
public:
RealSystemProvider(
- chromeos_update_engine::HardwareInterface* hardware,
- chromeos_update_engine::BootControlInterface* boot_control,
+ chromeos_update_engine::SystemState* system_state,
org::chromium::KioskAppServiceInterfaceProxyInterface* kiosk_app_proxy)
- : hardware_(hardware),
#if USE_CHROME_KIOSK_APP
- boot_control_(boot_control),
- kiosk_app_proxy_(kiosk_app_proxy) {
+ : system_state_(system_state), kiosk_app_proxy_(kiosk_app_proxy) {
}
#else
- boot_control_(boot_control) {
+ system_state_(system_state) {
}
#endif // USE_CHROME_KIOSK_APP
@@ -72,6 +70,10 @@
return var_kiosk_required_platform_version_.get();
}
+ Variable<base::Version>* var_chromeos_version() override {
+ return var_chromeos_version_.get();
+ }
+
private:
bool GetKioskAppRequiredPlatformVersion(
std::string* required_platform_version);
@@ -81,9 +83,9 @@
std::unique_ptr<Variable<bool>> var_is_oobe_complete_;
std::unique_ptr<Variable<unsigned int>> var_num_slots_;
std::unique_ptr<Variable<std::string>> var_kiosk_required_platform_version_;
+ std::unique_ptr<Variable<base::Version>> var_chromeos_version_;
- chromeos_update_engine::HardwareInterface* const hardware_;
- chromeos_update_engine::BootControlInterface* const boot_control_;
+ chromeos_update_engine::SystemState* const system_state_;
#if USE_CHROME_KIOSK_APP
org::chromium::KioskAppServiceInterfaceProxyInterface* const kiosk_app_proxy_;
#endif // USE_CHROME_KIOSK_APP
diff --git a/update_manager/real_system_provider_unittest.cc b/update_manager/real_system_provider_unittest.cc
index f654f7a..9757146 100644
--- a/update_manager/real_system_provider_unittest.cc
+++ b/update_manager/real_system_provider_unittest.cc
@@ -24,6 +24,7 @@
#include "update_engine/common/fake_boot_control.h"
#include "update_engine/common/fake_hardware.h"
+#include "update_engine/fake_system_state.h"
#include "update_engine/update_manager/umtest_utils.h"
#if USE_CHROME_KIOSK_APP
#include "kiosk-app/dbus-proxies.h"
@@ -54,17 +55,15 @@
.WillByDefault(
DoAll(SetArgPointee<0>(kRequiredPlatformVersion), Return(true)));
- provider_.reset(new RealSystemProvider(
- &fake_hardware_, &fake_boot_control_, kiosk_app_proxy_mock_.get()));
+ provider_.reset(new RealSystemProvider(&fake_system_state_,
+ kiosk_app_proxy_mock_.get()));
#else
- provider_.reset(
- new RealSystemProvider(&fake_hardware_, &fake_boot_control_, nullptr));
+ provider_.reset(new RealSystemProvider(&fake_system_state, nullptr));
#endif // USE_CHROME_KIOSK_APP
EXPECT_TRUE(provider_->Init());
}
- chromeos_update_engine::FakeHardware fake_hardware_;
- chromeos_update_engine::FakeBootControl fake_boot_control_;
+ chromeos_update_engine::FakeSystemState fake_system_state_;
unique_ptr<RealSystemProvider> provider_;
#if USE_CHROME_KIOSK_APP
@@ -77,18 +76,29 @@
EXPECT_NE(nullptr, provider_->var_is_official_build());
EXPECT_NE(nullptr, provider_->var_is_oobe_complete());
EXPECT_NE(nullptr, provider_->var_kiosk_required_platform_version());
+ EXPECT_NE(nullptr, provider_->var_chromeos_version());
}
TEST_F(UmRealSystemProviderTest, IsOOBECompleteTrue) {
- fake_hardware_.SetIsOOBEComplete(base::Time());
+ fake_system_state_.fake_hardware()->SetIsOOBEComplete(base::Time());
UmTestUtils::ExpectVariableHasValue(true, provider_->var_is_oobe_complete());
}
TEST_F(UmRealSystemProviderTest, IsOOBECompleteFalse) {
- fake_hardware_.UnsetIsOOBEComplete();
+ fake_system_state_.fake_hardware()->UnsetIsOOBEComplete();
UmTestUtils::ExpectVariableHasValue(false, provider_->var_is_oobe_complete());
}
+TEST_F(UmRealSystemProviderTest, VersionFromRequestParams) {
+ fake_system_state_.request_params()->set_app_version("1.2.3");
+ // Call |Init| again to pick up the version.
+ EXPECT_TRUE(provider_->Init());
+
+ base::Version version("1.2.3");
+ UmTestUtils::ExpectVariableHasValue(version,
+ provider_->var_chromeos_version());
+}
+
#if USE_CHROME_KIOSK_APP
TEST_F(UmRealSystemProviderTest, KioskRequiredPlatformVersion) {
UmTestUtils::ExpectVariableHasValue(
@@ -119,6 +129,22 @@
std::string(kRequiredPlatformVersion),
provider_->var_kiosk_required_platform_version());
}
+
+TEST_F(UmRealSystemProviderTest, KioskRequiredPlatformVersionRepeatedFailure) {
+ // Simulate unreadable platform version. The variable should return a
+ // null pointer |kRetryPollVariableMaxRetry| times and then return an empty
+ // string to indicate that it gave up.
+ constexpr int kNumMethodCalls = 5;
+ EXPECT_CALL(*kiosk_app_proxy_mock_, GetRequiredPlatformVersion)
+ .Times(kNumMethodCalls + 1)
+ .WillRepeatedly(Return(false));
+ for (int i = 0; i < kNumMethodCalls; ++i) {
+ UmTestUtils::ExpectVariableNotSet(
+ provider_->var_kiosk_required_platform_version());
+ }
+ UmTestUtils::ExpectVariableHasValue(
+ std::string(""), provider_->var_kiosk_required_platform_version());
+}
#else
TEST_F(UmRealSystemProviderTest, KioskRequiredPlatformVersion) {
UmTestUtils::ExpectVariableHasValue(
diff --git a/update_manager/real_updater_provider.cc b/update_manager/real_updater_provider.cc
index 1f9af0d..1548d57 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>
@@ -441,6 +442,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_ > 5)
+ 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)
@@ -474,6 +515,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
diff --git a/update_manager/real_updater_provider.h b/update_manager/real_updater_provider.h
index 1b46895..0819357 100644
--- a/update_manager/real_updater_provider.h
+++ b/update_manager/real_updater_provider.h
@@ -94,6 +94,10 @@
return var_update_restrictions_.get();
}
+ Variable<int64_t>* var_test_update_check_interval_timeout() override {
+ return var_test_update_check_interval_timeout_.get();
+ }
+
private:
// A pointer to the update engine's system state aggregator.
chromeos_update_engine::SystemState* system_state_;
@@ -114,6 +118,7 @@
std::unique_ptr<Variable<unsigned int>> var_server_dictated_poll_interval_;
std::unique_ptr<Variable<UpdateRequestStatus>> var_forced_update_requested_;
std::unique_ptr<Variable<UpdateRestrictions>> var_update_restrictions_;
+ std::unique_ptr<Variable<int64_t>> var_test_update_check_interval_timeout_;
DISALLOW_COPY_AND_ASSIGN(RealUpdaterProvider);
};
diff --git a/update_manager/real_updater_provider_unittest.cc b/update_manager/real_updater_provider_unittest.cc
index fb7a763..06808b8 100644
--- a/update_manager/real_updater_provider_unittest.cc
+++ b/update_manager/real_updater_provider_unittest.cc
@@ -327,7 +327,7 @@
TEST_F(UmRealUpdaterProviderTest, GetCurrChannelOkay) {
const string kChannelName("foo-channel");
OmahaRequestParams request_params(&fake_sys_state_);
- request_params.Init("", "", false);
+ request_params.Init("", "", {});
request_params.set_current_channel(kChannelName);
fake_sys_state_.set_request_params(&request_params);
UmTestUtils::ExpectVariableHasValue(kChannelName,
@@ -336,7 +336,7 @@
TEST_F(UmRealUpdaterProviderTest, GetCurrChannelFailEmpty) {
OmahaRequestParams request_params(&fake_sys_state_);
- request_params.Init("", "", false);
+ request_params.Init("", "", {});
request_params.set_current_channel("");
fake_sys_state_.set_request_params(&request_params);
UmTestUtils::ExpectVariableNotSet(provider_->var_curr_channel());
@@ -345,7 +345,7 @@
TEST_F(UmRealUpdaterProviderTest, GetNewChannelOkay) {
const string kChannelName("foo-channel");
OmahaRequestParams request_params(&fake_sys_state_);
- request_params.Init("", "", false);
+ request_params.Init("", "", {});
request_params.set_target_channel(kChannelName);
fake_sys_state_.set_request_params(&request_params);
UmTestUtils::ExpectVariableHasValue(kChannelName,
@@ -354,7 +354,7 @@
TEST_F(UmRealUpdaterProviderTest, GetNewChannelFailEmpty) {
OmahaRequestParams request_params(&fake_sys_state_);
- request_params.Init("", "", false);
+ request_params.Init("", "", {});
request_params.set_target_channel("");
fake_sys_state_.set_request_params(&request_params);
UmTestUtils::ExpectVariableNotSet(provider_->var_new_channel());
@@ -445,4 +445,29 @@
UmTestUtils::ExpectVariableHasValue(UpdateRestrictions::kNone,
provider_->var_update_restrictions());
}
+
+TEST_F(UmRealUpdaterProviderTest, TestUpdateCheckIntervalTimeout) {
+ UmTestUtils::ExpectVariableNotSet(
+ provider_->var_test_update_check_interval_timeout());
+ fake_prefs_.SetInt64(
+ chromeos_update_engine::kPrefsTestUpdateCheckIntervalTimeout, 1);
+ UmTestUtils::ExpectVariableHasValue(
+ static_cast<int64_t>(1),
+ provider_->var_test_update_check_interval_timeout());
+
+ // Make sure the value does not exceed a threshold of 10 minutes.
+ fake_prefs_.SetInt64(
+ chromeos_update_engine::kPrefsTestUpdateCheckIntervalTimeout, 11 * 60);
+ // The next 5 reads should return valid values.
+ for (int i = 0; i < 5; ++i)
+ UmTestUtils::ExpectVariableHasValue(
+ static_cast<int64_t>(10 * 60),
+ provider_->var_test_update_check_interval_timeout());
+
+ // Just to make sure it is not cached anywhere and deleted. The variable is
+ // allowd to be read 6 times.
+ UmTestUtils::ExpectVariableNotSet(
+ provider_->var_test_update_check_interval_timeout());
+}
+
} // namespace chromeos_update_manager
diff --git a/update_manager/rollback_prefs.h b/update_manager/rollback_prefs.h
index 9567701..6cbc447 100644
--- a/update_manager/rollback_prefs.h
+++ b/update_manager/rollback_prefs.h
@@ -35,6 +35,19 @@
kMaxValue = 4
};
+// Whether the device should do rollback and powerwash on channel downgrade.
+// Matches chrome_device_policy.proto's
+// |AutoUpdateSettingsProto::ChannelDowngradeBehavior|.
+enum class ChannelDowngradeBehavior {
+ kUnspecified = 0,
+ kWaitForVersionToCatchUp = 1,
+ kRollback = 2,
+ kAllowUserToConfigure = 3,
+ // These values must be kept up to date.
+ kFirstValue = kUnspecified,
+ kLastValue = kAllowUserToConfigure
+};
+
} // namespace chromeos_update_manager
#endif // UPDATE_ENGINE_UPDATE_MANAGER_ROLLBACK_PREFS_H_
diff --git a/update_manager/state_factory.cc b/update_manager/state_factory.cc
index 78cec6a..a0d8a63 100644
--- a/update_manager/state_factory.cc
+++ b/update_manager/state_factory.cc
@@ -69,8 +69,8 @@
unique_ptr<FakeShillProvider> shill_provider(new FakeShillProvider());
#endif // USE_SHILL
unique_ptr<RealRandomProvider> random_provider(new RealRandomProvider());
- unique_ptr<RealSystemProvider> system_provider(new RealSystemProvider(
- system_state->hardware(), system_state->boot_control(), kiosk_app_proxy));
+ unique_ptr<RealSystemProvider> system_provider(
+ new RealSystemProvider(system_state, kiosk_app_proxy));
unique_ptr<RealTimeProvider> time_provider(new RealTimeProvider(clock));
unique_ptr<RealUpdaterProvider> updater_provider(
diff --git a/update_manager/system_provider.h b/update_manager/system_provider.h
index 13e188b..8eb14e3 100644
--- a/update_manager/system_provider.h
+++ b/update_manager/system_provider.h
@@ -17,6 +17,10 @@
#ifndef UPDATE_ENGINE_UPDATE_MANAGER_SYSTEM_PROVIDER_H_
#define UPDATE_ENGINE_UPDATE_MANAGER_SYSTEM_PROVIDER_H_
+#include <string>
+
+#include <base/version.h>
+
#include "update_engine/update_manager/provider.h"
#include "update_engine/update_manager/variable.h"
@@ -46,6 +50,9 @@
// with zero delay kiosk app if any.
virtual Variable<std::string>* var_kiosk_required_platform_version() = 0;
+ // Chrome OS version number as provided by |ImagePropeties|.
+ virtual Variable<base::Version>* var_chromeos_version() = 0;
+
protected:
SystemProvider() {}
diff --git a/update_manager/update_manager-inl.h b/update_manager/update_manager-inl.h
index a1d172d..550642c 100644
--- a/update_manager/update_manager-inl.h
+++ b/update_manager/update_manager-inl.h
@@ -49,7 +49,6 @@
ec->ResetEvaluation();
const std::string policy_name = policy_->PolicyRequestName(policy_method);
- LOG(INFO) << policy_name << ": START";
// First try calling the actual policy.
std::string error;
@@ -71,8 +70,6 @@
}
}
- LOG(INFO) << policy_name << ": END";
-
return status;
}
diff --git a/update_manager/updater_provider.h b/update_manager/updater_provider.h
index 81ffb41..86af1c8 100644
--- a/update_manager/updater_provider.h
+++ b/update_manager/updater_provider.h
@@ -116,6 +116,10 @@
// for all updates.
virtual Variable<UpdateRestrictions>* var_update_restrictions() = 0;
+ // A variable that returns the number of seconds for the first update check to
+ // happen.
+ virtual Variable<int64_t>* var_test_update_check_interval_timeout() = 0;
+
protected:
UpdaterProvider() {}
diff --git a/update_manager/variable.h b/update_manager/variable.h
index 6c7d350..9ac7dae 100644
--- a/update_manager/variable.h
+++ b/update_manager/variable.h
@@ -83,6 +83,10 @@
// variable. In other case, it returns 0.
base::TimeDelta GetPollInterval() const { return poll_interval_; }
+ // Returns true, if the value for this variable is expected to be missing
+ // sometimes so we can avoid printing confusing error logs.
+ bool IsMissingOk() const { return missing_ok_; }
+
// Adds and removes observers for value changes on the variable. This only
// works for kVariableAsync variables since the other modes don't track value
// changes. Adding the same observer twice has no effect.
@@ -115,6 +119,8 @@
poll_interval_ = poll_interval;
}
+ void SetMissingOk() { missing_ok_ = true; }
+
// Calls ValueChanged on all the observers.
void NotifyValueChanged() {
// Fire all the observer methods from the main loop as single call. In order
@@ -140,7 +146,8 @@
: name_(name),
mode_(mode),
poll_interval_(mode == kVariableModePoll ? poll_interval
- : base::TimeDelta()) {}
+ : base::TimeDelta()),
+ missing_ok_(false) {}
void OnValueChangedNotification() {
// A ValueChanged() method can change the list of observers, for example
@@ -174,6 +181,9 @@
// The list of value changes observers.
std::list<BaseVariable::ObserverInterface*> observer_list_;
+ // Defines whether this variable is expected to have no value.
+ bool missing_ok_;
+
DISALLOW_COPY_AND_ASSIGN(BaseVariable);
};
diff --git a/update_metadata.proto b/update_metadata.proto
index ca59a02..452b89d 100644
--- a/update_metadata.proto
+++ b/update_metadata.proto
@@ -153,16 +153,16 @@
//
// All fields will be set, if this message is present.
message ImageInfo {
- optional string board = 1;
- optional string key = 2;
- optional string channel = 3;
- optional string version = 4;
+ optional string board = 1 [deprecated = true];
+ optional string key = 2 [deprecated = true];
+ optional string channel = 3 [deprecated = true];
+ optional string version = 4 [deprecated = true];
// If these values aren't present, they should be assumed to match
// the equivalent value above. They are normally only different for
// special image types such as nplusone images.
- optional string build_channel = 5;
- optional string build_version = 6;
+ optional string build_channel = 5 [deprecated = true];
+ optional string build_version = 6 [deprecated = true];
}
message InstallOperation {
@@ -173,15 +173,15 @@
BSDIFF = 3 [deprecated = true]; // The data is a bsdiff binary diff.
// On minor version 2 or newer, these operations are supported:
- SOURCE_COPY = 4; // Copy from source to target partition
- SOURCE_BSDIFF = 5; // Like BSDIFF, but read from source partition
+ SOURCE_COPY = 4; // Copy from source to target partition
+ SOURCE_BSDIFF = 5; // Like BSDIFF, but read from source partition
// On minor version 3 or newer and on major version 2 or newer, these
// operations are supported:
- REPLACE_XZ = 8; // Replace destination extents w/ attached xz data.
+ REPLACE_XZ = 8; // Replace destination extents w/ attached xz data.
// On minor version 4 or newer, these operations are supported:
- ZERO = 6; // Write zeros in the destination.
+ ZERO = 6; // Write zeros in the destination.
DISCARD = 7; // Discard the destination blocks, reading as undefined.
BROTLI_BSDIFF = 10; // Like SOURCE_BSDIFF, but compressed with brotli.
@@ -376,9 +376,9 @@
optional PartitionInfo new_rootfs_info = 9 [deprecated = true];
// old_image_info will only be present for delta images.
- optional ImageInfo old_image_info = 10;
+ optional ImageInfo old_image_info = 10 [deprecated = true];
- optional ImageInfo new_image_info = 11;
+ optional ImageInfo new_image_info = 11 [deprecated = true];
// The minor version, also referred as "delta version", of the payload.
// Minor version 0 is full payload, everything else is delta payload.