Implement powerwash on Android.
Powerwash, the name for the equivalent of a factory reset or /data wipe,
can be triggered in Android by writing the desired command to the
recovery command file and rebooting into recovery.
This patch moves the powerwash scheduling/canceling logic to the
HardwareInterface and implements it on Android.
Bug: 28700985
TEST=Called update_engine_client passing POWERWASH=1, BCB is stored up
to offset 832.
Change-Id: If737fd4b9b3e2ed9bce709b3b59f22e9f0a3dc9a
diff --git a/payload_consumer/postinstall_runner_action.cc b/payload_consumer/postinstall_runner_action.cc
index c24590e..47b1947 100644
--- a/payload_consumer/postinstall_runner_action.cc
+++ b/payload_consumer/postinstall_runner_action.cc
@@ -58,8 +58,8 @@
install_plan_ = GetInputObject();
if (install_plan_.powerwash_required) {
- if (utils::CreatePowerwashMarkerFile(powerwash_marker_file_)) {
- powerwash_marker_created_ = true;
+ if (hardware_->SchedulePowerwash()) {
+ powerwash_scheduled_ = true;
} else {
return CompletePostinstall(ErrorCode::kPostinstallPowerwashError);
}
@@ -327,9 +327,9 @@
if (error_code != ErrorCode::kSuccess) {
LOG(ERROR) << "Postinstall action failed.";
- // Undo any changes done to trigger Powerwash using clobber-state.
- if (powerwash_marker_created_)
- utils::DeletePowerwashMarkerFile(powerwash_marker_file_);
+ // Undo any changes done to trigger Powerwash.
+ if (powerwash_scheduled_)
+ hardware_->CancelPowerwash();
return;
}
diff --git a/payload_consumer/postinstall_runner_action.h b/payload_consumer/postinstall_runner_action.h
index 4cdc47e..2bde3ca 100644
--- a/payload_consumer/postinstall_runner_action.h
+++ b/payload_consumer/postinstall_runner_action.h
@@ -24,6 +24,8 @@
#include <gtest/gtest_prod.h>
#include "update_engine/common/action.h"
+#include "update_engine/common/boot_control_interface.h"
+#include "update_engine/common/hardware_interface.h"
#include "update_engine/payload_consumer/install_plan.h"
// The Postinstall Runner Action is responsible for running the postinstall
@@ -35,8 +37,9 @@
class PostinstallRunnerAction : public InstallPlanAction {
public:
- explicit PostinstallRunnerAction(BootControlInterface* boot_control)
- : PostinstallRunnerAction(boot_control, nullptr) {}
+ PostinstallRunnerAction(BootControlInterface* boot_control,
+ HardwareInterface* hardware)
+ : boot_control_(boot_control), hardware_(hardware) {}
// InstallPlanAction overrides.
void PerformAction() override;
@@ -63,12 +66,6 @@
friend class PostinstallRunnerActionTest;
FRIEND_TEST(PostinstallRunnerActionTest, ProcessProgressLineTest);
- // Special constructor used for testing purposes.
- PostinstallRunnerAction(BootControlInterface* boot_control,
- const char* powerwash_marker_file)
- : boot_control_(boot_control),
- powerwash_marker_file_(powerwash_marker_file) {}
-
void PerformPartitionPostinstall();
// Called whenever the |progress_fd_| has data available to read.
@@ -127,13 +124,12 @@
// The BootControlInerface used to mark the new slot as ready.
BootControlInterface* boot_control_;
- // True if Powerwash Marker was created before invoking post-install script.
- // False otherwise. Used for cleaning up if post-install fails.
- bool powerwash_marker_created_{false};
+ // HardwareInterface used to signal powerwash.
+ HardwareInterface* hardware_;
- // Non-null value will cause post-install to override the default marker
- // file name; used for testing.
- const char* powerwash_marker_file_;
+ // Whether the Powerwash was scheduled before invoking post-install script.
+ // Used for cleaning up if post-install fails.
+ bool powerwash_scheduled_{false};
// Postinstall command currently running, or 0 if no program running.
pid_t current_command_{0};
diff --git a/payload_consumer/postinstall_runner_action_unittest.cc b/payload_consumer/postinstall_runner_action_unittest.cc
index 3b6b49a..5a8e950 100644
--- a/payload_consumer/postinstall_runner_action_unittest.cc
+++ b/payload_consumer/postinstall_runner_action_unittest.cc
@@ -26,7 +26,6 @@
#include <base/bind.h>
#include <base/files/file_util.h>
-#include <base/files/scoped_temp_dir.h>
#include <base/message_loop/message_loop.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
@@ -38,6 +37,7 @@
#include "update_engine/common/constants.h"
#include "update_engine/common/fake_boot_control.h"
+#include "update_engine/common/fake_hardware.h"
#include "update_engine/common/test_utils.h"
#include "update_engine/common/utils.h"
@@ -88,10 +88,6 @@
loop_.SetAsCurrent();
async_signal_handler_.Init();
subprocess_.Init(&async_signal_handler_);
- ASSERT_TRUE(working_dir_.CreateUniqueTempDir());
- // We use a test-specific powerwash marker file, to avoid race conditions.
- powerwash_marker_file_ =
- working_dir_.path().Append("factory_install_reset").value();
// These tests use the postinstall files generated by "generate_images.sh"
// stored in the "disk_ext2_unittest.img" image.
postinstall_image_ =
@@ -154,14 +150,11 @@
brillo::AsynchronousSignalHandler async_signal_handler_;
Subprocess subprocess_;
- // A temporary working directory used for the test.
- base::ScopedTempDir working_dir_;
- string powerwash_marker_file_;
-
// The path to the postinstall sample image.
string postinstall_image_;
FakeBootControl fake_boot_control_;
+ FakeHardware fake_hardware_;
PostinstActionProcessorDelegate processor_delegate_;
// The PostinstallRunnerAction delegate receiving the progress updates.
@@ -189,8 +182,7 @@
install_plan.download_url = "http://127.0.0.1:8080/update";
install_plan.powerwash_required = powerwash_required;
feeder_action.set_obj(install_plan);
- PostinstallRunnerAction runner_action(&fake_boot_control_,
- powerwash_marker_file_.c_str());
+ PostinstallRunnerAction runner_action(&fake_boot_control_, &fake_hardware_);
postinstall_action_ = &runner_action;
runner_action.set_delegate(setup_action_delegate_);
BondActions(&feeder_action, &runner_action);
@@ -216,8 +208,7 @@
}
TEST_F(PostinstallRunnerActionTest, ProcessProgressLineTest) {
- PostinstallRunnerAction action(&fake_boot_control_,
- powerwash_marker_file_.c_str());
+ PostinstallRunnerAction action(&fake_boot_control_, &fake_hardware_);
testing::StrictMock<MockPostinstallRunnerActionDelegate> mock_delegate_;
action.set_delegate(&mock_delegate_);
@@ -246,7 +237,7 @@
EXPECT_TRUE(processor_delegate_.processing_done_called_);
// Since powerwash_required was false, this should not trigger a powerwash.
- EXPECT_FALSE(utils::FileExists(powerwash_marker_file_.c_str()));
+ EXPECT_FALSE(fake_hardware_.IsPowerwashScheduled());
}
TEST_F(PostinstallRunnerActionTest, RunAsRootRunSymlinkFileTest) {
@@ -261,11 +252,8 @@
RunPosinstallAction(loop.dev(), "bin/postinst_example", true);
EXPECT_EQ(ErrorCode::kSuccess, processor_delegate_.code_);
- // Check that the powerwash marker file was set.
- string actual_cmd;
- EXPECT_TRUE(base::ReadFileToString(base::FilePath(powerwash_marker_file_),
- &actual_cmd));
- EXPECT_EQ(kPowerwashCommand, actual_cmd);
+ // Check that powerwash was scheduled.
+ EXPECT_TRUE(fake_hardware_.IsPowerwashScheduled());
}
// Runs postinstall from a partition file that doesn't mount, so it should
@@ -276,7 +264,7 @@
// In case of failure, Postinstall should not signal a powerwash even if it
// was requested.
- EXPECT_FALSE(utils::FileExists(powerwash_marker_file_.c_str()));
+ EXPECT_FALSE(fake_hardware_.IsPowerwashScheduled());
}
// Check that the failures from the postinstall script cause the action to