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/common/constants.cc b/common/constants.cc
index c0bb874..0ac22f3 100644
--- a/common/constants.cc
+++ b/common/constants.cc
@@ -18,11 +18,6 @@
 
 namespace chromeos_update_engine {
 
-const char kPowerwashMarkerFile[] =
-    "/mnt/stateful_partition/factory_install_reset";
-
-const char kPowerwashCommand[] = "safe fast keepimg reason=update_engine\n";
-
 const char kPowerwashSafePrefsSubDirectory[] = "update_engine/prefs";
 
 const char kPrefsSubDirectory[] = "prefs";
@@ -97,5 +92,6 @@
 const char kPayloadPropertyMetadataHash[] = "METADATA_HASH";
 const char kPayloadPropertyAuthorization[] = "AUTHORIZATION";
 const char kPayloadPropertyUserAgent[] = "USER_AGENT";
+const char kPayloadPropertyPowerwash[] = "POWERWASH";
 
 }  // namespace chromeos_update_engine
diff --git a/common/constants.h b/common/constants.h
index 660d9a9..649034e 100644
--- a/common/constants.h
+++ b/common/constants.h
@@ -19,13 +19,6 @@
 
 namespace chromeos_update_engine {
 
-// The name of the marker file used to trigger powerwash when post-install
-// completes successfully so that the device is powerwashed on next reboot.
-extern const char kPowerwashMarkerFile[];
-
-// The contents of the powerwash marker file.
-extern const char kPowerwashCommand[];
-
 // Directory for AU prefs that are preserved across powerwash.
 extern const char kPowerwashSafePrefsSubDirectory[];
 
@@ -100,6 +93,7 @@
 extern const char kPayloadPropertyMetadataHash[];
 extern const char kPayloadPropertyAuthorization[];
 extern const char kPayloadPropertyUserAgent[];
+extern const char kPayloadPropertyPowerwash[];
 
 // A download source is any combination of protocol and server (that's of
 // interest to us when looking at UMA metrics) using which we may download
diff --git a/common/fake_hardware.h b/common/fake_hardware.h
index 4558c8c..2da12ad 100644
--- a/common/fake_hardware.h
+++ b/common/fake_hardware.h
@@ -57,6 +57,18 @@
 
   int GetPowerwashCount() const override { return powerwash_count_; }
 
+  bool SchedulePowerwash() override {
+    powerwash_scheduled_ = true;
+    return true;
+  }
+
+  bool CancelPowerwash() override {
+    powerwash_scheduled_ = false;
+    return true;
+  }
+
+  bool IsPowerwashScheduled() { return powerwash_scheduled_; }
+
   bool GetNonVolatileDirectory(base::FilePath* path) const override {
     return false;
   }
@@ -115,6 +127,7 @@
   std::string firmware_version_{"Fake Firmware v1.0.1"};
   std::string ec_version_{"Fake EC v1.0a"};
   int powerwash_count_{kPowerwashCountNotSet};
+  bool powerwash_scheduled_{false};
 
   DISALLOW_COPY_AND_ASSIGN(FakeHardware);
 };
diff --git a/common/hardware_interface.h b/common/hardware_interface.h
index e434cc9..f5f900e 100644
--- a/common/hardware_interface.h
+++ b/common/hardware_interface.h
@@ -70,6 +70,13 @@
   // recovery don't have this value set.
   virtual int GetPowerwashCount() const = 0;
 
+  // Signals that a powerwash (stateful partition wipe) should be performed
+  // after reboot.
+  virtual bool SchedulePowerwash() = 0;
+
+  // Cancel the powerwash operation scheduled to be performed on next boot.
+  virtual bool CancelPowerwash() = 0;
+
   // Store in |path| the path to a non-volatile directory (persisted across
   // reboots) available for this daemon. In case of an error, such as no
   // directory available, returns false.
diff --git a/common/utils.cc b/common/utils.cc
index f7d4585..a352961 100644
--- a/common/utils.cc
+++ b/common/utils.cc
@@ -879,35 +879,6 @@
   return base_code;
 }
 
-bool CreatePowerwashMarkerFile(const char* file_path) {
-  const char* marker_file = file_path ? file_path : kPowerwashMarkerFile;
-  bool result = utils::WriteFile(marker_file,
-                                 kPowerwashCommand,
-                                 strlen(kPowerwashCommand));
-  if (result) {
-    LOG(INFO) << "Created " << marker_file << " to powerwash on next reboot";
-  } else {
-    PLOG(ERROR) << "Error in creating powerwash marker file: " << marker_file;
-  }
-
-  return result;
-}
-
-bool DeletePowerwashMarkerFile(const char* file_path) {
-  const char* marker_file = file_path ? file_path : kPowerwashMarkerFile;
-  const base::FilePath kPowerwashMarkerPath(marker_file);
-  bool result = base::DeleteFile(kPowerwashMarkerPath, false);
-
-  if (result)
-    LOG(INFO) << "Successfully deleted the powerwash marker file : "
-              << marker_file;
-  else
-    PLOG(ERROR) << "Could not delete the powerwash marker file : "
-                << marker_file;
-
-  return result;
-}
-
 Time TimeFromStructTimespec(struct timespec *ts) {
   int64_t us = static_cast<int64_t>(ts->tv_sec) * Time::kMicrosecondsPerSecond +
       static_cast<int64_t>(ts->tv_nsec) / Time::kNanosecondsPerMicrosecond;
diff --git a/common/utils.h b/common/utils.h
index e950b15..3987484 100644
--- a/common/utils.h
+++ b/common/utils.h
@@ -265,16 +265,6 @@
 // it'll return the same value again.
 ErrorCode GetBaseErrorCode(ErrorCode code);
 
-// Creates the powerwash marker file with the appropriate commands in it.  Uses
-// |file_path| as the path to the marker file if non-null, otherwise uses the
-// global default. Returns true if successfully created.  False otherwise.
-bool CreatePowerwashMarkerFile(const char* file_path);
-
-// Deletes the marker file used to trigger Powerwash using clobber-state.  Uses
-// |file_path| as the path to the marker file if non-null, otherwise uses the
-// global default. Returns true if successfully deleted. False otherwise.
-bool DeletePowerwashMarkerFile(const char* file_path);
-
 // Decodes the data in |base64_encoded| and stores it in a temporary
 // file. Returns false if the given data is empty, not well-formed
 // base64 or if an error occurred. If true is returned, the decoded