update_engine: Enterprise channel downgrade
Powerwash and roll back when an enrolled user downgrades the channel:
- If the admin downgrades channel, check for ChannelDowngradebehavior
policy.
- If the user downgrades the channel, powerwash based on given boolean.
Add the "rollback" flag to the powerwash file to try to preserve some
data.
Note that this change is not affecting users yet: The
ChannelDowngradeBehavior policy is not available in DPanel and the UI
does not support chosing powerwash on channel downgrade for enrolled
users.
BUG=chromium:1122531
TEST=FEATURES=test emerge-amd64-generic update_engine
TEST=Set policy with YAPS and test on device
Change-Id: I2f02a6e752eed083b57484766f8e7ecc2eed7aca
Reviewed-on: https://chromium-review.googlesource.com/c/aosp/platform/system/update_engine/+/2397890
Tested-by: Miriam Polzer <mpolzer@google.com>
Commit-Queue: Miriam Polzer <mpolzer@google.com>
Reviewed-by: Amin Hassani <ahassani@chromium.org>
Reviewed-by: Jae Hoon Kim <kimjae@chromium.org>
diff --git a/update_attempter_unittest.cc b/update_attempter_unittest.cc
index 354416e..edcb67b 100644
--- a/update_attempter_unittest.cc
+++ b/update_attempter_unittest.cc
@@ -25,6 +25,7 @@
#include <unordered_set>
#include <base/files/file_util.h>
+#include <base/files/scoped_temp_dir.h>
#include <base/message_loop/message_loop.h>
#include <brillo/message_loops/base_message_loop.h>
#include <brillo/message_loops/message_loop.h>
@@ -179,6 +180,7 @@
bool rollback_allowed,
bool rollback_data_save_requested,
int rollback_allowed_milestones,
+ bool rollback_on_channel_downgrade,
bool obey_proxies,
bool interactive) override {
update_called_ = true;
@@ -191,6 +193,7 @@
rollback_allowed,
rollback_data_save_requested,
rollback_allowed_milestones,
+ rollback_on_channel_downgrade,
obey_proxies,
interactive);
return;
@@ -427,7 +430,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("", "", "", "", "", false, false, 0, false, false, false);
EXPECT_NE(old_session_id, attempter_.session_id_);
ScheduleQuitMainLoop();
}
@@ -798,7 +801,7 @@
EXPECT_CALL(*processor_, StartProcessing());
}
- attempter_.Update("", "", "", "", "", false, false, 0, false, false);
+ attempter_.Update("", "", "", "", "", false, false, 0, false, false, false);
loop_.PostTask(FROM_HERE,
base::Bind(&UpdateAttempterTest::UpdateTestVerify,
base::Unretained(this)));
@@ -998,7 +1001,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("", "", "", "", "", false, false, 0, false, false, false);
EXPECT_FALSE(actual_using_p2p_for_downloading_);
EXPECT_FALSE(actual_using_p2p_for_sharing());
ScheduleQuitMainLoop();
@@ -1020,7 +1023,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("", "", "", "", "", false, false, 0, false, false, false);
EXPECT_FALSE(actual_using_p2p_for_downloading());
EXPECT_FALSE(actual_using_p2p_for_sharing());
ScheduleQuitMainLoop();
@@ -1043,7 +1046,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("", "", "", "", "", false, false, 0, false, false, false);
EXPECT_FALSE(actual_using_p2p_for_downloading());
EXPECT_FALSE(actual_using_p2p_for_sharing());
ScheduleQuitMainLoop();
@@ -1065,7 +1068,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("", "", "", "", "", false, false, 0, false, false, false);
EXPECT_TRUE(actual_using_p2p_for_downloading());
EXPECT_TRUE(actual_using_p2p_for_sharing());
ScheduleQuitMainLoop();
@@ -1097,6 +1100,7 @@
false,
/*rollback_allowed_milestones=*/0,
false,
+ false,
/*interactive=*/true);
EXPECT_FALSE(actual_using_p2p_for_downloading());
EXPECT_TRUE(actual_using_p2p_for_sharing());
@@ -1127,7 +1131,7 @@
attempter_.policy_provider_.reset(
new policy::PolicyProvider(std::move(device_policy)));
- attempter_.Update("", "", "", "", "", false, false, 0, false, false);
+ attempter_.Update("", "", "", "", "", false, false, 0, false, false, false);
EXPECT_EQ(scatter_factor_in_seconds, attempter_.scatter_factor_.InSeconds());
ScheduleQuitMainLoop();
@@ -1165,7 +1169,7 @@
attempter_.policy_provider_.reset(
new policy::PolicyProvider(std::move(device_policy)));
- attempter_.Update("", "", "", "", "", false, false, 0, false, false);
+ attempter_.Update("", "", "", "", "", false, false, 0, false, false, false);
EXPECT_EQ(scatter_factor_in_seconds, attempter_.scatter_factor_.InSeconds());
// Make sure the file still exists.
@@ -1181,7 +1185,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("", "", "", "", "", false, false, 0, false, false, false);
EXPECT_TRUE(fake_prefs.Exists(kPrefsUpdateCheckCount));
EXPECT_TRUE(fake_prefs.GetInt64(kPrefsUpdateCheckCount, &new_value));
EXPECT_EQ(initial_value, new_value);
@@ -1237,6 +1241,7 @@
false,
/*rollback_allowed_milestones=*/0,
false,
+ false,
/*interactive=*/true);
EXPECT_EQ(scatter_factor_in_seconds, attempter_.scatter_factor_.InSeconds());
@@ -1289,7 +1294,7 @@
FakePrefs fake_prefs;
SetUpStagingTest(kValidStagingSchedule, &fake_prefs);
- attempter_.Update("", "", "", "", "", false, false, 0, false, false);
+ attempter_.Update("", "", "", "", "", false, false, 0, false, false, false);
// Check that prefs have the correct values.
int64_t update_count;
EXPECT_TRUE(fake_prefs.GetInt64(kPrefsUpdateCheckCount, &update_count));
@@ -1346,8 +1351,17 @@
FakePrefs fake_prefs;
SetUpStagingTest(kValidStagingSchedule, &fake_prefs);
- attempter_.Update(
- "", "", "", "", "", false, false, 0, false, /* interactive = */ true);
+ attempter_.Update("",
+ "",
+ "",
+ "",
+ "",
+ false,
+ false,
+ 0,
+ false,
+ false,
+ /* interactive = */ true);
CheckStagingOff();
ScheduleQuitMainLoop();
@@ -1367,8 +1381,17 @@
FakePrefs fake_prefs;
SetUpStagingTest(kValidStagingSchedule, &fake_prefs);
- attempter_.Update(
- "", "", "", "", "", false, false, 0, false, /* interactive = */ true);
+ attempter_.Update("",
+ "",
+ "",
+ "",
+ "",
+ false,
+ false,
+ 0,
+ false,
+ false,
+ /* interactive = */ true);
CheckStagingOff();
ScheduleQuitMainLoop();
@@ -1697,23 +1720,33 @@
TEST_F(UpdateAttempterTest, TargetVersionPrefixSetAndReset) {
attempter_.CalculateUpdateParams(
- "", "", "", "", "1234", false, false, 4, false, false);
+ /*app_version=*/"",
+ /*omaha_url=*/"",
+ /*target_channel=*/"",
+ /*lts_tag=*/"",
+ /*target_version_prefix=*/"1234",
+ /*rollback_allowed=*/false,
+ /*rollback_data_save_requested=*/false,
+ /*rollback_allowed_milestones=*/4,
+ /*rollback_on_channel_downgrade=*/false,
+ /*obey_proxies=*/false,
+ /*interactive=*/false);
EXPECT_EQ("1234",
fake_system_state_.request_params()->target_version_prefix());
attempter_.CalculateUpdateParams(
- "", "", "", "", "", false, 4, false, false, false);
+ "", "", "", "", "", false, false, 4, false, false, false);
EXPECT_TRUE(
fake_system_state_.request_params()->target_version_prefix().empty());
}
TEST_F(UpdateAttempterTest, TargetChannelHintSetAndReset) {
attempter_.CalculateUpdateParams(
- "", "", "", "hint", "", false, false, 4, false, false);
+ "", "", "", "hint", "", false, false, 4, false, false, false);
EXPECT_EQ("hint", fake_system_state_.request_params()->lts_tag());
attempter_.CalculateUpdateParams(
- "", "", "", "", "", false, 4, false, false, false);
+ "", "", "", "", "", false, false, 4, false, false, false);
EXPECT_TRUE(fake_system_state_.request_params()->lts_tag().empty());
}
@@ -1726,6 +1759,7 @@
/*rollback_allowed=*/true,
/*rollback_data_save_requested=*/false,
/*rollback_allowed_milestones=*/4,
+ /*rollback_on_channel_downgrade=*/false,
false,
false);
EXPECT_TRUE(fake_system_state_.request_params()->rollback_allowed());
@@ -1740,6 +1774,7 @@
/*rollback_allowed=*/false,
/*rollback_data_save_requested=*/false,
/*rollback_allowed_milestones=*/4,
+ /*rollback_on_channel_downgrade=*/false,
false,
false);
EXPECT_FALSE(fake_system_state_.request_params()->rollback_allowed());
@@ -1747,6 +1782,42 @@
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(/*app_version=*/"",
+ /*omaha_url=*/"",
+ /*target_channel=*/"stable-channel",
+ /*lts_tag=*/"",
+ /*target_version_prefix=*/"",
+ /*rollback_allowed=*/false,
+ /*rollback_data_save_requested=*/false,
+ /*rollback_allowed_milestones=*/4,
+ /*rollback_on_channel_downgrade=*/false,
+ /*obey_proxies=*/false,
+ /*interactive=*/false);
+ 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(/*app_version=*/"",
+ /*omaha_url=*/"",
+ /*target_channel=*/"stable-channel",
+ /*lts_tag=*/"",
+ /*target_version_prefix=*/"",
+ /*rollback_allowed=*/false,
+ /*rollback_data_save_requested=*/false,
+ /*rollback_allowed_milestones=*/4,
+ /*rollback_on_channel_downgrade=*/true,
+ /*obey_proxies=*/false,
+ /*interactive=*/false);
+ 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.
@@ -1861,7 +1932,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("", "", "", "", "", false, false, 0, false, false, false);
ScheduleQuitMainLoop();
}
@@ -2202,7 +2273,7 @@
.WillOnce(Return(false));
attempter_.policy_provider_.reset(
new policy::PolicyProvider(std::move(device_policy)));
- attempter_.Update("", "", "", "", "", false, false, 0, false, false);
+ attempter_.Update("", "", "", "", "", false, false, 0, false, false, false);
EXPECT_EQ(token, attempter_.omaha_request_params_->autoupdate_token());
ScheduleQuitMainLoop();