[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_;