update_engine: Powerwash based on version
Powerwash after an update is currently enforced based on the channel: If
the new channel is more stable, powerwash happens. This may cause
unnecessary powerwash if the currently installed Chrome OS version is
old enough so that a normal update (e.g. 12817.68.0 -> 12817.76.0) can
take place.
Additionally decide whether a powerwash should take place based on the
new and old version number. Only powerwash if the new version number is
older than old version number.
BUG=chromium:1070563
TEST=FEATURES=test emerge-amd64-generic update_engine
channel change and update on test device
Change-Id: Ib211cf87711bde9f9c912395548124dcbb1194bb
Reviewed-on: https://chromium-review.googlesource.com/c/aosp/platform/system/update_engine/+/2162986
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/omaha_request_params.h b/omaha_request_params.h
index d29ce70..3452965 100644
--- a/omaha_request_params.h
+++ b/omaha_request_params.h
@@ -266,8 +266,10 @@
// or Init is called again.
virtual void UpdateDownloadChannel();
- // Returns whether we should powerwash for this update.
- virtual bool ShouldPowerwash() const;
+ // Returns whether we should powerwash for this update. Note that this is
+ // just an indication, the final decision to powerwash or not is made in the
+ // response handler.
+ bool ShouldPowerwash() const;
// Check if the provided update URL is official, meaning either the default
// autoupdate server or the autoupdate autotest server.
diff --git a/omaha_response_handler_action.cc b/omaha_response_handler_action.cc
index c25b76f..915e839 100644
--- a/omaha_response_handler_action.cc
+++ b/omaha_response_handler_action.cc
@@ -21,6 +21,7 @@
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
+#include <base/version.h>
#include <policy/device_policy.h>
#include "update_engine/common/constants.h"
@@ -183,8 +184,26 @@
params->rollback_data_save_requested();
}
- if (response.powerwash_required || params->ShouldPowerwash())
+ // Powerwash if either the response requires it or the parameters indicated
+ // powerwash and we are downgrading the version.
+ if (response.powerwash_required) {
install_plan_.powerwash_required = true;
+ } else if (params->ShouldPowerwash()) {
+ base::Version new_version(response.version);
+ base::Version current_version(params->app_version());
+
+ if (!new_version.IsValid()) {
+ LOG(WARNING) << "Not powerwashing,"
+ << " the update's version number is unreadable."
+ << " Update's version number: " << response.version;
+ } else if (!current_version.IsValid()) {
+ LOG(WARNING) << "Not powerwashing,"
+ << " the current version number is unreadable."
+ << " Current version number: " << params->app_version();
+ } else if (new_version < current_version) {
+ install_plan_.powerwash_required = true;
+ }
+ }
TEST_AND_RETURN(HasOutputPipe());
if (HasOutputPipe())
diff --git a/omaha_response_handler_action_unittest.cc b/omaha_response_handler_action_unittest.cc
index 0ebf848..04cfa73 100644
--- a/omaha_response_handler_action_unittest.cc
+++ b/omaha_response_handler_action_unittest.cc
@@ -430,10 +430,11 @@
EXPECT_EQ(in.version, install_plan.version);
}
-TEST_F(OmahaResponseHandlerActionTest, ChangeToMoreStableChannelTest) {
+TEST_F(OmahaResponseHandlerActionTest,
+ ChangeToMoreStableVersionAndChannelTest) {
OmahaResponse in;
in.update_exists = true;
- in.version = "a.b.c.d";
+ in.version = "1.0.0.0";
in.packages.push_back({.payload_urls = {"https://MoreStableChannelTest"},
.size = 1,
.hash = kPayloadHashHex});
@@ -454,7 +455,7 @@
#endif // __ANDROID__
EXPECT_TRUE(params.SetTargetChannel("stable-channel", true, nullptr));
params.UpdateDownloadChannel();
- EXPECT_TRUE(params.ShouldPowerwash());
+ params.set_app_version("2.0.0.0");
fake_system_state_.set_request_params(¶ms);
InstallPlan install_plan;
@@ -462,10 +463,79 @@
EXPECT_TRUE(install_plan.powerwash_required);
}
-TEST_F(OmahaResponseHandlerActionTest, ChangeToLessStableChannelTest) {
+TEST_F(OmahaResponseHandlerActionTest,
+ ChangeToMoreStableVersionAndChannelPowerwashNotAllowedTest) {
OmahaResponse in;
in.update_exists = true;
- in.version = "a.b.c.d";
+ in.version = "1.0.0.0";
+ in.packages.push_back({.payload_urls = {"https://MoreStableChannelTest"},
+ .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("canary-channel");
+ // The |ImageProperties| in Android uses prefs to store
+ // |MutableImageProperties|.
+#ifdef __ANDROID__
+ EXPECT_CALL(*fake_system_state_.mock_prefs(), SetBoolean(_, true))
+ .WillOnce(Return(true));
+#endif // __ANDROID__
+ EXPECT_TRUE(params.SetTargetChannel("stable-channel", false, nullptr));
+ params.UpdateDownloadChannel();
+ params.set_app_version("2.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);
+}
+
+TEST_F(OmahaResponseHandlerActionTest,
+ ChangeToMoreStableChannelButNewerVersionTest) {
+ OmahaResponse in;
+ in.update_exists = true;
+ in.version = "12345.96.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");
+ // The |ImageProperties| in Android uses prefs to store
+ // |MutableImageProperties|.
+#ifdef __ANDROID__
+ EXPECT_CALL(*fake_system_state_.mock_prefs(), SetBoolean(_, true))
+ .WillOnce(Return(true));
+#endif // __ANDROID__
+ EXPECT_TRUE(params.SetTargetChannel("stable-channel", true, nullptr));
+ params.UpdateDownloadChannel();
+ params.set_app_version("12345.48.0.0");
+
+ fake_system_state_.set_request_params(¶ms);
+ InstallPlan install_plan;
+ EXPECT_TRUE(DoTest(in, "", &install_plan));
+ EXPECT_FALSE(install_plan.powerwash_required);
+}
+
+TEST_F(OmahaResponseHandlerActionTest,
+ ChangeToLessStableVersionAndChannelTest) {
+ OmahaResponse in;
+ in.update_exists = true;
+ in.version = "2.0.0.0";
in.packages.push_back({.payload_urls = {"https://LessStableChannelTest"},
.size = 15,
.hash = kPayloadHashHex});
@@ -486,7 +556,7 @@
#endif // __ANDROID__
EXPECT_TRUE(params.SetTargetChannel("canary-channel", false, nullptr));
params.UpdateDownloadChannel();
- EXPECT_FALSE(params.ShouldPowerwash());
+ params.set_app_version("1.0.0.0");
fake_system_state_.set_request_params(¶ms);
InstallPlan install_plan;