If the blocks are not overlapping, write
them in ascending order if userspace snapshots
are enabled.

Bug: 193863443
Test: OTA on pixel/CF
Signed-off-by: Akilesh Kailash <akailash@google.com>
Change-Id: Ic5719d1dc005ed88f739a642e4663fffccf7d795
diff --git a/payload_consumer/vabc_partition_writer.cc b/payload_consumer/vabc_partition_writer.cc
index ba0f484..a11bdf4 100644
--- a/payload_consumer/vabc_partition_writer.cc
+++ b/payload_consumer/vabc_partition_writer.cc
@@ -23,6 +23,7 @@
 #include <utility>
 #include <vector>
 
+#include <android-base/properties.h>
 #include <brillo/secure_blob.h>
 #include <libsnapshot/cow_writer.h>
 
@@ -167,20 +168,41 @@
         merge_op.src_extent() == merge_op.dst_extent()) {
       continue;
     }
-    // libsnapshot prefers blocks in reverse order, so if this isn't a self
-    // overlapping OP, writing block in reverser order
+
+    const bool extent_overlap =
+        ExtentRanges::ExtentsOverlap(src_extent, dst_extent);
+    // TODO(193863443) Remove this check once this feature
+    // lands on all pixel devices.
+    const bool is_ascending = android::base::GetBoolProperty(
+        "ro.virtual_ab.userspace.snapshots.enabled", false);
+
     // If this is a self-overlapping op and |dst_extent| comes after
     // |src_extent|, we must write in reverse order for correctness.
+    //
     // If this is self-overlapping op and |dst_extent| comes before
     // |src_extent|, we must write in ascending order for correctness.
-    if (ExtentRanges::ExtentsOverlap(src_extent, dst_extent) &&
-        dst_extent.start_block() <= src_extent.start_block()) {
-      for (size_t i = 0; i < dst_extent.num_blocks(); i++) {
-        blocks_merge_order.push_back(dst_extent.start_block() + i);
+    //
+    // If this isn't a self overlapping op, write block in ascending order
+    // if userspace snapshots are enabled
+    if (extent_overlap) {
+      if (dst_extent.start_block() <= src_extent.start_block()) {
+        for (size_t i = 0; i < dst_extent.num_blocks(); i++) {
+          blocks_merge_order.push_back(dst_extent.start_block() + i);
+        }
+      } else {
+        for (int i = dst_extent.num_blocks() - 1; i >= 0; i--) {
+          blocks_merge_order.push_back(dst_extent.start_block() + i);
+        }
       }
     } else {
-      for (int i = dst_extent.num_blocks() - 1; i >= 0; i--) {
-        blocks_merge_order.push_back(dst_extent.start_block() + i);
+      if (is_ascending) {
+        for (size_t i = 0; i < dst_extent.num_blocks(); i++) {
+          blocks_merge_order.push_back(dst_extent.start_block() + i);
+        }
+      } else {
+        for (int i = dst_extent.num_blocks() - 1; i >= 0; i--) {
+          blocks_merge_order.push_back(dst_extent.start_block() + i);
+        }
       }
     }
   }
diff --git a/payload_consumer/vabc_partition_writer_unittest.cc b/payload_consumer/vabc_partition_writer_unittest.cc
index fdfa0a6..f331091 100644
--- a/payload_consumer/vabc_partition_writer_unittest.cc
+++ b/payload_consumer/vabc_partition_writer_unittest.cc
@@ -18,6 +18,7 @@
 
 #include <android-base/file.h>
 #include <android-base/mapped_file.h>
+#include <android-base/properties.h>
 #include <bsdiff/bsdiff.h>
 #include <gtest/gtest.h>
 #include <libsnapshot/cow_writer.h>
@@ -200,11 +201,20 @@
             std::make_unique<android::snapshot::MockSnapshotWriter>(
                 android::snapshot::CowOptions{});
         ON_CALL(*cow_writer, EmitLabel(_)).WillByDefault(Return(true));
-        auto expected_merge_sequence = {11, 10, 14, 13};
+        auto expected_merge_sequence = {10, 11, 13, 14};
+        auto expected_merge_sequence_rev = {11, 10, 14, 13};
+        const bool is_ascending = android::base::GetBoolProperty(
+            "ro.virtual_ab.userspace.snapshots.enabled", false);
         ON_CALL(*cow_writer, Initialize()).WillByDefault(Return(true));
-        EXPECT_CALL(*cow_writer, EmitSequenceData(_, _))
-            .With(Args<1, 0>(ElementsAreArray(expected_merge_sequence)))
-            .WillOnce(Return(true));
+        if (!is_ascending) {
+          EXPECT_CALL(*cow_writer, EmitSequenceData(_, _))
+              .With(Args<1, 0>(ElementsAreArray(expected_merge_sequence_rev)))
+              .WillOnce(Return(true));
+        } else {
+          EXPECT_CALL(*cow_writer, EmitSequenceData(_, _))
+              .With(Args<1, 0>(ElementsAreArray(expected_merge_sequence)))
+              .WillOnce(Return(true));
+        }
         EXPECT_CALL(*cow_writer, Initialize()).Times(1);
         EXPECT_CALL(*cow_writer, EmitCopy(_, _)).Times(0);
         EXPECT_CALL(*cow_writer, EmitRawBlocks(_, _, _)).WillOnce(Return(true));