summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTianjie <xunchang@google.com>2021-03-15 16:00:50 -0700
committerTianjie Xu <xunchang@google.com>2021-03-27 07:00:33 +0000
commit9f4dc7f49d76d30aaa14bfc103e8fc619268a1bc (patch)
treedc04096a2c0c00d4b80c388033b4808c60ad4bd5
parent21a4991833d778725eef1fdbf7866c3aa0f1dbad (diff)
Check the super partiton size in VAB case
When the snapshot is used, we should check that the maximum size of all dynamic partition groups doesn't exceed the super partition size. Bug: 182431975 Test: primary payload fails as expected Pixel21 Change-Id: I5df8976e6b7e011284b29fd554dda80e31305698
-rw-r--r--aosp/dynamic_partition_control_android.cc84
-rw-r--r--aosp/dynamic_partition_control_android.h7
-rw-r--r--aosp/dynamic_partition_control_android_unittest.cc7
3 files changed, 68 insertions, 30 deletions
diff --git a/aosp/dynamic_partition_control_android.cc b/aosp/dynamic_partition_control_android.cc
index 1db8da8d..444fe42c 100644
--- a/aosp/dynamic_partition_control_android.cc
+++ b/aosp/dynamic_partition_control_android.cc
@@ -805,9 +805,7 @@ bool DynamicPartitionControlAndroid::PrepareDynamicPartitionsForUpdate(
}
std::string device_dir_str;
- if (!GetDeviceDir(&device_dir_str)) {
- return false;
- }
+ TEST_AND_RETURN_FALSE(GetDeviceDir(&device_dir_str));
base::FilePath device_dir(device_dir_str);
auto source_device =
device_dir.Append(GetSuperPartitionName(source_slot)).value();
@@ -824,21 +822,68 @@ bool DynamicPartitionControlAndroid::PrepareDynamicPartitionsForUpdate(
DeleteSourcePartitions(builder.get(), source_slot, manifest));
}
- if (!UpdatePartitionMetadata(builder.get(), target_slot, manifest)) {
- return false;
- }
+ TEST_AND_RETURN_FALSE(
+ UpdatePartitionMetadata(builder.get(), target_slot, manifest));
auto target_device =
device_dir.Append(GetSuperPartitionName(target_slot)).value();
return StoreMetadata(target_device, builder.get(), target_slot);
}
+bool DynamicPartitionControlAndroid::CheckSuperPartitionAllocatableSpace(
+ android::fs_mgr::MetadataBuilder* builder,
+ const DeltaArchiveManifest& manifest,
+ bool use_snapshot) {
+ uint64_t total_size = 0;
+ for (const auto& group : manifest.dynamic_partition_metadata().groups()) {
+ total_size += group.size();
+ }
+
+ std::string expr;
+ uint64_t allocatable_space = builder->AllocatableSpace();
+ // On device retrofitting dynamic partitions, allocatable_space = super.
+ // On device launching dynamic partitions w/o VAB,
+ // allocatable_space = super / 2.
+ // On device launching dynamic partitions with VAB, allocatable_space = super.
+ // For recovery sideload, allocatable_space = super.
+ if (!GetDynamicPartitionsFeatureFlag().IsRetrofit() && !use_snapshot &&
+ !IsRecovery()) {
+ allocatable_space /= 2;
+ expr = "half of ";
+ }
+ if (total_size > allocatable_space) {
+ LOG(ERROR) << "The maximum size of all groups for the target slot"
+ << " (" << total_size << ") has exceeded " << expr
+ << "allocatable space for dynamic partitions "
+ << allocatable_space << ".";
+ return false;
+ }
+
+ return true;
+}
+
bool DynamicPartitionControlAndroid::PrepareSnapshotPartitionsForUpdate(
uint32_t source_slot,
uint32_t target_slot,
const DeltaArchiveManifest& manifest,
uint64_t* required_size) {
TEST_AND_RETURN_FALSE(ExpectMetadataMounted());
+
+ std::string device_dir_str;
+ TEST_AND_RETURN_FALSE(GetDeviceDir(&device_dir_str));
+ base::FilePath device_dir(device_dir_str);
+ auto super_device =
+ device_dir.Append(GetSuperPartitionName(source_slot)).value();
+ auto builder = LoadMetadataBuilder(super_device, source_slot);
+ if (builder == nullptr) {
+ LOG(ERROR) << "No metadata at "
+ << BootControlInterface::SlotName(source_slot);
+ return false;
+ }
+
+ TEST_AND_RETURN_FALSE(
+ CheckSuperPartitionAllocatableSpace(builder.get(), manifest, true));
+
if (!snapshot_->BeginUpdate()) {
LOG(ERROR) << "Cannot begin new update.";
return false;
@@ -877,29 +922,8 @@ bool DynamicPartitionControlAndroid::UpdatePartitionMetadata(
const std::string target_suffix = SlotSuffixForSlotNumber(target_slot);
DeleteGroupsWithSuffix(builder, target_suffix);
- uint64_t total_size = 0;
- for (const auto& group : manifest.dynamic_partition_metadata().groups()) {
- total_size += group.size();
- }
-
- std::string expr;
- uint64_t allocatable_space = builder->AllocatableSpace();
- // On device retrofitting dynamic partitions, allocatable_space = super.
- // On device launching dynamic partitions w/o VAB,
- // allocatable_space = super / 2.
- // On device launching dynamic partitions with VAB, allocatable_space = super.
- if (!GetDynamicPartitionsFeatureFlag().IsRetrofit() &&
- !GetVirtualAbFeatureFlag().IsEnabled()) {
- allocatable_space /= 2;
- expr = "half of ";
- }
- if (total_size > allocatable_space) {
- LOG(ERROR) << "The maximum size of all groups with suffix " << target_suffix
- << " (" << total_size << ") has exceeded " << expr
- << "allocatable space for dynamic partitions "
- << allocatable_space << ".";
- return false;
- }
+ TEST_AND_RETURN_FALSE(
+ CheckSuperPartitionAllocatableSpace(builder, manifest, false));
// name of partition(e.g. "system") -> size in bytes
std::map<std::string, uint64_t> partition_sizes;
@@ -1167,7 +1191,7 @@ bool DynamicPartitionControlAndroid::DeleteSourcePartitions(
LOG(INFO) << "Will overwrite existing partitions. Slot "
<< BootControlInterface::SlotName(source_slot)
- << "may be unbootable until update finishes!";
+ << " may be unbootable until update finishes!";
const std::string source_suffix = SlotSuffixForSlotNumber(source_slot);
DeleteGroupsWithSuffix(builder, source_suffix);
diff --git a/aosp/dynamic_partition_control_android.h b/aosp/dynamic_partition_control_android.h
index c506ac97..b7aa7eaa 100644
--- a/aosp/dynamic_partition_control_android.h
+++ b/aosp/dynamic_partition_control_android.h
@@ -258,6 +258,13 @@ class DynamicPartitionControlAndroid : public DynamicPartitionControlInterface {
const DeltaArchiveManifest& manifest,
uint64_t* required_size);
+ // Returns true if the allocatable space in super partition is larger than
+ // the size of dynamic partition groups in the manifest.
+ bool CheckSuperPartitionAllocatableSpace(
+ android::fs_mgr::MetadataBuilder* builder,
+ const DeltaArchiveManifest& manifest,
+ bool use_snapshot);
+
enum class DynamicPartitionDeviceStatus {
SUCCESS,
ERROR,
diff --git a/aosp/dynamic_partition_control_android_unittest.cc b/aosp/dynamic_partition_control_android_unittest.cc
index eb3f60cc..0bb8df7a 100644
--- a/aosp/dynamic_partition_control_android_unittest.cc
+++ b/aosp/dynamic_partition_control_android_unittest.cc
@@ -1051,6 +1051,7 @@ class SnapshotPartitionTestP : public DynamicPartitionControlAndroidTestP {
// Test happy path of PreparePartitionsForUpdate on a Virtual A/B device.
TEST_P(SnapshotPartitionTestP, PreparePartitions) {
ExpectCreateUpdateSnapshots(android::snapshot::Return::Ok());
+ SetMetadata(source(), {});
uint64_t required_size = 0;
EXPECT_TRUE(PreparePartitionsForUpdate(&required_size));
EXPECT_EQ(0u, required_size);
@@ -1061,6 +1062,8 @@ TEST_P(SnapshotPartitionTestP, PreparePartitions) {
TEST_P(SnapshotPartitionTestP, PreparePartitionsNoSpace) {
ExpectCreateUpdateSnapshots(android::snapshot::Return::NoSpace(1_GiB));
uint64_t required_size = 0;
+
+ SetMetadata(source(), {});
EXPECT_FALSE(PreparePartitionsForUpdate(&required_size));
EXPECT_EQ(1_GiB, required_size);
}
@@ -1070,6 +1073,10 @@ TEST_P(SnapshotPartitionTestP, PreparePartitionsNoSpace) {
TEST_P(SnapshotPartitionTestP, RecoveryUseSuperEmpty) {
ExpectCreateUpdateSnapshots(android::snapshot::Return::Ok());
EXPECT_CALL(dynamicControl(), IsRecovery()).WillRepeatedly(Return(true));
+
+ // Metadata is needed to perform super partition size check.
+ SetMetadata(source(), {});
+
// Must not call PrepareDynamicPartitionsForUpdate if
// PrepareSnapshotPartitionsForUpdate succeeds.
EXPECT_CALL(dynamicControl(), PrepareDynamicPartitionsForUpdate(_, _, _, _))