CheckSuperPartitionAllocatableSpace: based on device prop am: 3a1293a41d am: b521391c2e
Original change: https://android-review.googlesource.com/c/platform/system/update_engine/+/1678230
Change-Id: I492c8937e3919d1668b62a99b560bfcacc7305e0
diff --git a/aosp/dynamic_partition_control_android.cc b/aosp/dynamic_partition_control_android.cc
index 444fe42..be24e44 100644
--- a/aosp/dynamic_partition_control_android.cc
+++ b/aosp/dynamic_partition_control_android.cc
@@ -32,6 +32,7 @@
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/strings/string_util.h>
+#include <base/strings/stringprintf.h>
#include <bootloader_message/bootloader_message.h>
#include <fs_mgr.h>
#include <fs_mgr_dm_linear.h>
@@ -70,6 +71,7 @@
using android::snapshot::SnapshotManager;
using android::snapshot::SnapshotManagerStub;
using android::snapshot::UpdateState;
+using base::StringPrintf;
namespace chromeos_update_engine {
@@ -830,33 +832,90 @@
return StoreMetadata(target_device, builder.get(), target_slot);
}
+DynamicPartitionControlAndroid::SpaceLimit
+DynamicPartitionControlAndroid::GetSpaceLimit(bool use_snapshot) {
+ // On device retrofitting dynamic partitions, allocatable_space = "super",
+ // where "super" is the sum of all block devices for that slot. Since block
+ // devices are dedicated for the corresponding slot, there's no need to halve
+ // the allocatable space.
+ if (GetDynamicPartitionsFeatureFlag().IsRetrofit())
+ return SpaceLimit::ERROR_IF_EXCEEDED_SUPER;
+
+ // On device launching dynamic partitions w/o VAB, regardless of recovery
+ // sideload, super partition must be big enough to hold both A and B slots of
+ // groups. Hence,
+ // allocatable_space = super / 2
+ if (!GetVirtualAbFeatureFlag().IsEnabled())
+ return SpaceLimit::ERROR_IF_EXCEEDED_HALF_OF_SUPER;
+
+ // Source build supports VAB. Super partition must be big enough to hold
+ // one slot of groups (ERROR_IF_EXCEEDED_SUPER). However, there are cases
+ // where additional warning messages needs to be written.
+
+ // If using snapshot updates, implying that target build also uses VAB,
+ // allocatable_space = super
+ if (use_snapshot)
+ return SpaceLimit::ERROR_IF_EXCEEDED_SUPER;
+
+ // Source build supports VAB but not using snapshot updates. There are
+ // several cases, as listed below.
+ // Sideloading: allocatable_space = super.
+ if (IsRecovery())
+ return SpaceLimit::ERROR_IF_EXCEEDED_SUPER;
+
+ // On launch VAB device, this implies secondary payload.
+ // Technically, we don't have to check anything, but sum(groups) < super
+ // still applies.
+ if (!GetVirtualAbFeatureFlag().IsRetrofit())
+ return SpaceLimit::ERROR_IF_EXCEEDED_SUPER;
+
+ // On retrofit VAB device, either of the following:
+ // - downgrading: allocatable_space = super / 2
+ // - secondary payload: don't check anything
+ // These two cases are indistinguishable,
+ // hence emit warning if sum(groups) > super / 2
+ return SpaceLimit::WARN_IF_EXCEEDED_HALF_OF_SUPER;
+}
+
bool DynamicPartitionControlAndroid::CheckSuperPartitionAllocatableSpace(
android::fs_mgr::MetadataBuilder* builder,
const DeltaArchiveManifest& manifest,
bool use_snapshot) {
- uint64_t total_size = 0;
+ uint64_t sum_groups = 0;
for (const auto& group : manifest.dynamic_partition_metadata().groups()) {
- total_size += group.size();
+ sum_groups += 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;
+ uint64_t full_space = builder->AllocatableSpace();
+ uint64_t half_space = full_space / 2;
+ constexpr const char* fmt =
+ "The maximum size of all groups for the target slot (%" PRIu64
+ ") has exceeded %sallocatable space for dynamic partitions %" PRIu64 ".";
+ switch (GetSpaceLimit(use_snapshot)) {
+ case SpaceLimit::ERROR_IF_EXCEEDED_HALF_OF_SUPER: {
+ if (sum_groups > half_space) {
+ LOG(ERROR) << StringPrintf(fmt, sum_groups, "HALF OF ", half_space);
+ return false;
+ }
+ // If test passes, it implies that the following two conditions also pass.
+ break;
+ }
+ case SpaceLimit::WARN_IF_EXCEEDED_HALF_OF_SUPER: {
+ if (sum_groups > half_space) {
+ LOG(WARNING) << StringPrintf(fmt, sum_groups, "HALF OF ", half_space)
+ << " This is allowed for downgrade or secondary OTA on "
+ "retrofit VAB device.";
+ }
+ // still check sum(groups) < super
+ [[fallthrough]];
+ }
+ case SpaceLimit::ERROR_IF_EXCEEDED_SUPER: {
+ if (sum_groups > full_space) {
+ LOG(ERROR) << base::StringPrintf(fmt, sum_groups, "", full_space);
+ return false;
+ }
+ break;
+ }
}
return true;
diff --git a/aosp/dynamic_partition_control_android.h b/aosp/dynamic_partition_control_android.h
index b7aa7ea..df91401 100644
--- a/aosp/dynamic_partition_control_android.h
+++ b/aosp/dynamic_partition_control_android.h
@@ -258,6 +258,18 @@
const DeltaArchiveManifest& manifest,
uint64_t* required_size);
+ enum SpaceLimit {
+ // Most restricted: if sum(groups) > super / 2, error
+ ERROR_IF_EXCEEDED_HALF_OF_SUPER,
+ // Implies ERROR_IF_EXCEEDED_SUPER; then, if sum(groups) > super / 2, warn
+ WARN_IF_EXCEEDED_HALF_OF_SUPER,
+ // Least restricted: if sum(groups) > super, error
+ ERROR_IF_EXCEEDED_SUPER,
+ };
+ // Helper of CheckSuperPartitionAllocatableSpace. Determine limit for groups
+ // and partitions.
+ SpaceLimit GetSpaceLimit(bool use_snapshot);
+
// Returns true if the allocatable space in super partition is larger than
// the size of dynamic partition groups in the manifest.
bool CheckSuperPartitionAllocatableSpace(