[REFACTOR] Pass DeltaArchiveManifest to DynamicPartitionControl

DynamicPartitionControl need the list of operations to calculate
COW sizes.

- Remove BootControlInterface::PartitionMetadata. Replace all references
  with DeltaArchiveManifest. DeltaArchiveManifest has all information
  that PartitionMetadata has.
- Rename all InitPartitionMetadata to PreparePartitionsForUpdate
- Change all PreparePartitionsForUpdate to use new signature
Bug: 138816109
Test: update_enigne_unittests --gtest_filter=*BootControl*:*Dynamic*
Change-Id: I4389ba2b1801addf8c3bc8395e2ea6a9a3ed27a0
diff --git a/boot_control_android.cc b/boot_control_android.cc
index ce86666..4c998b1 100644
--- a/boot_control_android.cc
+++ b/boot_control_android.cc
@@ -39,8 +39,6 @@
 using android::hardware::boot::V1_0::CommandResult;
 using android::hardware::boot::V1_0::IBootControl;
 using Slot = chromeos_update_engine::BootControlInterface::Slot;
-using PartitionMetadata =
-    chromeos_update_engine::BootControlInterface::PartitionMetadata;
 
 namespace {
 
@@ -277,9 +275,9 @@
          brillo::MessageLoop::kTaskIdNull;
 }
 
-bool BootControlAndroid::InitPartitionMetadata(
+bool BootControlAndroid::PreparePartitionsForUpdate(
     Slot target_slot,
-    const PartitionMetadata& partition_metadata,
+    const DeltaArchiveManifest& manifest,
     bool update_metadata) {
   if (fs_mgr_overlayfs_is_setup()) {
     // Non DAP devices can use overlayfs as well.
@@ -294,14 +292,14 @@
 
   auto source_slot = GetCurrentSlot();
   if (target_slot == source_slot) {
-    LOG(ERROR) << "Cannot call InitPartitionMetadata on current slot.";
+    LOG(ERROR) << "Cannot call PreparePartitionsForUpdate on current slot.";
     return false;
   }
 
   // Although the current build supports dynamic partitions, the given payload
   // doesn't use it for target partitions. This could happen when applying a
   // retrofit update. Skip updating the partition metadata for the target slot.
-  is_target_dynamic_ = !partition_metadata.groups.empty();
+  is_target_dynamic_ = !manifest.dynamic_partition_metadata().groups().empty();
   if (!is_target_dynamic_) {
     return true;
   }
@@ -311,7 +309,7 @@
   }
 
   return dynamic_control_->PreparePartitionsForUpdate(
-      source_slot, target_slot, partition_metadata);
+      source_slot, target_slot, manifest);
 }
 
 }  // namespace chromeos_update_engine
diff --git a/boot_control_android.h b/boot_control_android.h
index a6f33be..65543ca 100644
--- a/boot_control_android.h
+++ b/boot_control_android.h
@@ -51,9 +51,9 @@
   bool MarkSlotUnbootable(BootControlInterface::Slot slot) override;
   bool SetActiveBootSlot(BootControlInterface::Slot slot) override;
   bool MarkBootSuccessfulAsync(base::Callback<void(bool)> callback) override;
-  bool InitPartitionMetadata(Slot slot,
-                             const PartitionMetadata& partition_metadata,
-                             bool update_metadata) override;
+  bool PreparePartitionsForUpdate(Slot slot,
+                                  const DeltaArchiveManifest& manifest,
+                                  bool update_metadata) override;
   void Cleanup() override;
 
  private:
@@ -84,7 +84,7 @@
                           const std::string& partition_name_suffix) const;
 
   // Whether the target partitions should be loaded as dynamic partitions. Set
-  // by InitPartitionMetadata() per each update.
+  // by PreparePartitionsForUpdate() per each update.
   bool is_target_dynamic_{false};
 
   DISALLOW_COPY_AND_ASSIGN(BootControlAndroid);
diff --git a/boot_control_android_unittest.cc b/boot_control_android_unittest.cc
index 3b92191..f090de2 100644
--- a/boot_control_android_unittest.cc
+++ b/boot_control_android_unittest.cc
@@ -102,7 +102,7 @@
                 LoadMetadataBuilder(GetSuperDevice(slot), slot))
         .Times(AnyNumber())
         .WillRepeatedly(Invoke([sizes](auto, auto) {
-          return NewFakeMetadata(PartitionSuffixSizesToMetadata(sizes));
+          return NewFakeMetadata(PartitionSuffixSizesToManifest(sizes));
         }));
   }
 
@@ -125,11 +125,11 @@
     }));
   }
 
-  bool InitPartitionMetadata(uint32_t slot,
-                             PartitionSizes partition_sizes,
-                             bool update_metadata = true) {
-    auto m = PartitionSizesToMetadata(partition_sizes);
-    return bootctl_.InitPartitionMetadata(slot, m, update_metadata);
+  bool PreparePartitionsForUpdate(uint32_t slot,
+                                  PartitionSizes partition_sizes,
+                                  bool update_metadata = true) {
+    auto m = PartitionSizesToManifest(partition_sizes);
+    return bootctl_.PreparePartitionsForUpdate(slot, m, update_metadata);
   }
 
   BootControlAndroid bootctl_;  // BootControlAndroid under test.
@@ -155,9 +155,9 @@
                {T("system"), 2_GiB},
                {T("vendor"), 1_GiB}});
 
-  // Not calling through BootControlAndroidTest::InitPartitionMetadata(), since
-  // we don't want any default group in the PartitionMetadata.
-  EXPECT_TRUE(bootctl_.InitPartitionMetadata(target(), {}, true));
+  // Not calling through BootControlAndroidTest::PreparePartitionsForUpdate(),
+  // since we don't want any default group in the PartitionMetadata.
+  EXPECT_TRUE(bootctl_.PreparePartitionsForUpdate(target(), {}, true));
 
   // Should use dynamic source partitions.
   EXPECT_CALL(dynamicControl(), GetState(S("system")))
@@ -197,7 +197,7 @@
                {T("system"), 2_GiB},
                {T("vendor"), 1_GiB}});
 
-  EXPECT_TRUE(InitPartitionMetadata(
+  EXPECT_TRUE(PreparePartitionsForUpdate(
       target(), {{"system", 2_GiB}, {"vendor", 1_GiB}}, false));
 
   // Dynamic partition "system".
@@ -240,7 +240,7 @@
 
 TEST_F(BootControlAndroidTest, ApplyingToCurrentSlot) {
   SetSlots({1, 1});
-  EXPECT_FALSE(InitPartitionMetadata(target(), {}))
+  EXPECT_FALSE(PreparePartitionsForUpdate(target(), {}))
       << "Should not be able to apply to current slot.";
 }
 
diff --git a/boot_control_chromeos.cc b/boot_control_chromeos.cc
index ccba316..7e748d5 100644
--- a/boot_control_chromeos.cc
+++ b/boot_control_chromeos.cc
@@ -326,10 +326,8 @@
   return -1;
 }
 
-bool BootControlChromeOS::InitPartitionMetadata(
-    Slot slot,
-    const PartitionMetadata& partition_metadata,
-    bool update_metadata) {
+bool BootControlChromeOS::PreparePartitionsForUpdate(
+    Slot slot, const DeltaArchiveManifest& manifest, bool update_metadata) {
   return true;
 }
 
diff --git a/boot_control_chromeos.h b/boot_control_chromeos.h
index f3682e9..29841c9 100644
--- a/boot_control_chromeos.h
+++ b/boot_control_chromeos.h
@@ -50,9 +50,9 @@
   bool MarkSlotUnbootable(BootControlInterface::Slot slot) override;
   bool SetActiveBootSlot(BootControlInterface::Slot slot) override;
   bool MarkBootSuccessfulAsync(base::Callback<void(bool)> callback) override;
-  bool InitPartitionMetadata(Slot slot,
-                             const PartitionMetadata& partition_metadata,
-                             bool update_metadata) override;
+  bool PreparePartitionsForUpdate(Slot slot,
+                                  const DeltaArchiveManifest& manifest,
+                                  bool update_metadata) override;
   void Cleanup() override;
 
  private:
diff --git a/common/boot_control_interface.h b/common/boot_control_interface.h
index 392d785..9bf639a 100644
--- a/common/boot_control_interface.h
+++ b/common/boot_control_interface.h
@@ -25,6 +25,8 @@
 #include <base/callback.h>
 #include <base/macros.h>
 
+#include "update_engine/update_metadata.pb.h"
+
 namespace chromeos_update_engine {
 
 // The abstract boot control interface defines the interaction with the
@@ -35,19 +37,6 @@
  public:
   using Slot = unsigned int;
 
-  struct PartitionMetadata {
-    struct Partition {
-      std::string name;
-      uint64_t size;
-    };
-    struct Group {
-      std::string name;
-      uint64_t size;
-      std::vector<Partition> partitions;
-    };
-    std::vector<Group> groups;
-  };
-
   static const Slot kInvalidSlot = UINT_MAX;
 
   virtual ~BootControlInterface() = default;
@@ -67,9 +56,9 @@
   // The |slot| number must be between 0 and GetNumSlots() - 1 and the
   // |partition_name| is a platform-specific name that identifies a partition on
   // every slot. In order to access the dynamic partitions in the target slot,
-  // InitPartitionMetadata() must be called (once per payload) prior to calling
-  // this function. On success, returns true and stores the block device in
-  // |device|.
+  // PreparePartitionsForUpdate() must be called (once per payload) prior to
+  // calling this function. On success, returns true and stores the block device
+  // in |device|.
   virtual bool GetPartitionDevice(const std::string& partition_name,
                                   Slot slot,
                                   std::string* device) const = 0;
@@ -96,12 +85,11 @@
 
   // Initializes the metadata of the underlying partitions for a given |slot|
   // and sets up the states for accessing dynamic partitions.
-  // |partition_metadata| will be written to the specified |slot| if
+  // Metadata will be written to the specified |slot| if
   // |update_metadata| is set.
-  virtual bool InitPartitionMetadata(
-      Slot slot,
-      const PartitionMetadata& partition_metadata,
-      bool update_metadata) = 0;
+  virtual bool PreparePartitionsForUpdate(Slot slot,
+                                          const DeltaArchiveManifest& manifest,
+                                          bool update_metadata) = 0;
 
   // Do necessary clean-up operations after the whole update.
   virtual void Cleanup() = 0;
diff --git a/common/boot_control_stub.cc b/common/boot_control_stub.cc
index 0fe8a98..b10e82f 100644
--- a/common/boot_control_stub.cc
+++ b/common/boot_control_stub.cc
@@ -59,10 +59,8 @@
   return false;
 }
 
-bool BootControlStub::InitPartitionMetadata(
-    Slot slot,
-    const PartitionMetadata& partition_metadata,
-    bool update_metadata) {
+bool BootControlStub::PreparePartitionsForUpdate(
+    Slot slot, const DeltaArchiveManifest& manifest, bool update_metadata) {
   LOG(ERROR) << __FUNCTION__ << " should never be called.";
   return false;
 }
diff --git a/common/boot_control_stub.h b/common/boot_control_stub.h
index 8dfaffc..f2973a2 100644
--- a/common/boot_control_stub.h
+++ b/common/boot_control_stub.h
@@ -45,9 +45,9 @@
   bool MarkSlotUnbootable(BootControlInterface::Slot slot) override;
   bool SetActiveBootSlot(BootControlInterface::Slot slot) override;
   bool MarkBootSuccessfulAsync(base::Callback<void(bool)> callback) override;
-  bool InitPartitionMetadata(Slot slot,
-                             const PartitionMetadata& partition_metadata,
-                             bool update_metadata) override;
+  bool PreparePartitionsForUpdate(Slot slot,
+                                  const DeltaArchiveManifest& manifest,
+                                  bool update_metadata) override;
   void Cleanup() override;
 
  private:
diff --git a/common/fake_boot_control.h b/common/fake_boot_control.h
index 3d65075..11810d1 100644
--- a/common/fake_boot_control.h
+++ b/common/fake_boot_control.h
@@ -74,9 +74,9 @@
     return true;
   }
 
-  bool InitPartitionMetadata(Slot slot,
-                             const PartitionMetadata& partition_metadata,
-                             bool update_metadata) override {
+  bool PreparePartitionsForUpdate(Slot slot,
+                                  const DeltaArchiveManifest& manifest,
+                                  bool update_metadata) override {
     return true;
   }
 
diff --git a/dynamic_partition_control_android.cc b/dynamic_partition_control_android.cc
index b973232..e351dbd 100644
--- a/dynamic_partition_control_android.cc
+++ b/dynamic_partition_control_android.cc
@@ -16,6 +16,7 @@
 
 #include "update_engine/dynamic_partition_control_android.h"
 
+#include <map>
 #include <memory>
 #include <set>
 #include <string>
@@ -48,8 +49,6 @@
 
 namespace chromeos_update_engine {
 
-using PartitionMetadata = BootControlInterface::PartitionMetadata;
-
 constexpr char kUseDynamicPartitions[] = "ro.boot.dynamic_partitions";
 constexpr char kRetrfoitDynamicPartitions[] =
     "ro.boot.dynamic_partitions_retrofit";
@@ -309,14 +308,14 @@
 bool DynamicPartitionControlAndroid::PreparePartitionsForUpdate(
     uint32_t source_slot,
     uint32_t target_slot,
-    const PartitionMetadata& partition_metadata) {
+    const DeltaArchiveManifest& manifest) {
   const std::string target_suffix = SlotSuffixForSlotNumber(target_slot);
 
   // Unmap all the target dynamic partitions because they would become
   // inconsistent with the new metadata.
-  for (const auto& group : partition_metadata.groups) {
-    for (const auto& partition : group.partitions) {
-      if (!UnmapPartitionOnDeviceMapper(partition.name + target_suffix)) {
+  for (const auto& group : manifest.dynamic_partition_metadata().groups()) {
+    for (const auto& partition_name : group.partition_names()) {
+      if (!UnmapPartitionOnDeviceMapper(partition_name + target_suffix)) {
         return false;
       }
     }
@@ -337,8 +336,7 @@
     return false;
   }
 
-  if (!UpdatePartitionMetadata(
-          builder.get(), target_slot, partition_metadata)) {
+  if (!UpdatePartitionMetadata(builder.get(), target_slot, manifest)) {
     return false;
   }
 
@@ -355,13 +353,13 @@
 bool DynamicPartitionControlAndroid::UpdatePartitionMetadata(
     MetadataBuilder* builder,
     uint32_t target_slot,
-    const PartitionMetadata& partition_metadata) {
+    const DeltaArchiveManifest& manifest) {
   const std::string target_suffix = SlotSuffixForSlotNumber(target_slot);
   DeleteGroupsWithSuffix(builder, target_suffix);
 
   uint64_t total_size = 0;
-  for (const auto& group : partition_metadata.groups) {
-    total_size += group.size;
+  for (const auto& group : manifest.dynamic_partition_metadata().groups()) {
+    total_size += group.size();
   }
 
   std::string expr;
@@ -378,18 +376,36 @@
     return false;
   }
 
-  for (const auto& group : partition_metadata.groups) {
-    auto group_name_suffix = group.name + target_suffix;
-    if (!builder->AddGroup(group_name_suffix, group.size)) {
+  // name of partition(e.g. "system") -> size in bytes
+  std::map<std::string, uint64_t> partition_sizes;
+  for (const auto& partition : manifest.partitions()) {
+    partition_sizes.emplace(partition.partition_name(),
+                            partition.new_partition_info().size());
+  }
+
+  for (const auto& group : manifest.dynamic_partition_metadata().groups()) {
+    auto group_name_suffix = group.name() + target_suffix;
+    if (!builder->AddGroup(group_name_suffix, group.size())) {
       LOG(ERROR) << "Cannot add group " << group_name_suffix << " with size "
-                 << group.size;
+                 << group.size();
       return false;
     }
     LOG(INFO) << "Added group " << group_name_suffix << " with size "
-              << group.size;
+              << group.size();
 
-    for (const auto& partition : group.partitions) {
-      auto partition_name_suffix = partition.name + target_suffix;
+    for (const auto& partition_name : group.partition_names()) {
+      auto partition_sizes_it = partition_sizes.find(partition_name);
+      if (partition_sizes_it == partition_sizes.end()) {
+        // TODO(tbao): Support auto-filling partition info for framework-only
+        // OTA.
+        LOG(ERROR) << "dynamic_partition_metadata contains partition "
+                   << partition_name << " but it is not part of the manifest. "
+                   << "This is not supported.";
+        return false;
+      }
+      uint64_t partition_size = partition_sizes_it->second;
+
+      auto partition_name_suffix = partition_name + target_suffix;
       Partition* p = builder->AddPartition(
           partition_name_suffix, group_name_suffix, LP_PARTITION_ATTR_READONLY);
       if (!p) {
@@ -397,13 +413,13 @@
                    << " to group " << group_name_suffix;
         return false;
       }
-      if (!builder->ResizePartition(p, partition.size)) {
+      if (!builder->ResizePartition(p, partition_size)) {
         LOG(ERROR) << "Cannot resize partition " << partition_name_suffix
-                   << " to size " << partition.size << ". Not enough space?";
+                   << " to size " << partition_size << ". Not enough space?";
         return false;
       }
       LOG(INFO) << "Added partition " << partition_name_suffix << " to group "
-                << group_name_suffix << " with size " << partition.size;
+                << group_name_suffix << " with size " << partition_size;
     }
   }
 
diff --git a/dynamic_partition_control_android.h b/dynamic_partition_control_android.h
index d743e6e..0907236 100644
--- a/dynamic_partition_control_android.h
+++ b/dynamic_partition_control_android.h
@@ -44,10 +44,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 BootControlInterface::PartitionMetadata&
-                                      partition_metadata) override;
+  bool PreparePartitionsForUpdate(
+      uint32_t source_slot,
+      uint32_t target_slot,
+      const DeltaArchiveManifest& manifest) override;
   bool GetDeviceDir(std::string* path) override;
   std::string GetSuperPartitionName(uint32_t slot) override;
 
@@ -94,10 +94,9 @@
 
   // Update |builder| according to |partition_metadata|, assuming the device
   // does not have Virtual A/B.
-  bool UpdatePartitionMetadata(
-      android::fs_mgr::MetadataBuilder* builder,
-      uint32_t target_slot,
-      const BootControlInterface::PartitionMetadata& partition_metadata);
+  bool UpdatePartitionMetadata(android::fs_mgr::MetadataBuilder* builder,
+                               uint32_t target_slot,
+                               const DeltaArchiveManifest& manifest);
 
   DISALLOW_COPY_AND_ASSIGN(DynamicPartitionControlAndroid);
 };
diff --git a/dynamic_partition_control_android_unittest.cc b/dynamic_partition_control_android_unittest.cc
index 1a3f664..552774e 100644
--- a/dynamic_partition_control_android_unittest.cc
+++ b/dynamic_partition_control_android_unittest.cc
@@ -86,7 +86,7 @@
                 LoadMetadataBuilder(GetSuperDevice(slot), slot, _))
         .Times(AnyNumber())
         .WillRepeatedly(Invoke([sizes](auto, auto, auto) {
-          return NewFakeMetadata(PartitionSuffixSizesToMetadata(sizes));
+          return NewFakeMetadata(PartitionSuffixSizesToManifest(sizes));
         }));
   }
 
@@ -112,7 +112,7 @@
   }
   bool PreparePartitionsForUpdate(const PartitionSizes& partition_sizes) {
     return dynamicControl().PreparePartitionsForUpdate(
-        source(), target(), PartitionSizesToMetadata(partition_sizes));
+        source(), target(), PartitionSizesToManifest(partition_sizes));
   }
   void SetSlots(const TestParam& slots) { slots_ = slots; }
 
@@ -125,24 +125,24 @@
       const PartitionSizes& update_metadata,
       const PartitionSuffixSizes& expected) {
     return UpdatePartitionMetadata(
-        PartitionSuffixSizesToMetadata(source_metadata),
-        PartitionSizesToMetadata(update_metadata),
-        PartitionSuffixSizesToMetadata(expected));
+        PartitionSuffixSizesToManifest(source_metadata),
+        PartitionSizesToManifest(update_metadata),
+        PartitionSuffixSizesToManifest(expected));
   }
   testing::AssertionResult UpdatePartitionMetadata(
-      const PartitionMetadata& source_metadata,
-      const PartitionMetadata& update_metadata,
-      const PartitionMetadata& expected) {
+      const DeltaArchiveManifest& source_manifest,
+      const DeltaArchiveManifest& update_manifest,
+      const DeltaArchiveManifest& expected) {
     return UpdatePartitionMetadata(
-        source_metadata, update_metadata, MetadataMatches(expected));
+        source_manifest, update_manifest, MetadataMatches(expected));
   }
   testing::AssertionResult UpdatePartitionMetadata(
-      const PartitionMetadata& source_metadata,
-      const PartitionMetadata& update_metadata,
+      const DeltaArchiveManifest& source_manifest,
+      const DeltaArchiveManifest& update_manifest,
       const Matcher<MetadataBuilder*>& matcher) {
-    auto super_metadata = NewFakeMetadata(source_metadata);
+    auto super_metadata = NewFakeMetadata(source_manifest);
     if (!module_->UpdatePartitionMetadata(
-            super_metadata.get(), target(), update_metadata)) {
+            super_metadata.get(), target(), update_manifest)) {
       return testing::AssertionFailure()
              << "UpdatePartitionMetadataInternal failed";
     }
@@ -290,112 +290,115 @@
 class DynamicPartitionControlAndroidGroupTestP
     : public DynamicPartitionControlAndroidTestP {
  public:
-  PartitionMetadata source_metadata;
+  DeltaArchiveManifest source_manifest;
   void SetUp() override {
     DynamicPartitionControlAndroidTestP::SetUp();
-    source_metadata = {
-        .groups = {SimpleGroup(S("android"), 3_GiB, S("system"), 2_GiB),
-                   SimpleGroup(S("oem"), 2_GiB, S("vendor"), 1_GiB),
-                   SimpleGroup(T("android"), 3_GiB, T("system"), 0),
-                   SimpleGroup(T("oem"), 2_GiB, T("vendor"), 0)}};
+    AddGroupAndPartition(
+        &source_manifest, S("android"), 3_GiB, S("system"), 2_GiB);
+    AddGroupAndPartition(&source_manifest, S("oem"), 2_GiB, S("vendor"), 1_GiB);
+    AddGroupAndPartition(&source_manifest, T("android"), 3_GiB, T("system"), 0);
+    AddGroupAndPartition(&source_manifest, T("oem"), 2_GiB, T("vendor"), 0);
   }
 
-  // Return a simple group with only one partition.
-  PartitionMetadata::Group SimpleGroup(const string& group,
-                                       uint64_t group_size,
-                                       const string& partition,
-                                       uint64_t partition_size) {
-    return {.name = group,
-            .size = group_size,
-            .partitions = {{.name = partition, .size = partition_size}}};
+  void AddGroupAndPartition(DeltaArchiveManifest* manifest,
+                            const string& group,
+                            uint64_t group_size,
+                            const string& partition,
+                            uint64_t partition_size) {
+    auto* g = AddGroup(manifest, group, group_size);
+    AddPartition(manifest, g, partition, partition_size);
   }
 };
 
 // Allow to resize within group.
 TEST_P(DynamicPartitionControlAndroidGroupTestP, ResizeWithinGroup) {
-  PartitionMetadata expected{
-      .groups = {SimpleGroup(T("android"), 3_GiB, T("system"), 3_GiB),
-                 SimpleGroup(T("oem"), 2_GiB, T("vendor"), 2_GiB)}};
+  DeltaArchiveManifest expected;
+  AddGroupAndPartition(&expected, T("android"), 3_GiB, T("system"), 3_GiB);
+  AddGroupAndPartition(&expected, T("oem"), 2_GiB, T("vendor"), 2_GiB);
 
-  PartitionMetadata update_metadata{
-      .groups = {SimpleGroup("android", 3_GiB, "system", 3_GiB),
-                 SimpleGroup("oem", 2_GiB, "vendor", 2_GiB)}};
+  DeltaArchiveManifest update_manifest;
+  AddGroupAndPartition(&update_manifest, "android", 3_GiB, "system", 3_GiB);
+  AddGroupAndPartition(&update_manifest, "oem", 2_GiB, "vendor", 2_GiB);
 
   EXPECT_TRUE(
-      UpdatePartitionMetadata(source_metadata, update_metadata, expected));
+      UpdatePartitionMetadata(source_manifest, update_manifest, expected));
 }
 
 TEST_P(DynamicPartitionControlAndroidGroupTestP, NotEnoughSpaceForGroup) {
-  PartitionMetadata update_metadata{
-      .groups = {SimpleGroup("android", 3_GiB, "system", 1_GiB),
-                 SimpleGroup("oem", 2_GiB, "vendor", 3_GiB)}};
-  EXPECT_FALSE(UpdatePartitionMetadata(source_metadata, update_metadata, {}))
+  DeltaArchiveManifest update_manifest;
+  AddGroupAndPartition(&update_manifest, "android", 3_GiB, "system", 1_GiB),
+      AddGroupAndPartition(&update_manifest, "oem", 2_GiB, "vendor", 3_GiB);
+  EXPECT_FALSE(UpdatePartitionMetadata(source_manifest, update_manifest, {}))
       << "Should not be able to grow over maximum size of group";
 }
 
 TEST_P(DynamicPartitionControlAndroidGroupTestP, GroupTooBig) {
-  PartitionMetadata update_metadata{
-      .groups = {{.name = "android", .size = 3_GiB},
-                 {.name = "oem", .size = 3_GiB}}};
-  EXPECT_FALSE(UpdatePartitionMetadata(source_metadata, update_metadata, {}))
+  DeltaArchiveManifest update_manifest;
+  AddGroup(&update_manifest, "android", 3_GiB);
+  AddGroup(&update_manifest, "oem", 3_GiB);
+  EXPECT_FALSE(UpdatePartitionMetadata(source_manifest, update_manifest, {}))
       << "Should not be able to grow over size of super / 2";
 }
 
 TEST_P(DynamicPartitionControlAndroidGroupTestP, AddPartitionToGroup) {
-  PartitionMetadata expected{
-      .groups = {{.name = T("android"),
-                  .size = 3_GiB,
-                  .partitions = {{.name = T("system"), .size = 2_GiB},
-                                 {.name = T("system_ext"), .size = 1_GiB}}}}};
-  PartitionMetadata update_metadata{
-      .groups = {{.name = "android",
-                  .size = 3_GiB,
-                  .partitions = {{.name = "system", .size = 2_GiB},
-                                 {.name = "system_ext", .size = 1_GiB}}},
-                 SimpleGroup("oem", 2_GiB, "vendor", 2_GiB)}};
+  DeltaArchiveManifest expected;
+  auto* g = AddGroup(&expected, T("android"), 3_GiB);
+  AddPartition(&expected, g, T("system"), 2_GiB);
+  AddPartition(&expected, g, T("system_ext"), 1_GiB);
+
+  DeltaArchiveManifest update_manifest;
+  g = AddGroup(&update_manifest, "android", 3_GiB);
+  AddPartition(&update_manifest, g, "system", 2_GiB);
+  AddPartition(&update_manifest, g, "system_ext", 1_GiB);
+  AddGroupAndPartition(&update_manifest, "oem", 2_GiB, "vendor", 2_GiB);
+
   EXPECT_TRUE(
-      UpdatePartitionMetadata(source_metadata, update_metadata, expected));
+      UpdatePartitionMetadata(source_manifest, update_manifest, expected));
 }
 
 TEST_P(DynamicPartitionControlAndroidGroupTestP, RemovePartitionFromGroup) {
-  PartitionMetadata expected{
-      .groups = {{.name = T("android"), .size = 3_GiB, .partitions = {}}}};
-  PartitionMetadata update_metadata{
-      .groups = {{.name = "android", .size = 3_GiB, .partitions = {}},
-                 SimpleGroup("oem", 2_GiB, "vendor", 2_GiB)}};
+  DeltaArchiveManifest expected;
+  AddGroup(&expected, T("android"), 3_GiB);
+
+  DeltaArchiveManifest update_manifest;
+  AddGroup(&update_manifest, "android", 3_GiB);
+  AddGroupAndPartition(&update_manifest, "oem", 2_GiB, "vendor", 2_GiB);
+
   EXPECT_TRUE(
-      UpdatePartitionMetadata(source_metadata, update_metadata, expected));
+      UpdatePartitionMetadata(source_manifest, update_manifest, expected));
 }
 
 TEST_P(DynamicPartitionControlAndroidGroupTestP, AddGroup) {
-  PartitionMetadata expected{
-      .groups = {
-          SimpleGroup(T("new_group"), 2_GiB, T("new_partition"), 2_GiB)}};
-  PartitionMetadata update_metadata{
-      .groups = {SimpleGroup("android", 2_GiB, "system", 2_GiB),
-                 SimpleGroup("oem", 1_GiB, "vendor", 1_GiB),
-                 SimpleGroup("new_group", 2_GiB, "new_partition", 2_GiB)}};
+  DeltaArchiveManifest expected;
+  AddGroupAndPartition(
+      &expected, T("new_group"), 2_GiB, T("new_partition"), 2_GiB);
+
+  DeltaArchiveManifest update_manifest;
+  AddGroupAndPartition(&update_manifest, "android", 2_GiB, "system", 2_GiB);
+  AddGroupAndPartition(&update_manifest, "oem", 1_GiB, "vendor", 1_GiB);
+  AddGroupAndPartition(
+      &update_manifest, "new_group", 2_GiB, "new_partition", 2_GiB);
   EXPECT_TRUE(
-      UpdatePartitionMetadata(source_metadata, update_metadata, expected));
+      UpdatePartitionMetadata(source_manifest, update_manifest, expected));
 }
 
 TEST_P(DynamicPartitionControlAndroidGroupTestP, RemoveGroup) {
-  PartitionMetadata update_metadata{
-      .groups = {SimpleGroup("android", 2_GiB, "system", 2_GiB)}};
+  DeltaArchiveManifest update_manifest;
+  AddGroupAndPartition(&update_manifest, "android", 2_GiB, "system", 2_GiB);
 
   EXPECT_TRUE(UpdatePartitionMetadata(
-      source_metadata, update_metadata, Not(HasGroup(T("oem")))));
+      source_manifest, update_manifest, Not(HasGroup(T("oem")))));
 }
 
 TEST_P(DynamicPartitionControlAndroidGroupTestP, ResizeGroup) {
-  PartitionMetadata expected{
-      .groups = {SimpleGroup(T("android"), 2_GiB, T("system"), 2_GiB),
-                 SimpleGroup(T("oem"), 3_GiB, T("vendor"), 3_GiB)}};
-  PartitionMetadata update_metadata{
-      .groups = {SimpleGroup("android", 2_GiB, "system", 2_GiB),
-                 SimpleGroup("oem", 3_GiB, "vendor", 3_GiB)}};
+  DeltaArchiveManifest expected;
+  AddGroupAndPartition(&expected, T("android"), 2_GiB, T("system"), 2_GiB);
+  AddGroupAndPartition(&expected, T("oem"), 3_GiB, T("vendor"), 3_GiB);
+  DeltaArchiveManifest update_manifest;
+  AddGroupAndPartition(&update_manifest, "android", 2_GiB, "system", 2_GiB),
+      AddGroupAndPartition(&update_manifest, "oem", 3_GiB, "vendor", 3_GiB);
   EXPECT_TRUE(
-      UpdatePartitionMetadata(source_metadata, update_metadata, expected));
+      UpdatePartitionMetadata(source_manifest, update_manifest, expected));
 }
 
 INSTANTIATE_TEST_CASE_P(DynamicPartitionControlAndroidTest,
diff --git a/dynamic_partition_control_interface.h b/dynamic_partition_control_interface.h
index 9c7b8d0..a4dc576 100644
--- a/dynamic_partition_control_interface.h
+++ b/dynamic_partition_control_interface.h
@@ -27,6 +27,7 @@
 #include <liblp/builder.h>
 
 #include "update_engine/common/boot_control_interface.h"
+#include "update_engine/update_metadata.pb.h"
 
 namespace chromeos_update_engine {
 
@@ -88,13 +89,13 @@
   virtual std::unique_ptr<android::fs_mgr::MetadataBuilder> LoadMetadataBuilder(
       const std::string& super_device, uint32_t source_slot) = 0;
 
-  // Prepare all partitions for an update specified in |partition_metadata|.
+  // 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 BootControlInterface::PartitionMetadata& partition_metadata) = 0;
+      const DeltaArchiveManifest& manifest) = 0;
 
   // Return a possible location for devices listed by name.
   virtual bool GetDeviceDir(std::string* path) = 0;
diff --git a/dynamic_partition_test_utils.h b/dynamic_partition_test_utils.h
index 61d8e0a..346998f 100644
--- a/dynamic_partition_test_utils.h
+++ b/dynamic_partition_test_utils.h
@@ -33,6 +33,7 @@
 #include <storage_literals/storage_literals.h>
 
 #include "update_engine/common/boot_control_interface.h"
+#include "update_engine/update_metadata.pb.h"
 
 namespace chromeos_update_engine {
 
@@ -59,8 +60,6 @@
 // "{name_a, size}"
 using PartitionSuffixSizes = std::map<std::string, uint64_t>;
 
-using PartitionMetadata = BootControlInterface::PartitionMetadata;
-
 constexpr uint64_t kDefaultGroupSize = 5_GiB;
 // Super device size. 1 MiB for metadata.
 constexpr uint64_t kDefaultSuperSize = kDefaultGroupSize * 2 + 1_MiB;
@@ -78,8 +77,8 @@
   return os << "}";
 }
 
-template <typename T>
-inline std::ostream& operator<<(std::ostream& os, const std::vector<T>& param) {
+template <typename V>
+inline void VectorToStream(std::ostream& os, const V& param) {
   os << "[";
   bool first = true;
   for (const auto& e : param) {
@@ -88,21 +87,28 @@
     os << e;
     first = false;
   }
-  return os << "]";
+  os << "]";
+}
+
+inline std::ostream& operator<<(std::ostream& os, const PartitionUpdate& p) {
+  return os << "{" << p.partition_name() << ", "
+            << p.new_partition_info().size() << "}";
 }
 
 inline std::ostream& operator<<(std::ostream& os,
-                                const PartitionMetadata::Partition& p) {
-  return os << "{" << p.name << ", " << p.size << "}";
+                                const DynamicPartitionGroup& g) {
+  os << "{" << g.name() << ", " << g.size() << ", ";
+  VectorToStream(os, g.partition_names());
+  return os << "}";
 }
 
 inline std::ostream& operator<<(std::ostream& os,
-                                const PartitionMetadata::Group& g) {
-  return os << "{" << g.name << ", " << g.size << ", " << g.partitions << "}";
-}
-
-inline std::ostream& operator<<(std::ostream& os, const PartitionMetadata& m) {
-  return os << m.groups;
+                                const DeltaArchiveManifest& m) {
+  os << "{.groups = ";
+  VectorToStream(os, m.dynamic_partition_metadata().groups());
+  os << ", .partitions = ";
+  VectorToStream(os, m.partitions());
+  return os;
 }
 
 inline std::string GetDevice(const std::string& name) {
@@ -113,90 +119,125 @@
   return kFakeDmDevicePath + name;
 }
 
+inline DynamicPartitionGroup* AddGroup(DeltaArchiveManifest* manifest,
+                                       const std::string& group,
+                                       uint64_t group_size) {
+  auto* g = manifest->mutable_dynamic_partition_metadata()->add_groups();
+  g->set_name(group);
+  g->set_size(group_size);
+  return g;
+}
+
+inline void AddPartition(DeltaArchiveManifest* manifest,
+                         DynamicPartitionGroup* group,
+                         const std::string& partition,
+                         uint64_t partition_size) {
+  group->add_partition_names(partition);
+  auto* p = manifest->add_partitions();
+  p->set_partition_name(partition);
+  p->mutable_new_partition_info()->set_size(partition_size);
+}
+
 // To support legacy tests, auto-convert {name_a: size} map to
-// PartitionMetadata.
-inline PartitionMetadata PartitionSuffixSizesToMetadata(
+// DeltaArchiveManifest.
+inline DeltaArchiveManifest PartitionSuffixSizesToManifest(
     const PartitionSuffixSizes& partition_sizes) {
-  PartitionMetadata metadata;
+  DeltaArchiveManifest manifest;
   for (const char* suffix : kSlotSuffixes) {
-    metadata.groups.push_back(
-        {std::string(kDefaultGroup) + suffix, kDefaultGroupSize, {}});
+    AddGroup(&manifest, std::string(kDefaultGroup) + suffix, kDefaultGroupSize);
   }
   for (const auto& pair : partition_sizes) {
     for (size_t suffix_idx = 0; suffix_idx < kMaxNumSlots; ++suffix_idx) {
       if (base::EndsWith(pair.first,
                          kSlotSuffixes[suffix_idx],
                          base::CompareCase::SENSITIVE)) {
-        metadata.groups[suffix_idx].partitions.push_back(
-            {pair.first, pair.second});
+        AddPartition(
+            &manifest,
+            manifest.mutable_dynamic_partition_metadata()->mutable_groups(
+                suffix_idx),
+            pair.first,
+            pair.second);
       }
     }
   }
-  return metadata;
+  return manifest;
 }
 
 // To support legacy tests, auto-convert {name: size} map to PartitionMetadata.
-inline PartitionMetadata PartitionSizesToMetadata(
+inline DeltaArchiveManifest PartitionSizesToManifest(
     const PartitionSizes& partition_sizes) {
-  PartitionMetadata metadata;
-  metadata.groups.push_back(
-      {std::string{kDefaultGroup}, kDefaultGroupSize, {}});
+  DeltaArchiveManifest manifest;
+  auto* g = AddGroup(&manifest, std::string(kDefaultGroup), kDefaultGroupSize);
   for (const auto& pair : partition_sizes) {
-    metadata.groups[0].partitions.push_back({pair.first, pair.second});
+    AddPartition(&manifest, g, pair.first, pair.second);
   }
-  return metadata;
+  return manifest;
 }
 
 inline std::unique_ptr<MetadataBuilder> NewFakeMetadata(
-    const PartitionMetadata& metadata) {
+    const DeltaArchiveManifest& manifest) {
   auto builder =
       MetadataBuilder::New(kDefaultSuperSize, kFakeMetadataSize, kMaxNumSlots);
-  EXPECT_GE(builder->AllocatableSpace(), kDefaultGroupSize * 2);
-  EXPECT_NE(nullptr, builder);
-  if (builder == nullptr)
-    return nullptr;
-  for (const auto& group : metadata.groups) {
-    EXPECT_TRUE(builder->AddGroup(group.name, group.size));
-    for (const auto& partition : group.partitions) {
-      auto p = builder->AddPartition(partition.name, group.name, 0 /* attr */);
-      EXPECT_TRUE(p && builder->ResizePartition(p, partition.size));
+  for (const auto& group : manifest.dynamic_partition_metadata().groups()) {
+    EXPECT_TRUE(builder->AddGroup(group.name(), group.size()));
+    for (const auto& partition_name : group.partition_names()) {
+      EXPECT_NE(
+          nullptr,
+          builder->AddPartition(partition_name, group.name(), 0 /* attr */));
     }
   }
+  for (const auto& partition : manifest.partitions()) {
+    auto p = builder->FindPartition(partition.partition_name());
+    EXPECT_TRUE(p && builder->ResizePartition(
+                         p, partition.new_partition_info().size()));
+  }
   return builder;
 }
 
 class MetadataMatcher : public MatcherInterface<MetadataBuilder*> {
  public:
   explicit MetadataMatcher(const PartitionSuffixSizes& partition_sizes)
-      : partition_metadata_(PartitionSuffixSizesToMetadata(partition_sizes)) {}
-  explicit MetadataMatcher(const PartitionMetadata& partition_metadata)
-      : partition_metadata_(partition_metadata) {}
+      : manifest_(PartitionSuffixSizesToManifest(partition_sizes)) {}
+  explicit MetadataMatcher(const DeltaArchiveManifest& manifest)
+      : manifest_(manifest) {}
 
   bool MatchAndExplain(MetadataBuilder* metadata,
                        MatchResultListener* listener) const override {
     bool success = true;
-    for (const auto& group : partition_metadata_.groups) {
-      for (const auto& partition : group.partitions) {
-        auto p = metadata->FindPartition(partition.name);
+    for (const auto& group : manifest_.dynamic_partition_metadata().groups()) {
+      for (const auto& partition_name : group.partition_names()) {
+        auto p = metadata->FindPartition(partition_name);
         if (p == nullptr) {
           if (!success)
             *listener << "; ";
-          *listener << "No partition " << partition.name;
+          *listener << "No partition " << partition_name;
           success = false;
           continue;
         }
-        if (p->size() != partition.size) {
+        const auto& partition_updates = manifest_.partitions();
+        auto it = std::find_if(partition_updates.begin(),
+                               partition_updates.end(),
+                               [&](const auto& p) {
+                                 return p.partition_name() == partition_name;
+                               });
+        if (it == partition_updates.end()) {
+          *listener << "Can't find partition update " << partition_name;
+          success = false;
+          continue;
+        }
+        auto partition_size = it->new_partition_info().size();
+        if (p->size() != partition_size) {
           if (!success)
             *listener << "; ";
-          *listener << "Partition " << partition.name << " has size "
-                    << p->size() << ", expected " << partition.size;
+          *listener << "Partition " << partition_name << " has size "
+                    << p->size() << ", expected " << partition_size;
           success = false;
         }
-        if (p->group_name() != group.name) {
+        if (p->group_name() != group.name()) {
           if (!success)
             *listener << "; ";
-          *listener << "Partition " << partition.name << " has group "
-                    << p->group_name() << ", expected " << group.name;
+          *listener << "Partition " << partition_name << " has group "
+                    << p->group_name() << ", expected " << group.name();
           success = false;
         }
       }
@@ -205,15 +246,15 @@
   }
 
   void DescribeTo(std::ostream* os) const override {
-    *os << "expect: " << partition_metadata_;
+    *os << "expect: " << manifest_;
   }
 
   void DescribeNegationTo(std::ostream* os) const override {
-    *os << "expect not: " << partition_metadata_;
+    *os << "expect not: " << manifest_;
   }
 
  private:
-  PartitionMetadata partition_metadata_;
+  DeltaArchiveManifest manifest_;
 };
 
 inline Matcher<MetadataBuilder*> MetadataMatches(
@@ -222,8 +263,8 @@
 }
 
 inline Matcher<MetadataBuilder*> MetadataMatches(
-    const PartitionMetadata& partition_metadata) {
-  return MakeMatcher(new MetadataMatcher(partition_metadata));
+    const DeltaArchiveManifest& manifest) {
+  return MakeMatcher(new MetadataMatcher(manifest));
 }
 
 MATCHER_P(HasGroup, group, " has group " + group) {
diff --git a/mock_dynamic_partition_control.h b/mock_dynamic_partition_control.h
index aab3c4d..d96432b 100644
--- a/mock_dynamic_partition_control.h
+++ b/mock_dynamic_partition_control.h
@@ -45,9 +45,7 @@
   MOCK_METHOD1(GetDeviceDir, bool(std::string*));
   MOCK_METHOD0(GetDynamicPartitionsFeatureFlag, FeatureFlag());
   MOCK_METHOD3(PreparePartitionsForUpdate,
-               bool(uint32_t,
-                    uint32_t,
-                    const BootControlInterface::PartitionMetadata&));
+               bool(uint32_t, uint32_t, const DeltaArchiveManifest&));
   MOCK_METHOD1(GetSuperPartitionName, std::string(uint32_t));
   MOCK_METHOD0(GetVirtualAbFeatureFlag, FeatureFlag());
 };
diff --git a/payload_consumer/delta_performer.cc b/payload_consumer/delta_performer.cc
index d76a959..3ff98ca 100644
--- a/payload_consumer/delta_performer.cc
+++ b/payload_consumer/delta_performer.cc
@@ -808,7 +808,6 @@
     for (const PartitionUpdate& partition : manifest_.partitions()) {
       partitions_.push_back(partition);
     }
-    manifest_.clear_partitions();
   } else if (major_payload_version_ == kChromeOSMajorPayloadVersion) {
     LOG(INFO) << "Converting update information from old format.";
     PartitionUpdate root_part;
@@ -923,12 +922,16 @@
   }
 
   if (install_plan_->target_slot != BootControlInterface::kInvalidSlot) {
-    if (!InitPartitionMetadata()) {
+    if (!PreparePartitionsForUpdate()) {
       *error = ErrorCode::kInstallDeviceOpenError;
       return false;
     }
   }
 
+  if (major_payload_version_ == kBrilloMajorPayloadVersion) {
+    manifest_.clear_partitions();
+  }
+
   if (!install_plan_->LoadPartitionsFromSlots(boot_control_)) {
     LOG(ERROR) << "Unable to determine all the partition devices.";
     *error = ErrorCode::kInstallDeviceOpenError;
@@ -938,45 +941,18 @@
   return true;
 }
 
-bool DeltaPerformer::InitPartitionMetadata() {
-  BootControlInterface::PartitionMetadata partition_metadata;
-  if (manifest_.has_dynamic_partition_metadata()) {
-    std::map<string, uint64_t> partition_sizes;
-    for (const auto& partition : install_plan_->partitions) {
-      partition_sizes.emplace(partition.name, partition.target_size);
-    }
-    for (const auto& group : manifest_.dynamic_partition_metadata().groups()) {
-      BootControlInterface::PartitionMetadata::Group e;
-      e.name = group.name();
-      e.size = group.size();
-      for (const auto& partition_name : group.partition_names()) {
-        auto it = partition_sizes.find(partition_name);
-        if (it == partition_sizes.end()) {
-          // TODO(tbao): Support auto-filling partition info for framework-only
-          // OTA.
-          LOG(ERROR) << "dynamic_partition_metadata contains partition "
-                     << partition_name
-                     << " but it is not part of the manifest. "
-                     << "This is not supported.";
-          return false;
-        }
-        e.partitions.push_back({partition_name, it->second});
-      }
-      partition_metadata.groups.push_back(std::move(e));
-    }
-  }
-
+bool DeltaPerformer::PreparePartitionsForUpdate() {
   bool metadata_updated = false;
   prefs_->GetBoolean(kPrefsDynamicPartitionMetadataUpdated, &metadata_updated);
-  if (!boot_control_->InitPartitionMetadata(
-          install_plan_->target_slot, partition_metadata, !metadata_updated)) {
+  if (!boot_control_->PreparePartitionsForUpdate(
+          install_plan_->target_slot, manifest_, !metadata_updated)) {
     LOG(ERROR) << "Unable to initialize partition metadata for slot "
                << BootControlInterface::SlotName(install_plan_->target_slot);
     return false;
   }
   TEST_AND_RETURN_FALSE(
       prefs_->SetBoolean(kPrefsDynamicPartitionMetadataUpdated, true));
-  LOG(INFO) << "InitPartitionMetadata done.";
+  LOG(INFO) << "PreparePartitionsForUpdate done.";
 
   return true;
 }
diff --git a/payload_consumer/delta_performer.h b/payload_consumer/delta_performer.h
index 17cb599..25c348c 100644
--- a/payload_consumer/delta_performer.h
+++ b/payload_consumer/delta_performer.h
@@ -275,7 +275,7 @@
 
   // After install_plan_ is filled with partition names and sizes, initialize
   // metadata of partitions and map necessary devices before opening devices.
-  bool InitPartitionMetadata();
+  bool PreparePartitionsForUpdate();
 
   // Update Engine preference store.
   PrefsInterface* prefs_;