diff options
author | Tianjie <xunchang@google.com> | 2021-03-15 16:00:50 -0700 |
---|---|---|
committer | Tianjie Xu <xunchang@google.com> | 2021-03-27 07:00:33 +0000 |
commit | 9f4dc7f49d76d30aaa14bfc103e8fc619268a1bc (patch) | |
tree | dc04096a2c0c00d4b80c388033b4808c60ad4bd5 | |
parent | 21a4991833d778725eef1fdbf7866c3aa0f1dbad (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.cc | 84 | ||||
-rw-r--r-- | aosp/dynamic_partition_control_android.h | 7 | ||||
-rw-r--r-- | aosp/dynamic_partition_control_android_unittest.cc | 7 |
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(_, _, _, _)) |