DynamicPartitionControl: only create snapshot when snapshot_enabled

Do not create snapshot when applying downgrade
to non-Virtual-A/B packages and secondary OTAs.

Test: apply downgrade OTA on Virtual A/B devices

Bug: 138733621 (secondary OTA)
Fixes: 138258570 (downgrades)

Change-Id: I13318f57613d6bd60a5b7e81ebb3e35b3c225a0c
diff --git a/boot_control_android.cc b/boot_control_android.cc
index 4a010bd..b1d775e 100644
--- a/boot_control_android.cc
+++ b/boot_control_android.cc
@@ -308,12 +308,8 @@
     return true;
   }
 
-  if (!update_metadata) {
-    return true;
-  }
-
   return dynamic_control_->PreparePartitionsForUpdate(
-      source_slot, target_slot, manifest);
+      source_slot, target_slot, manifest, update_metadata);
 }
 
 }  // namespace chromeos_update_engine
diff --git a/boot_control_android_unittest.cc b/boot_control_android_unittest.cc
index f090de2..e44af15 100644
--- a/boot_control_android_unittest.cc
+++ b/boot_control_android_unittest.cc
@@ -197,6 +197,9 @@
                {T("system"), 2_GiB},
                {T("vendor"), 1_GiB}});
 
+  EXPECT_CALL(dynamicControl(), PreparePartitionsForUpdate(_, _, _, false))
+      .WillOnce(Return(true));
+
   EXPECT_TRUE(PreparePartitionsForUpdate(
       target(), {{"system", 2_GiB}, {"vendor", 1_GiB}}, false));
 
diff --git a/dynamic_partition_control_android.cc b/dynamic_partition_control_android.cc
index 8dcf343..88a787a 100644
--- a/dynamic_partition_control_android.cc
+++ b/dynamic_partition_control_android.cc
@@ -112,7 +112,8 @@
       .force_writable = force_writable,
   };
   bool success = false;
-  if (GetVirtualAbFeatureFlag().IsEnabled() && force_writable) {
+  if (GetVirtualAbFeatureFlag().IsEnabled() && target_supports_snapshot_ &&
+      force_writable) {
     // Only target partitions are mapped with force_writable. On Virtual
     // A/B devices, target partitions may overlap with source partitions, so
     // they must be mapped with snapshot.
@@ -343,11 +344,15 @@
 bool DynamicPartitionControlAndroid::PreparePartitionsForUpdate(
     uint32_t source_slot,
     uint32_t target_slot,
-    const DeltaArchiveManifest& manifest) {
-  // TODO(elsk): Also call PrepareDynamicPartitionsForUpdate when applying
-  // downgrade packages on retrofit Virtual A/B devices and when applying
-  // secondary OTA. b/138258570
-  if (GetVirtualAbFeatureFlag().IsEnabled()) {
+    const DeltaArchiveManifest& manifest,
+    bool update) {
+  target_supports_snapshot_ =
+      manifest.dynamic_partition_metadata().snapshot_enabled();
+
+  if (!update)
+    return true;
+
+  if (GetVirtualAbFeatureFlag().IsEnabled() && target_supports_snapshot_) {
     return PrepareSnapshotPartitionsForUpdate(
         source_slot, target_slot, manifest);
   }
@@ -491,10 +496,11 @@
 }
 
 bool DynamicPartitionControlAndroid::FinishUpdate() {
-  if (!GetVirtualAbFeatureFlag().IsEnabled())
-    return true;
-  LOG(INFO) << "Snapshot writes are done.";
-  return snapshot_->FinishedSnapshotWrites();
+  if (GetVirtualAbFeatureFlag().IsEnabled() && target_supports_snapshot_) {
+    LOG(INFO) << "Snapshot writes are done.";
+    return snapshot_->FinishedSnapshotWrites();
+  }
+  return true;
 }
 
 }  // namespace chromeos_update_engine
diff --git a/dynamic_partition_control_android.h b/dynamic_partition_control_android.h
index f9dfd89..35d8216 100644
--- a/dynamic_partition_control_android.h
+++ b/dynamic_partition_control_android.h
@@ -46,10 +46,10 @@
   std::unique_ptr<android::fs_mgr::MetadataBuilder> LoadMetadataBuilder(
       const std::string& super_device, uint32_t source_slot) override;
 
-  bool PreparePartitionsForUpdate(
-      uint32_t source_slot,
-      uint32_t target_slot,
-      const DeltaArchiveManifest& manifest) override;
+  bool PreparePartitionsForUpdate(uint32_t source_slot,
+                                  uint32_t target_slot,
+                                  const DeltaArchiveManifest& manifest,
+                                  bool update) override;
   bool GetDeviceDir(std::string* path) override;
   std::string GetSuperPartitionName(uint32_t slot) override;
   bool FinishUpdate() override;
@@ -113,6 +113,7 @@
 
   std::set<std::string> mapped_devices_;
   std::unique_ptr<android::snapshot::SnapshotManager> snapshot_;
+  bool target_supports_snapshot_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(DynamicPartitionControlAndroid);
 };
diff --git a/dynamic_partition_control_android_unittest.cc b/dynamic_partition_control_android_unittest.cc
index 552774e..e8ef1f9 100644
--- a/dynamic_partition_control_android_unittest.cc
+++ b/dynamic_partition_control_android_unittest.cc
@@ -112,7 +112,7 @@
   }
   bool PreparePartitionsForUpdate(const PartitionSizes& partition_sizes) {
     return dynamicControl().PreparePartitionsForUpdate(
-        source(), target(), PartitionSizesToManifest(partition_sizes));
+        source(), target(), PartitionSizesToManifest(partition_sizes), true);
   }
   void SetSlots(const TestParam& slots) { slots_ = slots; }
 
diff --git a/dynamic_partition_control_interface.h b/dynamic_partition_control_interface.h
index 0ccfcd6..9c4c2e8 100644
--- a/dynamic_partition_control_interface.h
+++ b/dynamic_partition_control_interface.h
@@ -92,10 +92,11 @@
   // Prepare all partitions for an update specified in |manifest|.
   // This is needed before calling MapPartitionOnDeviceMapper(), otherwise the
   // device would be mapped in an inconsistent way.
-  virtual bool PreparePartitionsForUpdate(
-      uint32_t source_slot,
-      uint32_t target_slot,
-      const DeltaArchiveManifest& manifest) = 0;
+  // If |update| is set, create snapshots and writes super partition metadata.
+  virtual bool PreparePartitionsForUpdate(uint32_t source_slot,
+                                          uint32_t target_slot,
+                                          const DeltaArchiveManifest& manifest,
+                                          bool update) = 0;
 
   // Return a possible location for devices listed by name.
   virtual bool GetDeviceDir(std::string* path) = 0;
diff --git a/mock_dynamic_partition_control.h b/mock_dynamic_partition_control.h
index 1af6cfe..8146e0f 100644
--- a/mock_dynamic_partition_control.h
+++ b/mock_dynamic_partition_control.h
@@ -44,8 +44,8 @@
                    const std::string&, uint32_t));
   MOCK_METHOD1(GetDeviceDir, bool(std::string*));
   MOCK_METHOD0(GetDynamicPartitionsFeatureFlag, FeatureFlag());
-  MOCK_METHOD3(PreparePartitionsForUpdate,
-               bool(uint32_t, uint32_t, const DeltaArchiveManifest&));
+  MOCK_METHOD4(PreparePartitionsForUpdate,
+               bool(uint32_t, uint32_t, const DeltaArchiveManifest&, bool));
   MOCK_METHOD1(GetSuperPartitionName, std::string(uint32_t));
   MOCK_METHOD0(GetVirtualAbFeatureFlag, FeatureFlag());
   MOCK_METHOD0(FinishUpdate, bool());