summaryrefslogtreecommitdiff
path: root/aosp/dynamic_partition_control_android.cc
diff options
context:
space:
mode:
Diffstat (limited to 'aosp/dynamic_partition_control_android.cc')
-rw-r--r--aosp/dynamic_partition_control_android.cc116
1 files changed, 91 insertions, 25 deletions
diff --git a/aosp/dynamic_partition_control_android.cc b/aosp/dynamic_partition_control_android.cc
index 444fe42c..ab349a82 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::Return;
using android::snapshot::SnapshotManager;
using android::snapshot::SnapshotManagerStub;
using android::snapshot::UpdateState;
+using base::StringPrintf;
namespace chromeos_update_engine {
@@ -830,33 +832,90 @@ bool DynamicPartitionControlAndroid::PrepareDynamicPartitionsForUpdate(
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();
- }
-
- 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;
+ sum_groups += group.size();
+ }
+
+ 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;
@@ -910,9 +969,16 @@ bool DynamicPartitionControlAndroid::UpdatePartitionMetadata(
uint32_t target_slot,
const DeltaArchiveManifest& manifest) {
// Check preconditions.
- LOG_IF(WARNING, !GetVirtualAbFeatureFlag().IsEnabled() || IsRecovery())
- << "UpdatePartitionMetadata is called on a Virtual A/B device "
- "but source partitions is not deleted. This is not allowed.";
+ if (GetVirtualAbFeatureFlag().IsEnabled()) {
+ CHECK(!target_supports_snapshot_ || IsRecovery())
+ << "Must use snapshot on VAB device when target build supports VAB and "
+ "not sideloading.";
+ LOG_IF(INFO, !target_supports_snapshot_)
+ << "Not using snapshot on VAB device because target build does not "
+ "support snapshot. Secondary or downgrade OTA?";
+ LOG_IF(INFO, IsRecovery())
+ << "Not using snapshot on VAB device because sideloading.";
+ }
// If applying downgrade from Virtual A/B to non-Virtual A/B, the left-over
// COW group needs to be deleted to ensure there are enough space to create