payload_generator: Use actions to apply payload.

Verity data is written by FilesystemVerifierAction(), so we need to
use the actions to apply payload correctly.

Bug: 28171891
Test: brillo_update_payload verify
Change-Id: I106053a6291282538008f7fbbaba0e6d14346770
diff --git a/payload_generator/generate_delta_main.cc b/payload_generator/generate_delta_main.cc
index eecb345..8240518 100644
--- a/payload_generator/generate_delta_main.cc
+++ b/payload_generator/generate_delta_main.cc
@@ -14,28 +14,27 @@
 // limitations under the License.
 //
 
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <xz.h>
-
 #include <string>
 #include <vector>
 
+#include <base/files/file_path.h>
+#include <base/files/file_util.h>
 #include <base/logging.h>
 #include <base/strings/string_number_conversions.h>
 #include <base/strings/string_split.h>
 #include <brillo/flag_helper.h>
 #include <brillo/key_value_store.h>
+#include <brillo/message_loops/base_message_loop.h>
+#include <xz.h>
 
 #include "update_engine/common/fake_boot_control.h"
 #include "update_engine/common/fake_hardware.h"
+#include "update_engine/common/file_fetcher.h"
 #include "update_engine/common/prefs.h"
 #include "update_engine/common/terminator.h"
 #include "update_engine/common/utils.h"
-#include "update_engine/payload_consumer/delta_performer.h"
+#include "update_engine/payload_consumer/download_action.h"
+#include "update_engine/payload_consumer/filesystem_verifier_action.h"
 #include "update_engine/payload_consumer/payload_constants.h"
 #include "update_engine/payload_generator/delta_diff_generator.h"
 #include "update_engine/payload_generator/payload_generation_config.h"
@@ -185,8 +184,20 @@
   return 0;
 }
 
-// TODO(deymo): This function is likely broken for deltas minor version 2 or
-// newer. Move this function to a new file and make the delta_performer
+class ApplyPayloadProcessorDelegate : public ActionProcessorDelegate {
+ public:
+  void ProcessingDone(const ActionProcessor* processor,
+                      ErrorCode code) override {
+    brillo::MessageLoop::current()->BreakLoop();
+    code_ = code;
+  }
+  void ProcessingStopped(const ActionProcessor* processor) override {
+    brillo::MessageLoop::current()->BreakLoop();
+  }
+  ErrorCode code_;
+};
+
+// TODO(deymo): Move this function to a new file and make the delta_performer
 // integration tests use this instead.
 bool ApplyPayload(const string& payload_file,
                   // Simply reuses the payload config used for payload
@@ -203,6 +214,14 @@
   install_plan.target_slot = 1;
   payload.type =
       config.is_delta ? InstallPayloadType::kDelta : InstallPayloadType::kFull;
+  payload.size = utils::FileSize(payload_file);
+  // TODO(senj): This hash is only correct for unsigned payload, need to support
+  // signed payload using PayloadSigner.
+  HashCalculator::RawHashOfFile(payload_file, payload.size, &payload.hash);
+  install_plan.payloads = {payload};
+  install_plan.download_url =
+      "file://" +
+      base::MakeAbsoluteFilePath(base::FilePath(payload_file)).value();
 
   for (size_t i = 0; i < config.target.partitions.size(); i++) {
     const string& part_name = config.target.partitions[i].name;
@@ -220,31 +239,34 @@
     }
 
     LOG(INFO) << "Install partition:"
-              << " source: " << source_path << " target: " << target_path;
+              << " source: " << source_path << "\ttarget: " << target_path;
   }
 
-  DeltaPerformer performer(&prefs,
-                           &fake_boot_control,
-                           &fake_hardware,
-                           nullptr,
-                           &install_plan,
-                           &payload,
-                           true);  // interactive
-
-  brillo::Blob buf(1024 * 1024);
-  int fd = open(payload_file.c_str(), O_RDONLY, 0);
-  CHECK_GE(fd, 0);
-  ScopedFdCloser fd_closer(&fd);
   xz_crc32_init();
-  for (off_t offset = 0;; offset += buf.size()) {
-    ssize_t bytes_read;
-    CHECK(utils::PReadAll(fd, buf.data(), buf.size(), offset, &bytes_read));
-    if (bytes_read == 0)
-      break;
-    TEST_AND_RETURN_FALSE(performer.Write(buf.data(), bytes_read));
-  }
-  CHECK_EQ(performer.Close(), 0);
-  DeltaPerformer::ResetUpdateProgress(&prefs, false);
+  brillo::BaseMessageLoop loop;
+  loop.SetAsCurrent();
+  auto install_plan_action = std::make_unique<InstallPlanAction>(install_plan);
+  auto download_action =
+      std::make_unique<DownloadAction>(&prefs,
+                                       &fake_boot_control,
+                                       &fake_hardware,
+                                       nullptr,
+                                       new FileFetcher(),
+                                       true /* interactive */);
+  auto filesystem_verifier_action =
+      std::make_unique<FilesystemVerifierAction>();
+
+  BondActions(install_plan_action.get(), download_action.get());
+  BondActions(download_action.get(), filesystem_verifier_action.get());
+  ActionProcessor processor;
+  ApplyPayloadProcessorDelegate delegate;
+  processor.set_delegate(&delegate);
+  processor.EnqueueAction(std::move(install_plan_action));
+  processor.EnqueueAction(std::move(download_action));
+  processor.EnqueueAction(std::move(filesystem_verifier_action));
+  processor.StartProcessing();
+  loop.Run();
+  CHECK_EQ(delegate.code_, ErrorCode::kSuccess);
   LOG(INFO) << "Completed applying " << (config.is_delta ? "delta" : "full")
             << " payload.";
   return true;
diff --git a/scripts/brillo_update_payload b/scripts/brillo_update_payload
index 531a1bd..a4c3f91 100755
--- a/scripts/brillo_update_payload
+++ b/scripts/brillo_update_payload
@@ -758,21 +758,24 @@
 
   echo "Running delta_generator to verify ${payload_type} payload with args: \
 ${GENERATOR_ARGS[@]}"
-  "${GENERATOR}" "${GENERATOR_ARGS[@]}"
+  "${GENERATOR}" "${GENERATOR_ARGS[@]}" || true
 
-  if [[ $? -eq 0 ]]; then
-    echo "Done applying ${payload_type} update."
-    echo "Checking the newly generated partitions against the target partitions"
-    for part in "${PARTITIONS_ORDER[@]}"; do
-      cmp "${TMP_PARTITIONS[${part}]}" "${DST_PARTITIONS[${part}]}"
-      local not_str=""
-      if [[ $? -ne 0 ]]; then
-        not_str="in"
-      fi
-      echo "The new partition (${part}) is ${not_str}valid."
-    done
-  else
-    echo "Failed to apply ${payload_type} update."
+  echo "Done applying ${payload_type} update."
+  echo "Checking the newly generated partitions against the target partitions"
+  local need_pause=false
+  for part in "${PARTITIONS_ORDER[@]}"; do
+    local not_str=""
+    if ! cmp "${TMP_PARTITIONS[${part}]}" "${DST_PARTITIONS[${part}]}"; then
+      not_str="in"
+      need_pause=true
+    fi
+    echo "The new partition (${part}) is ${not_str}valid."
+  done
+  # All images will be cleaned up when script exits, pause here to give a chance
+  # to inspect the images.
+  if [[ "$need_pause" == true ]]; then
+    read -n1 -r -s -p "Paused to investigate invalid partitions, \
+press any key to exit."
   fi
 }