update_engine: Place enterprise rollback save marker file
- There are now two types of rollback. One that does a full powerwash
and one that save some system state.
- When an enterprise rollback powerwash is scheduled, place a marker
file to tell the shutdown process to save data before rebooting.
- This lets rollback preserve additional data over a powerwash that
can be restored later.
- Change a few places that were using is_rollback to save_rollback_data
to be explicit.
BUG=chromium:955463
TEST=unittests
Change-Id: I9f18319e711e425a6e712dd319e03bcc6ddd0a1b
Reviewed-on: https://chromium-review.googlesource.com/1414030
Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com>
Tested-by: Zentaro Kavanagh <zentaro@chromium.org>
Reviewed-by: Amin Hassani <ahassani@chromium.org>
diff --git a/common/fake_hardware.h b/common/fake_hardware.h
index 3e5a66e..53b2dd5 100644
--- a/common/fake_hardware.h
+++ b/common/fake_hardware.h
@@ -104,15 +104,15 @@
int GetPowerwashCount() const override { return powerwash_count_; }
- bool SchedulePowerwash(bool is_rollback) override {
+ bool SchedulePowerwash(bool save_rollback_data) override {
powerwash_scheduled_ = true;
- is_rollback_powerwash_ = is_rollback;
+ save_rollback_data_ = save_rollback_data;
return true;
}
bool CancelPowerwash() override {
powerwash_scheduled_ = false;
- is_rollback_powerwash_ = false;
+ save_rollback_data_ = false;
return true;
}
@@ -193,7 +193,7 @@
int GetMaxKernelKeyRollforward() const { return kernel_max_rollforward_; }
bool GetIsRollbackPowerwashScheduled() const {
- return powerwash_scheduled_ && is_rollback_powerwash_;
+ return powerwash_scheduled_ && save_rollback_data_;
}
private:
@@ -213,7 +213,7 @@
int firmware_max_rollforward_{kFirmwareMaxRollforward};
int powerwash_count_{kPowerwashCountNotSet};
bool powerwash_scheduled_{false};
- bool is_rollback_powerwash_{false};
+ bool save_rollback_data_{false};
int64_t build_timestamp_{0};
bool first_active_omaha_ping_sent_{false};
diff --git a/common/hardware_interface.h b/common/hardware_interface.h
index 0140588..6c53540 100644
--- a/common/hardware_interface.h
+++ b/common/hardware_interface.h
@@ -102,9 +102,9 @@
virtual int GetPowerwashCount() const = 0;
// Signals that a powerwash (stateful partition wipe) should be performed
- // after reboot. If |is_rollback| is true additional state is preserved
- // during shutdown that can be restored after the powerwash.
- virtual bool SchedulePowerwash(bool is_rollback) = 0;
+ // after reboot. If |save_rollback_data| is true additional state is
+ // preserved during shutdown that can be restored after the powerwash.
+ virtual bool SchedulePowerwash(bool save_rollback_data) = 0;
// Cancel the powerwash operation scheduled to be performed on next boot.
virtual bool CancelPowerwash() = 0;
diff --git a/hardware_android.cc b/hardware_android.cc
index 21d4659..80c7757 100644
--- a/hardware_android.cc
+++ b/hardware_android.cc
@@ -152,9 +152,10 @@
return 0;
}
-bool HardwareAndroid::SchedulePowerwash(bool is_rollback) {
+bool HardwareAndroid::SchedulePowerwash(bool save_rollback_data) {
LOG(INFO) << "Scheduling a powerwash to BCB.";
- LOG_IF(WARNING, is_rollback) << "is_rollback was true but isn't supported.";
+ LOG_IF(WARNING, save_rollback_data) << "save_rollback_data was true but "
+ << "isn't supported.";
string err;
if (!update_bootloader_message({"--wipe_data", "--reason=wipe_data_from_ota"},
&err)) {
diff --git a/hardware_android.h b/hardware_android.h
index 5b3c99d..c59a152 100644
--- a/hardware_android.h
+++ b/hardware_android.h
@@ -48,7 +48,7 @@
bool SetMaxFirmwareKeyRollforward(int firmware_max_rollforward) override;
bool SetMaxKernelKeyRollforward(int kernel_max_rollforward) override;
int GetPowerwashCount() const override;
- bool SchedulePowerwash(bool is_rollback) override;
+ bool SchedulePowerwash(bool save_rollback_data) override;
bool CancelPowerwash() override;
bool GetNonVolatileDirectory(base::FilePath* path) const override;
bool GetPowerwashSafeDirectory(base::FilePath* path) const override;
diff --git a/hardware_chromeos.cc b/hardware_chromeos.cc
index 8ef05b2..60583e1 100644
--- a/hardware_chromeos.cc
+++ b/hardware_chromeos.cc
@@ -61,6 +61,11 @@
const char kPowerwashMarkerFile[] =
"/mnt/stateful_partition/factory_install_reset";
+// The name of the marker file used to trigger a save of rollback data
+// during the next shutdown.
+const char kRollbackSaveMarkerFile[] =
+ "/mnt/stateful_partition/.save_rollback_data";
+
// The contents of the powerwash marker file for the non-rollback case.
const char kPowerwashCommand[] = "safe fast keepimg reason=update_engine\n";
@@ -226,15 +231,25 @@
return powerwash_count;
}
-bool HardwareChromeOS::SchedulePowerwash(bool is_rollback) {
+bool HardwareChromeOS::SchedulePowerwash(bool save_rollback_data) {
+ if (save_rollback_data) {
+ if (!utils::WriteFile(kRollbackSaveMarkerFile, nullptr, 0)) {
+ PLOG(ERROR) << "Error in creating rollback save marker file: "
+ << kRollbackSaveMarkerFile << ". Rollback will not"
+ << " preserve any data.";
+ } else {
+ LOG(INFO) << "Rollback data save has been scheduled on next shutdown.";
+ }
+ }
+
const char* powerwash_command =
- is_rollback ? kRollbackPowerwashCommand : kPowerwashCommand;
+ save_rollback_data ? kRollbackPowerwashCommand : kPowerwashCommand;
bool result = utils::WriteFile(
kPowerwashMarkerFile, powerwash_command, strlen(powerwash_command));
if (result) {
LOG(INFO) << "Created " << kPowerwashMarkerFile
- << " to powerwash on next reboot (is_rollback=" << is_rollback
- << ")";
+ << " to powerwash on next reboot ("
+ << "save_rollback_data=" << save_rollback_data << ")";
} else {
PLOG(ERROR) << "Error in creating powerwash marker file: "
<< kPowerwashMarkerFile;
@@ -254,6 +269,11 @@
<< kPowerwashMarkerFile;
}
+ // Delete the rollback save marker file if it existed.
+ if (!base::DeleteFile(base::FilePath(kRollbackSaveMarkerFile), false)) {
+ PLOG(ERROR) << "Could not remove rollback save marker";
+ }
+
return result;
}
diff --git a/hardware_chromeos.h b/hardware_chromeos.h
index 8829866..04bdae3 100644
--- a/hardware_chromeos.h
+++ b/hardware_chromeos.h
@@ -53,7 +53,7 @@
bool SetMaxFirmwareKeyRollforward(int firmware_max_rollforward) override;
bool SetMaxKernelKeyRollforward(int kernel_max_rollforward) override;
int GetPowerwashCount() const override;
- bool SchedulePowerwash(bool is_rollback) override;
+ bool SchedulePowerwash(bool save_rollback_data) override;
bool CancelPowerwash() override;
bool GetNonVolatileDirectory(base::FilePath* path) const override;
bool GetPowerwashSafeDirectory(base::FilePath* path) const override;
diff --git a/mock_update_attempter.h b/mock_update_attempter.h
index d97163d..c39fb62 100644
--- a/mock_update_attempter.h
+++ b/mock_update_attempter.h
@@ -30,12 +30,13 @@
public:
using UpdateAttempter::UpdateAttempter;
- MOCK_METHOD8(Update,
+ 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));
diff --git a/omaha_request_params.h b/omaha_request_params.h
index 6691bee..2d2ab69 100644
--- a/omaha_request_params.h
+++ b/omaha_request_params.h
@@ -51,6 +51,7 @@
delta_okay_(true),
interactive_(false),
rollback_allowed_(false),
+ rollback_data_save_requested_(false),
wall_clock_based_wait_enabled_(false),
update_check_count_wait_enabled_(false),
min_update_checks_needed_(kDefaultMinUpdateChecks),
@@ -132,6 +133,15 @@
inline bool rollback_allowed() const { return rollback_allowed_; }
+ inline void set_rollback_data_save_requested(
+ bool rollback_data_save_requested) {
+ rollback_data_save_requested_ = rollback_data_save_requested;
+ }
+
+ inline bool rollback_data_save_requested() const {
+ return rollback_data_save_requested_;
+ }
+
inline void set_rollback_allowed_milestones(int rollback_allowed_milestones) {
rollback_allowed_milestones_ = rollback_allowed_milestones;
}
@@ -330,6 +340,9 @@
// Whether the client is accepting rollback images too.
bool rollback_allowed_;
+ // Whether rollbacks should preserve some system state during powerwash.
+ bool rollback_data_save_requested_;
+
// How many milestones the client can rollback to.
int rollback_allowed_milestones_;
diff --git a/omaha_response_handler_action.cc b/omaha_response_handler_action.cc
index d05bc46..5741a2b 100644
--- a/omaha_response_handler_action.cc
+++ b/omaha_response_handler_action.cc
@@ -178,6 +178,8 @@
return;
}
install_plan_.is_rollback = true;
+ install_plan_.rollback_data_save_requested =
+ params->rollback_data_save_requested();
}
if (response.powerwash_required || params->ShouldPowerwash())
diff --git a/payload_consumer/install_plan.h b/payload_consumer/install_plan.h
index ede36b3..17cefd8 100644
--- a/payload_consumer/install_plan.h
+++ b/payload_consumer/install_plan.h
@@ -146,6 +146,9 @@
// True if this update is a rollback.
bool is_rollback{false};
+ // True if this rollback should preserve some system data.
+ bool rollback_data_save_requested{false};
+
// True if the update should write verity.
// False otherwise.
bool write_verity{true};
diff --git a/payload_consumer/postinstall_runner_action.cc b/payload_consumer/postinstall_runner_action.cc
index a782b8f..cc3843d 100644
--- a/payload_consumer/postinstall_runner_action.cc
+++ b/payload_consumer/postinstall_runner_action.cc
@@ -57,9 +57,14 @@
CHECK(HasInputObject());
install_plan_ = GetInputObject();
- // Currently we're always powerwashing when rolling back.
+ // We always powerwash when rolling back, however policy can determine
+ // if this is a full/normal powerwash, or a special rollback powerwash
+ // 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) {
- if (hardware_->SchedulePowerwash(install_plan_.is_rollback)) {
+ bool save_rollback_data =
+ install_plan_.is_rollback && install_plan_.rollback_data_save_requested;
+ if (hardware_->SchedulePowerwash(save_rollback_data)) {
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 caee5e2..04c81fa 100644
--- a/payload_consumer/postinstall_runner_action_unittest.cc
+++ b/payload_consumer/postinstall_runner_action_unittest.cc
@@ -100,7 +100,8 @@
void RunPostinstallAction(const string& device_path,
const string& postinstall_program,
bool powerwash_required,
- bool is_rollback);
+ bool is_rollback,
+ bool save_rollback_data);
public:
void ResumeRunningAction() {
@@ -170,7 +171,8 @@
const string& device_path,
const string& postinstall_program,
bool powerwash_required,
- bool is_rollback) {
+ bool is_rollback,
+ bool save_rollback_data) {
ActionProcessor processor;
processor_ = &processor;
auto feeder_action = std::make_unique<ObjectFeederAction<InstallPlan>>();
@@ -184,6 +186,7 @@
install_plan.download_url = "http://127.0.0.1:8080/update";
install_plan.powerwash_required = powerwash_required;
install_plan.is_rollback = is_rollback;
+ install_plan.rollback_data_save_requested = save_rollback_data;
feeder_action->set_obj(install_plan);
auto runner_action = std::make_unique<PostinstallRunnerAction>(
&fake_boot_control_, &fake_hardware_);
@@ -249,7 +252,8 @@
TEST_F(PostinstallRunnerActionTest, RunAsRootSimpleTest) {
ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr);
- RunPostinstallAction(loop.dev(), kPostinstallDefaultScript, false, false);
+ RunPostinstallAction(
+ loop.dev(), kPostinstallDefaultScript, false, false, false);
EXPECT_EQ(ErrorCode::kSuccess, processor_delegate_.code_);
EXPECT_TRUE(processor_delegate_.processing_done_called_);
@@ -260,7 +264,7 @@
TEST_F(PostinstallRunnerActionTest, RunAsRootRunSymlinkFileTest) {
ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr);
- RunPostinstallAction(loop.dev(), "bin/postinst_link", false, false);
+ RunPostinstallAction(loop.dev(), "bin/postinst_link", false, false, false);
EXPECT_EQ(ErrorCode::kSuccess, processor_delegate_.code_);
}
@@ -270,6 +274,7 @@
RunPostinstallAction(loop.dev(),
"bin/postinst_example",
/*powerwash_required=*/true,
+ false,
false);
EXPECT_EQ(ErrorCode::kSuccess, processor_delegate_.code_);
@@ -278,14 +283,31 @@
EXPECT_FALSE(fake_hardware_.GetIsRollbackPowerwashScheduled());
}
-TEST_F(PostinstallRunnerActionTest, RunAsRootRollbackTest) {
+TEST_F(PostinstallRunnerActionTest, RunAsRootRollbackTestNoDataSave) {
ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr);
// Run a simple postinstall program, rollback happened.
RunPostinstallAction(loop.dev(),
"bin/postinst_example",
false,
- /*is_rollback=*/true);
+ /*is_rollback=*/true,
+ /*save_rollback_data=*/false);
+ EXPECT_EQ(ErrorCode::kSuccess, processor_delegate_.code_);
+
+ // Check that powerwash was scheduled and that it's NOT a rollback powerwash.
+ EXPECT_TRUE(fake_hardware_.IsPowerwashScheduled());
+ EXPECT_FALSE(fake_hardware_.GetIsRollbackPowerwashScheduled());
+}
+
+TEST_F(PostinstallRunnerActionTest, RunAsRootRollbackTestWithDataSave) {
+ ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr);
+
+ // Run a simple postinstall program, rollback happened.
+ RunPostinstallAction(loop.dev(),
+ "bin/postinst_example",
+ false,
+ /*is_rollback=*/true,
+ /*save_rollback_data=*/true);
EXPECT_EQ(ErrorCode::kSuccess, processor_delegate_.code_);
// Check that powerwash was scheduled and that it's a rollback powerwash.
@@ -296,7 +318,8 @@
// Runs postinstall from a partition file that doesn't mount, so it should
// fail.
TEST_F(PostinstallRunnerActionTest, RunAsRootCantMountTest) {
- RunPostinstallAction("/dev/null", kPostinstallDefaultScript, false, false);
+ RunPostinstallAction(
+ "/dev/null", kPostinstallDefaultScript, false, false, false);
EXPECT_EQ(ErrorCode::kPostinstallRunnerError, processor_delegate_.code_);
// In case of failure, Postinstall should not signal a powerwash even if it
@@ -309,7 +332,7 @@
// fail.
TEST_F(PostinstallRunnerActionTest, RunAsRootErrScriptTest) {
ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr);
- RunPostinstallAction(loop.dev(), "bin/postinst_fail1", false, false);
+ RunPostinstallAction(loop.dev(), "bin/postinst_fail1", false, false, false);
EXPECT_EQ(ErrorCode::kPostinstallRunnerError, processor_delegate_.code_);
}
@@ -317,7 +340,7 @@
// UMA with a different error code. Test those cases are properly detected.
TEST_F(PostinstallRunnerActionTest, RunAsRootFirmwareBErrScriptTest) {
ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr);
- RunPostinstallAction(loop.dev(), "bin/postinst_fail3", false, false);
+ RunPostinstallAction(loop.dev(), "bin/postinst_fail3", false, false, false);
EXPECT_EQ(ErrorCode::kPostinstallBootedFromFirmwareB,
processor_delegate_.code_);
}
@@ -325,7 +348,7 @@
// Check that you can't specify an absolute path.
TEST_F(PostinstallRunnerActionTest, RunAsRootAbsolutePathNotAllowedTest) {
ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr);
- RunPostinstallAction(loop.dev(), "/etc/../bin/sh", false, false);
+ RunPostinstallAction(loop.dev(), "/etc/../bin/sh", false, false, false);
EXPECT_EQ(ErrorCode::kPostinstallRunnerError, processor_delegate_.code_);
}
@@ -334,7 +357,8 @@
// SElinux labels are only set on Android.
TEST_F(PostinstallRunnerActionTest, RunAsRootCheckFileContextsTest) {
ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr);
- RunPostinstallAction(loop.dev(), "bin/self_check_context", false, false);
+ RunPostinstallAction(
+ loop.dev(), "bin/self_check_context", false, false, false);
EXPECT_EQ(ErrorCode::kSuccess, processor_delegate_.code_);
}
#endif // __ANDROID__
@@ -347,7 +371,7 @@
loop_.PostTask(FROM_HERE,
base::Bind(&PostinstallRunnerActionTest::SuspendRunningAction,
base::Unretained(this)));
- RunPostinstallAction(loop.dev(), "bin/postinst_suspend", false, false);
+ RunPostinstallAction(loop.dev(), "bin/postinst_suspend", false, false, false);
// postinst_suspend returns 0 only if it was suspended at some point.
EXPECT_EQ(ErrorCode::kSuccess, processor_delegate_.code_);
EXPECT_TRUE(processor_delegate_.processing_done_called_);
@@ -359,7 +383,7 @@
// Wait for the action to start and then cancel it.
CancelWhenStarted();
- RunPostinstallAction(loop.dev(), "bin/postinst_suspend", false, false);
+ RunPostinstallAction(loop.dev(), "bin/postinst_suspend", false, false, false);
// When canceling the action, the action never finished and therefore we had
// a ProcessingStopped call instead.
EXPECT_FALSE(processor_delegate_.code_set_);
@@ -382,7 +406,8 @@
ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr);
setup_action_delegate_ = &mock_delegate_;
- RunPostinstallAction(loop.dev(), "bin/postinst_progress", false, false);
+ RunPostinstallAction(
+ loop.dev(), "bin/postinst_progress", false, false, false);
EXPECT_EQ(ErrorCode::kSuccess, processor_delegate_.code_);
}
diff --git a/update_attempter.cc b/update_attempter.cc
index 31a6ce4..44eea77 100644
--- a/update_attempter.cc
+++ b/update_attempter.cc
@@ -239,6 +239,7 @@
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) {
@@ -275,6 +276,7 @@
target_channel,
target_version_prefix,
rollback_allowed,
+ rollback_data_save_requested,
rollback_allowed_milestones,
obey_proxies,
interactive)) {
@@ -349,6 +351,7 @@
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) {
@@ -368,6 +371,10 @@
// 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);
// If staging_wait_time_ wasn't set, staging is off, use scattering instead.
if (staging_wait_time_.InSeconds() == 0) {
@@ -953,6 +960,7 @@
params.target_channel,
params.target_version_prefix,
params.rollback_allowed,
+ params.rollback_data_save_requested,
params.rollback_allowed_milestones,
/*obey_proxies=*/false,
params.interactive);
diff --git a/update_attempter.h b/update_attempter.h
index 6c25eb2..82b81ce 100644
--- a/update_attempter.h
+++ b/update_attempter.h
@@ -85,6 +85,7 @@
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);
@@ -341,6 +342,7 @@
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);
diff --git a/update_attempter_unittest.cc b/update_attempter_unittest.cc
index ec6066b..14fad38 100644
--- a/update_attempter_unittest.cc
+++ b/update_attempter_unittest.cc
@@ -506,7 +506,7 @@
EXPECT_CALL(*processor_, StartProcessing());
}
- attempter_.Update("", "", "", "", false, 0, false, false);
+ attempter_.Update("", "", "", "", false, false, 0, false, false);
loop_.PostTask(FROM_HERE,
base::Bind(&UpdateAttempterTest::UpdateTestVerify,
base::Unretained(this)));
@@ -706,7 +706,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, 0, false, false);
+ attempter_.Update("", "", "", "", false, false, 0, false, false);
EXPECT_FALSE(actual_using_p2p_for_downloading_);
EXPECT_FALSE(actual_using_p2p_for_sharing());
ScheduleQuitMainLoop();
@@ -728,7 +728,7 @@
mock_p2p_manager.fake().SetEnsureP2PRunningResult(false);
mock_p2p_manager.fake().SetPerformHousekeepingResult(false);
EXPECT_CALL(mock_p2p_manager, PerformHousekeeping()).Times(0);
- attempter_.Update("", "", "", "", false, 0, false, false);
+ attempter_.Update("", "", "", "", false, false, 0, false, false);
EXPECT_FALSE(actual_using_p2p_for_downloading());
EXPECT_FALSE(actual_using_p2p_for_sharing());
ScheduleQuitMainLoop();
@@ -751,7 +751,7 @@
mock_p2p_manager.fake().SetEnsureP2PRunningResult(true);
mock_p2p_manager.fake().SetPerformHousekeepingResult(false);
EXPECT_CALL(mock_p2p_manager, PerformHousekeeping());
- attempter_.Update("", "", "", "", false, 0, false, false);
+ attempter_.Update("", "", "", "", false, false, 0, false, false);
EXPECT_FALSE(actual_using_p2p_for_downloading());
EXPECT_FALSE(actual_using_p2p_for_sharing());
ScheduleQuitMainLoop();
@@ -773,7 +773,7 @@
mock_p2p_manager.fake().SetEnsureP2PRunningResult(true);
mock_p2p_manager.fake().SetPerformHousekeepingResult(true);
EXPECT_CALL(mock_p2p_manager, PerformHousekeeping());
- attempter_.Update("", "", "", "", false, 0, false, false);
+ attempter_.Update("", "", "", "", false, false, 0, false, false);
EXPECT_TRUE(actual_using_p2p_for_downloading());
EXPECT_TRUE(actual_using_p2p_for_sharing());
ScheduleQuitMainLoop();
@@ -801,6 +801,7 @@
"",
"",
false,
+ false,
/*rollback_allowed_milestones=*/0,
false,
/*interactive=*/true);
@@ -833,7 +834,7 @@
attempter_.policy_provider_.reset(
new policy::PolicyProvider(std::move(device_policy)));
- attempter_.Update("", "", "", "", false, 0, false, false);
+ attempter_.Update("", "", "", "", false, false, 0, false, false);
EXPECT_EQ(scatter_factor_in_seconds, attempter_.scatter_factor_.InSeconds());
ScheduleQuitMainLoop();
@@ -871,7 +872,7 @@
attempter_.policy_provider_.reset(
new policy::PolicyProvider(std::move(device_policy)));
- attempter_.Update("", "", "", "", false, 0, false, false);
+ attempter_.Update("", "", "", "", false, false, 0, false, false);
EXPECT_EQ(scatter_factor_in_seconds, attempter_.scatter_factor_.InSeconds());
// Make sure the file still exists.
@@ -887,7 +888,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, 0, false, false);
+ attempter_.Update("", "", "", "", false, false, 0, false, false);
EXPECT_TRUE(fake_prefs.Exists(kPrefsUpdateCheckCount));
EXPECT_TRUE(fake_prefs.GetInt64(kPrefsUpdateCheckCount, &new_value));
EXPECT_EQ(initial_value, new_value);
@@ -939,6 +940,7 @@
"",
"",
false,
+ false,
/*rollback_allowed_milestones=*/0,
false,
/*interactive=*/true);
@@ -993,7 +995,7 @@
FakePrefs fake_prefs;
SetUpStagingTest(kValidStagingSchedule, &fake_prefs);
- attempter_.Update("", "", "", "", false, 0, false, false);
+ attempter_.Update("", "", "", "", false, false, 0, false, false);
// Check that prefs have the correct values.
int64_t update_count;
EXPECT_TRUE(fake_prefs.GetInt64(kPrefsUpdateCheckCount, &update_count));
@@ -1050,7 +1052,8 @@
FakePrefs fake_prefs;
SetUpStagingTest(kValidStagingSchedule, &fake_prefs);
- attempter_.Update("", "", "", "", false, 0, false, /* interactive = */ true);
+ attempter_.Update(
+ "", "", "", "", false, false, 0, false, /* interactive = */ true);
CheckStagingOff();
ScheduleQuitMainLoop();
@@ -1070,7 +1073,8 @@
FakePrefs fake_prefs;
SetUpStagingTest(kValidStagingSchedule, &fake_prefs);
- attempter_.Update("", "", "", "", false, 0, false, /* interactive = */ true);
+ attempter_.Update(
+ "", "", "", "", false, false, 0, false, /* interactive = */ true);
CheckStagingOff();
ScheduleQuitMainLoop();
@@ -1240,11 +1244,13 @@
}
TEST_F(UpdateAttempterTest, TargetVersionPrefixSetAndReset) {
- attempter_.CalculateUpdateParams("", "", "", "1234", false, 4, false, false);
+ attempter_.CalculateUpdateParams(
+ "", "", "", "1234", false, false, 4, false, false);
EXPECT_EQ("1234",
fake_system_state_.request_params()->target_version_prefix());
- attempter_.CalculateUpdateParams("", "", "", "", false, 4, false, false);
+ attempter_.CalculateUpdateParams(
+ "", "", "", "", false, 4, false, false, false);
EXPECT_TRUE(
fake_system_state_.request_params()->target_version_prefix().empty());
}
@@ -1255,6 +1261,7 @@
"",
"1234",
/*rollback_allowed=*/true,
+ /*rollback_data_save_requested=*/false,
/*rollback_allowed_milestones=*/4,
false,
false);
@@ -1267,6 +1274,7 @@
"",
"1234",
/*rollback_allowed=*/false,
+ /*rollback_data_save_requested=*/false,
/*rollback_allowed_milestones=*/4,
false,
false);
@@ -1392,7 +1400,7 @@
SetRollbackHappened(false))
.Times(expected_reset ? 1 : 0);
attempter_.policy_provider_ = std::move(mock_policy_provider);
- attempter_.Update("", "", "", "", false, 0, false, false);
+ attempter_.Update("", "", "", "", false, false, 0, false, false);
ScheduleQuitMainLoop();
}
diff --git a/update_manager/android_things_policy.cc b/update_manager/android_things_policy.cc
index 4afcf12..26bd0ba 100644
--- a/update_manager/android_things_policy.cc
+++ b/update_manager/android_things_policy.cc
@@ -54,6 +54,7 @@
result->target_channel.clear();
result->target_version_prefix.clear();
result->rollback_allowed = false;
+ result->rollback_data_save_requested = false;
result->rollback_allowed_milestones = -1;
result->interactive = false;
diff --git a/update_manager/enterprise_device_policy_impl.cc b/update_manager/enterprise_device_policy_impl.cc
index a3430ef..3d77d59 100644
--- a/update_manager/enterprise_device_policy_impl.cc
+++ b/update_manager/enterprise_device_policy_impl.cc
@@ -91,22 +91,27 @@
case RollbackToTargetVersion::kDisabled:
LOG(INFO) << "Policy disables rollbacks.";
result->rollback_allowed = false;
+ result->rollback_data_save_requested = false;
break;
case RollbackToTargetVersion::kRollbackAndPowerwash:
LOG(INFO) << "Policy allows rollbacks with powerwash.";
result->rollback_allowed = true;
+ result->rollback_data_save_requested = false;
break;
case RollbackToTargetVersion::kRollbackAndRestoreIfPossible:
LOG(INFO)
<< "Policy allows rollbacks, also tries to restore if possible.";
- // We don't support restore yet, but policy still allows rollback.
result->rollback_allowed = true;
+ result->rollback_data_save_requested = true;
break;
case RollbackToTargetVersion::kRollbackOnlyIfRestorePossible:
+ // TODO(crbug.com/947621): Remove this policy option until we know
+ // how it could be supported correctly.
LOG(INFO) << "Policy only allows rollbacks if restore is possible.";
// We don't support restore yet, policy doesn't allow rollback in this
// case.
result->rollback_allowed = false;
+ result->rollback_data_save_requested = false;
break;
case RollbackToTargetVersion::kMaxValue:
NOTREACHED();
diff --git a/update_manager/policy.h b/update_manager/policy.h
index 5d65d9a..9e7df10 100644
--- a/update_manager/policy.h
+++ b/update_manager/policy.h
@@ -50,6 +50,8 @@
std::string target_version_prefix;
// Specifies whether rollback images are allowed by device policy.
bool rollback_allowed;
+ // Specifies if rollbacks should attempt to preserve some system state.
+ bool rollback_data_save_requested;
// 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