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