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_manager/android_things_policy.cc b/update_manager/android_things_policy.cc
index 6362a73..c4fa75a 100644
--- a/update_manager/android_things_policy.cc
+++ b/update_manager/android_things_policy.cc
@@ -63,6 +63,7 @@
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/chromeos_policy.cc b/update_manager/chromeos_policy.cc
index 85cc3ae..4c651b7 100644
--- a/update_manager/chromeos_policy.cc
+++ b/update_manager/chromeos_policy.cc
@@ -221,6 +221,7 @@
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/default_policy.cc b/update_manager/default_policy.cc
index cc13c44..7ca414b 100644
--- a/update_manager/default_policy.cc
+++ b/update_manager/default_policy.cc
@@ -44,6 +44,7 @@
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/enterprise_device_policy_impl.cc b/update_manager/enterprise_device_policy_impl.cc
index fed50a9..8fc79ca 100644
--- a/update_manager/enterprise_device_policy_impl.cc
+++ b/update_manager/enterprise_device_policy_impl.cc
@@ -117,14 +117,23 @@
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 =
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..5b25602
--- /dev/null
+++ b/update_manager/enterprise_device_policy_impl_unittest.cc
@@ -0,0 +1,65 @@
+//
+// 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, 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/policy.h b/update_manager/policy.h
index 9194c38..4b3bfc7 100644
--- a/update_manager/policy.h
+++ b/update_manager/policy.h
@@ -58,6 +58,9 @@
// (e.g. no device policy is available yet), in this case no version
// roll-forward should happen.
int rollback_allowed_milestones;
+ // 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.