Merge "Merge remote-tracking branch 'aosp/upstream-master' into merge"
diff --git a/common/cow_operation_convert.cc b/common/cow_operation_convert.cc
index db17b5f..6b64a9c 100644
--- a/common/cow_operation_convert.cc
+++ b/common/cow_operation_convert.cc
@@ -30,6 +30,7 @@
         merge_operations) {
   ExtentRanges merge_extents;
   std::vector<CowOperation> converted;
+  ExtentRanges modified_extents;
 
   // We want all CowCopy ops to be done first, before any COW_REPLACE happen.
   // Therefore we add these ops in 2 separate loops. This is because during
@@ -42,10 +43,29 @@
     merge_extents.AddExtent(merge_op.dst_extent());
     const auto& src_extent = merge_op.src_extent();
     const auto& dst_extent = merge_op.dst_extent();
-    for (uint64_t i = 0; i < src_extent.num_blocks(); i++) {
-      converted.push_back({CowOperation::CowCopy,
-                           src_extent.start_block() + i,
-                           dst_extent.start_block() + i});
+    // Add blocks in reverse order to avoid merge conflicts on self-overlapping
+    // Ops.
+    // For example: SOURCE_COPY [20 - 30] -> [25 - 35] If blocks are added in
+    // forward order, then 20->25 is performed first, destroying block 25, which
+    // is neede by a later operation.
+    if (src_extent.start_block() < dst_extent.start_block()) {
+      for (uint64_t i = src_extent.num_blocks(); i > 0; i--) {
+        auto src_block = src_extent.start_block() + i - 1;
+        auto dst_block = dst_extent.start_block() + i - 1;
+        CHECK(!modified_extents.ContainsBlock(src_block))
+            << "block " << src_block << " is modified by previous CowCopy";
+        converted.push_back({CowOperation::CowCopy, src_block, dst_block});
+        modified_extents.AddBlock(dst_block);
+      }
+    } else {
+      for (uint64_t i = 0; i < src_extent.num_blocks(); i++) {
+        auto src_block = src_extent.start_block() + i;
+        auto dst_block = dst_extent.start_block() + i;
+        CHECK(!modified_extents.ContainsBlock(src_block))
+            << "block " << src_block << " is modified by previous CowCopy";
+        converted.push_back({CowOperation::CowCopy, src_block, dst_block});
+        modified_extents.AddBlock(dst_block);
+      }
     }
   }
   // COW_REPLACE are added after COW_COPY, because replace might modify blocks
diff --git a/common/cow_operation_convert_unittest.cc b/common/cow_operation_convert_unittest.cc
index b70dcdf..93173fe 100644
--- a/common/cow_operation_convert_unittest.cc
+++ b/common/cow_operation_convert_unittest.cc
@@ -68,7 +68,6 @@
         EXPECT_FALSE(modified_extents.ContainsBlock(cow_op.src_block))
             << "SOURCE_COPY operation " << cow_op
             << " read from a modified block";
-        src_extent_set.SubtractExtent(ExtentForRange(cow_op.src_block, 1));
       }
       EXPECT_TRUE(dst_extent_set.ContainsBlock(cow_op.dst_block));
       dst_extent_set.SubtractExtent(ExtentForRange(cow_op.dst_block, 1));
@@ -217,4 +216,21 @@
   }));
   VerifyCowMergeOp(cow_ops);
 }
+
+TEST_F(CowOperationConvertTest, SelfOverlappingOperation) {
+  AddOperation(
+      &operations_, InstallOperation::SOURCE_COPY, {{20, 10}}, {{25, 10}});
+
+  AddMergeOperation(
+      &merge_operations_, CowMergeOperation::COW_COPY, {20, 10}, {25, 10});
+
+  auto cow_ops = ConvertToCowOperations(operations_, merge_operations_);
+  // Expect 10 COW_COPY
+  ASSERT_EQ(cow_ops.size(), 10UL);
+  ASSERT_TRUE(std::all_of(cow_ops.begin(), cow_ops.end(), [](auto&& cow_op) {
+    return cow_op.op == CowOperation::CowCopy;
+  }));
+  VerifyCowMergeOp(cow_ops);
+}
+
 }  // namespace chromeos_update_engine
diff --git a/payload_consumer/partition_update_generator_android.cc b/payload_consumer/partition_update_generator_android.cc
index 25771e1..4467182 100644
--- a/payload_consumer/partition_update_generator_android.cc
+++ b/payload_consumer/partition_update_generator_android.cc
@@ -41,6 +41,11 @@
         BootControlInterface::Slot target_slot,
         const std::set<std::string>& partitions_in_payload,
         std::vector<PartitionUpdate>* update_list) {
+#ifndef __ANDROID__
+  // Skip copying partitions for host verification.
+  return true;
+#endif
+
   auto ab_partitions = GetAbPartitionsOnDevice();
   if (ab_partitions.empty()) {
     LOG(ERROR) << "Failed to load static a/b partitions";
diff --git a/payload_generator/generate_delta_main.cc b/payload_generator/generate_delta_main.cc
index 29ec290..5bbeee4 100644
--- a/payload_generator/generate_delta_main.cc
+++ b/payload_generator/generate_delta_main.cc
@@ -18,6 +18,7 @@
 #include <string>
 #include <vector>
 
+#include <base/bind.h>
 #include <base/files/file_path.h>
 #include <base/files/file_util.h>
 #include <base/logging.h>
@@ -182,8 +183,11 @@
   install_plan.source_slot =
       config.is_delta ? 0 : BootControlInterface::kInvalidSlot;
   install_plan.target_slot = 1;
-  payload.type =
-      config.is_delta ? InstallPayloadType::kDelta : InstallPayloadType::kFull;
+  // For partial updates, we always write kDelta to the payload. Make it
+  // consistent for host simulation.
+  payload.type = config.is_delta || config.is_partial_update
+                     ? 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.
@@ -234,7 +238,9 @@
   processor.EnqueueAction(std::move(install_plan_action));
   processor.EnqueueAction(std::move(download_action));
   processor.EnqueueAction(std::move(filesystem_verifier_action));
-  processor.StartProcessing();
+  loop.PostTask(FROM_HERE,
+                base::Bind(&ActionProcessor::StartProcessing,
+                           base::Unretained(&processor)));
   loop.Run();
   CHECK_EQ(delegate.code_, ErrorCode::kSuccess);
   LOG(INFO) << "Completed applying " << (config.is_delta ? "delta" : "full")
@@ -573,6 +579,10 @@
     }
   }
 
+  if (FLAGS_is_partial_update) {
+    payload_config.is_partial_update = true;
+  }
+
   if (!FLAGS_in_file.empty()) {
     return ApplyPayload(FLAGS_in_file, payload_config) ? 0 : 1;
   }
@@ -601,10 +611,6 @@
     CHECK(payload_config.target.ValidateDynamicPartitionMetadata());
   }
 
-  if (FLAGS_is_partial_update) {
-    payload_config.is_partial_update = true;
-  }
-
   CHECK(!FLAGS_out_file.empty());
 
   payload_config.rootfs_partition_size = FLAGS_rootfs_partition_size;