update_engine: Add minimum version policy impl
This CL adds minimum version policy handler which checks if the current
Chrome OS version is less than the highest version specified in the
DeviceMinimumVersion policy.
The intent is to consult this policy in a later CL in
ChromeOSPolicy::UpdateCanBeApplied as download time restrictions will
not be applied if current Chrome OS version is
less than version provided by DeviceMinimumVersion policy.
BUG=chromium:1117450
TEST=FEATURES=test emerge-${BOARD} update_engine
Change-Id: I06ce66c4c85ac2718d9256c944160d63a6ac7e31
Reviewed-on: https://chromium-review.googlesource.com/c/aosp/platform/system/update_engine/+/2530630
Commit-Queue: Saurabh Nijhara <snijhara@google.com>
Tested-by: Saurabh Nijhara <snijhara@google.com>
Reviewed-by: Jae Hoon Kim <kimjae@chromium.org>
Reviewed-by: Amin Hassani <ahassani@chromium.org>
diff --git a/BUILD.gn b/BUILD.gn
index f7296ac..1f5dc7f 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -226,6 +226,7 @@
"update_manager/enterprise_device_policy_impl.cc",
"update_manager/evaluation_context.cc",
"update_manager/interactive_update_policy_impl.cc",
+ "update_manager/minimum_version_policy_impl.cc",
"update_manager/next_update_check_policy_impl.cc",
"update_manager/official_build_check_policy_impl.cc",
"update_manager/out_of_box_experience_policy_impl.cc",
@@ -528,6 +529,7 @@
"update_manager/enterprise_device_policy_impl_unittest.cc",
"update_manager/evaluation_context_unittest.cc",
"update_manager/generic_variables_unittest.cc",
+ "update_manager/minimum_version_policy_impl_unittest.cc",
"update_manager/prng_unittest.cc",
"update_manager/real_device_policy_provider_unittest.cc",
"update_manager/real_random_provider_unittest.cc",
diff --git a/update_manager/minimum_version_policy_impl.cc b/update_manager/minimum_version_policy_impl.cc
new file mode 100644
index 0000000..fb94ee4
--- /dev/null
+++ b/update_manager/minimum_version_policy_impl.cc
@@ -0,0 +1,56 @@
+//
+// 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/minimum_version_policy_impl.h"
+
+#include <base/version.h>
+
+using chromeos_update_engine::ErrorCode;
+using chromeos_update_engine::InstallPlan;
+
+namespace chromeos_update_manager {
+
+EvalStatus MinimumVersionPolicyImpl::UpdateCanBeApplied(
+ EvaluationContext* ec,
+ State* state,
+ std::string* error,
+ ErrorCode* result,
+ InstallPlan* install_plan) const {
+ const base::Version* current_version(
+ ec->GetValue(state->system_provider()->var_chromeos_version()));
+ if (current_version == nullptr || !current_version->IsValid()) {
+ LOG(WARNING) << "Unable to access current version";
+ return EvalStatus::kContinue;
+ }
+
+ const base::Version* minimum_version = ec->GetValue(
+ state->device_policy_provider()->var_device_minimum_version());
+ if (minimum_version == nullptr || !minimum_version->IsValid()) {
+ LOG(WARNING) << "Unable to access minimum version";
+ return EvalStatus::kContinue;
+ }
+
+ if (*current_version < *minimum_version) {
+ LOG(INFO) << "Updating from version less than minimum required"
+ ", allowing update to be applied.";
+ *result = ErrorCode::kSuccess;
+ return EvalStatus::kSucceeded;
+ }
+
+ return EvalStatus::kContinue;
+}
+
+} // namespace chromeos_update_manager
diff --git a/update_manager/minimum_version_policy_impl.h b/update_manager/minimum_version_policy_impl.h
new file mode 100644
index 0000000..600d624
--- /dev/null
+++ b/update_manager/minimum_version_policy_impl.h
@@ -0,0 +1,54 @@
+//
+// 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_UPDATE_MANAGER_MINIMUM_VERSION_POLICY_IMPL_H_
+#define UPDATE_ENGINE_UPDATE_MANAGER_MINIMUM_VERSION_POLICY_IMPL_H_
+
+#include <string>
+
+#include "update_engine/common/error_code.h"
+#include "update_engine/payload_consumer/install_plan.h"
+#include "update_engine/update_manager/policy_utils.h"
+
+namespace chromeos_update_manager {
+
+// Check to see if an update happens from a version less than the minimum
+// required one.
+class MinimumVersionPolicyImpl : public PolicyImplBase {
+ public:
+ MinimumVersionPolicyImpl() = default;
+ ~MinimumVersionPolicyImpl() override = default;
+
+ // If current version is less than the minimum required one, then this should
+ // not block the update to be applied.
+ EvalStatus UpdateCanBeApplied(
+ EvaluationContext* ec,
+ State* state,
+ std::string* error,
+ chromeos_update_engine::ErrorCode* result,
+ chromeos_update_engine::InstallPlan* install_plan) const override;
+
+ protected:
+ std::string PolicyName() const override { return "MinimumVersionPolicyImpl"; }
+
+ private:
+ MinimumVersionPolicyImpl(const MinimumVersionPolicyImpl&) = delete;
+ MinimumVersionPolicyImpl& operator=(const MinimumVersionPolicyImpl&) = delete;
+};
+
+} // namespace chromeos_update_manager
+
+#endif // UPDATE_ENGINE_UPDATE_MANAGER_MINIMUM_VERSION_POLICY_IMPL_H_
diff --git a/update_manager/minimum_version_policy_impl_unittest.cc b/update_manager/minimum_version_policy_impl_unittest.cc
new file mode 100644
index 0000000..8e4dba5
--- /dev/null
+++ b/update_manager/minimum_version_policy_impl_unittest.cc
@@ -0,0 +1,111 @@
+//
+// 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 <memory>
+
+#include "update_engine/update_manager/minimum_version_policy_impl.h"
+#include "update_engine/update_manager/policy_test_utils.h"
+
+using chromeos_update_engine::ErrorCode;
+using chromeos_update_engine::InstallPlan;
+
+namespace {
+
+const char* kInvalidVersion = "13315.woops.12";
+const char* kOldVersion = "13315.60.12";
+const char* kNewVersion = "13315.60.15";
+
+} // namespace
+
+namespace chromeos_update_manager {
+
+class UmMinimumVersionPolicyImplTest : public UmPolicyTestBase {
+ protected:
+ UmMinimumVersionPolicyImplTest() {
+ policy_ = std::make_unique<MinimumVersionPolicyImpl>();
+ }
+
+ void SetCurrentVersion(const std::string& version) {
+ fake_state_.system_provider()->var_chromeos_version()->reset(
+ new base::Version(version));
+ }
+
+ void SetMinimumVersion(const std::string& version) {
+ fake_state_.device_policy_provider()->var_device_minimum_version()->reset(
+ new base::Version(version));
+ }
+
+ void TestPolicy(const EvalStatus& expected_status) {
+ InstallPlan install_plan;
+ ErrorCode result;
+ ExpectPolicyStatus(
+ expected_status, &Policy::UpdateCanBeApplied, &result, &install_plan);
+ if (expected_status == EvalStatus::kSucceeded)
+ EXPECT_EQ(result, ErrorCode::kSuccess);
+ }
+};
+
+TEST_F(UmMinimumVersionPolicyImplTest, ContinueWhenCurrentVersionIsNotSet) {
+ SetMinimumVersion(kNewVersion);
+
+ TestPolicy(EvalStatus::kContinue);
+}
+
+TEST_F(UmMinimumVersionPolicyImplTest, ContinueWhenCurrentVersionIsInvalid) {
+ SetCurrentVersion(kInvalidVersion);
+ SetMinimumVersion(kNewVersion);
+
+ TestPolicy(EvalStatus::kContinue);
+}
+
+TEST_F(UmMinimumVersionPolicyImplTest, ContinueWhenMinumumVersionIsNotSet) {
+ SetCurrentVersion(kOldVersion);
+
+ TestPolicy(EvalStatus::kContinue);
+}
+
+TEST_F(UmMinimumVersionPolicyImplTest, ContinueWhenMinumumVersionIsInvalid) {
+ SetCurrentVersion(kOldVersion);
+ SetMinimumVersion(kInvalidVersion);
+
+ TestPolicy(EvalStatus::kContinue);
+}
+
+TEST_F(UmMinimumVersionPolicyImplTest,
+ ContinueWhenCurrentVersionIsGreaterThanMinimumVersion) {
+ SetCurrentVersion(kNewVersion);
+ SetMinimumVersion(kOldVersion);
+
+ TestPolicy(EvalStatus::kContinue);
+}
+
+TEST_F(UmMinimumVersionPolicyImplTest,
+ ContinueWhenCurrentVersionIsEqualToMinimumVersion) {
+ SetCurrentVersion(kNewVersion);
+ SetMinimumVersion(kNewVersion);
+
+ TestPolicy(EvalStatus::kContinue);
+}
+
+TEST_F(UmMinimumVersionPolicyImplTest,
+ SuccessWhenCurrentVersionIsLessThanMinimumVersion) {
+ SetCurrentVersion(kOldVersion);
+ SetMinimumVersion(kNewVersion);
+
+ TestPolicy(EvalStatus::kSucceeded);
+}
+
+} // namespace chromeos_update_manager