DeltaPerformer uses ShouldSkipOperation()

Enable DeltaPerformer request DynamicPartitionControl if a SOURCE_COPY
operation can be skip.
A SOURCE_COPY operation can still fail if its hash does not correspond
to the partition's.

Bug: 141207436
Test: manual OTA application
Change-Id: Ib3d8c9343acb4d3655781150a4cca57985f20387
Signed-off-by: Alessio Balsini <balsini@google.com>
diff --git a/payload_consumer/delta_performer.cc b/payload_consumer/delta_performer.cc
index f9244a9..3d38c5b 100644
--- a/payload_consumer/delta_performer.cc
+++ b/payload_consumer/delta_performer.cc
@@ -1154,7 +1154,14 @@
 
   TEST_AND_RETURN_FALSE(source_fd_ != nullptr);
 
+  // The device may optimize the SOURCE_COPY operation.
+  // Being this a device-specific optimization let DynamicPartitionController
+  // decide it the operation should be skipped.
+  const auto& partition_control = boot_control_->GetDynamicPartitionControl();
+  bool should_skip = partition_control->ShouldSkipOperation(operation);
+
   if (operation.has_src_sha256_hash()) {
+    bool read_ok;
     brillo::Blob source_hash;
     brillo::Blob expected_source_hash(operation.src_sha256_hash().begin(),
                                       operation.src_sha256_hash().end());
@@ -1163,12 +1170,17 @@
     // device doesn't match or there was an error reading the source partition.
     // Note that this code will also fall back if writing the target partition
     // fails.
-    bool read_ok = fd_utils::CopyAndHashExtents(source_fd_,
-                                                operation.src_extents(),
-                                                target_fd_,
-                                                operation.dst_extents(),
-                                                block_size_,
-                                                &source_hash);
+    if (should_skip) {
+      read_ok = fd_utils::ReadAndHashExtents(
+          source_fd_, operation.src_extents(), block_size_, &source_hash);
+    } else {
+      read_ok = fd_utils::CopyAndHashExtents(source_fd_,
+                                             operation.src_extents(),
+                                             target_fd_,
+                                             operation.dst_extents(),
+                                             block_size_,
+                                             &source_hash);
+    }
     if (read_ok && expected_source_hash == source_hash)
       return true;
 
@@ -1185,12 +1197,18 @@
                  << base::HexEncode(expected_source_hash.data(),
                                     expected_source_hash.size());
 
-    TEST_AND_RETURN_FALSE(fd_utils::CopyAndHashExtents(source_ecc_fd_,
-                                                       operation.src_extents(),
-                                                       target_fd_,
-                                                       operation.dst_extents(),
-                                                       block_size_,
-                                                       &source_hash));
+    if (should_skip) {
+      TEST_AND_RETURN_FALSE(fd_utils::ReadAndHashExtents(
+          source_ecc_fd_, operation.src_extents(), block_size_, &source_hash));
+    } else {
+      TEST_AND_RETURN_FALSE(
+          fd_utils::CopyAndHashExtents(source_ecc_fd_,
+                                       operation.src_extents(),
+                                       target_fd_,
+                                       operation.dst_extents(),
+                                       block_size_,
+                                       &source_hash));
+    }
     TEST_AND_RETURN_FALSE(
         ValidateSourceHash(source_hash, operation, source_ecc_fd_, error));
     // At this point reading from the the error corrected device worked, but
@@ -1202,6 +1220,10 @@
     // corrected device first since we can't verify the block in the raw device
     // at this point, but we fall back to the raw device since the error
     // corrected device can be shorter or not available.
+
+    if (should_skip)
+      return true;
+
     if (OpenCurrentECCPartition() &&
         fd_utils::CopyAndHashExtents(source_ecc_fd_,
                                      operation.src_extents(),