libsnapshot: CowWriter - AddCopy API change

AddCopy - When copy blocks are contiguous, send
'num_blocks' which are contiguous to libsnapshot_cow library.

This is required for batching the I/O requests.

Bug: 254188450
Test: Incremental OTA on Pixel (Tested legacy VAB as well)
Signed-off-by: Akilesh Kailash <akailash@google.com>
Change-Id: I5f04d88f720e86f5fcee1c775999c94226119270
diff --git a/payload_consumer/vabc_partition_writer.cc b/payload_consumer/vabc_partition_writer.cc
index 8ae0b51..c3b2e41 100644
--- a/payload_consumer/vabc_partition_writer.cc
+++ b/payload_consumer/vabc_partition_writer.cc
@@ -229,19 +229,30 @@
   for (const auto& cow_op : converted) {
     std::vector<uint8_t> buffer;
     switch (cow_op.op) {
-      case CowOperation::CowCopy:
+      case CowOperation::CowCopy: {
         if (cow_op.src_block == cow_op.dst_block) {
           continue;
         }
-        // Add blocks in reverse order, because snapused specifically prefers
-        // this ordering. Since we already eliminated all self-overlapping
-        // SOURCE_COPY during delta generation, this should be safe to do.
-        for (size_t i = cow_op.block_count; i > 0; i--) {
-          TEST_AND_RETURN_FALSE(cow_writer->AddCopy(cow_op.dst_block + i - 1,
-                                                    cow_op.src_block + i - 1));
+
+        const bool userSnapshots = android::base::GetBoolProperty(
+            "ro.virtual_ab.userspace.snapshots.enabled", false);
+
+        if (userSnapshots) {
+          TEST_AND_RETURN_FALSE(cow_op.block_count != 0);
+          TEST_AND_RETURN_FALSE(cow_writer->AddCopy(
+              cow_op.dst_block, cow_op.src_block, cow_op.block_count));
+        } else {
+          // Add blocks in reverse order, because snapused specifically prefers
+          // this ordering. Since we already eliminated all self-overlapping
+          // SOURCE_COPY during delta generation, this should be safe to do.
+          for (size_t i = cow_op.block_count; i > 0; i--) {
+            TEST_AND_RETURN_FALSE(cow_writer->AddCopy(
+                cow_op.dst_block + i - 1, cow_op.src_block + i - 1));
+          }
         }
         break;
-      case CowOperation::CowReplace:
+      }
+      case CowOperation::CowReplace: {
         buffer.resize(block_size * cow_op.block_count);
         ssize_t bytes_read = 0;
         TEST_AND_RETURN_FALSE(utils::ReadAll(source_fd,
@@ -257,6 +268,7 @@
         TEST_AND_RETURN_FALSE(cow_writer->AddRawBlocks(
             cow_op.dst_block, buffer.data(), buffer.size()));
         break;
+      }
     }
   }