diff options
author | Chad Reynolds <chadreynolds@google.com> | 2024-04-12 18:16:01 -0700 |
---|---|---|
committer | Chad Reynolds <chadreynolds@google.com> | 2024-04-24 17:55:26 -0700 |
commit | 6f4f77ff63e020e9b6bc93bb393b86e9593d6286 (patch) | |
tree | f6aafaa6d30704393a7882637bcc9687b8e68c2d | |
parent | 1294bb53b4ec148a21c258f03596343bdd030b1e (diff) | |
download | cuttlefish-6f4f77ff63e020e9b6bc93bb393b86e9593d6286.tar.gz |
Dynamically combine dynamic partitions and groups
Generate the dynamic partitions list and update groups from a
combination of both "dynamic_partitions_info.txt" files.
This is based on the `merge_target_files.py` logic, and generates a
close enough output for our purposes.
Bug: 322887496
Test: see the bug comment 37 for steps to test this stack of changes
Change-Id: Idc0148ba730751638d5d8542569270b78cc542b6
-rw-r--r-- | host/commands/assemble_cvd/misc_info.cc | 139 | ||||
-rw-r--r-- | host/commands/assemble_cvd/misc_info.h | 9 | ||||
-rw-r--r-- | host/commands/assemble_cvd/super_image_mixer.cc | 37 |
3 files changed, 115 insertions, 70 deletions
diff --git a/host/commands/assemble_cvd/misc_info.cc b/host/commands/assemble_cvd/misc_info.cc index 292258b96..1c7f1144c 100644 --- a/host/commands/assemble_cvd/misc_info.cc +++ b/host/commands/assemble_cvd/misc_info.cc @@ -15,13 +15,12 @@ #include "misc_info.h" -#include <algorithm> +#include <set> #include <string> -#include <vector> #include <android-base/logging.h> -#include <android-base/stringprintf.h> #include <android-base/strings.h> +#include <fmt/format.h> #include "common/libs/utils/contains.h" #include "common/libs/utils/result.h" @@ -31,7 +30,40 @@ namespace { constexpr char kDynamicPartitions[] = "dynamic_partition_list"; constexpr char kGoogleDynamicPartitions[] = "google_dynamic_partitions"; +constexpr char kSuperBlockDevices[] = "super_block_devices"; constexpr char kSuperPartitionGroups[] = "super_partition_groups"; +constexpr char kUseDynamicPartitions[] = "use_dynamic_partitions"; + +Result<std::string> GetExpected(const MiscInfo& misc_info, + const std::string& key) { + auto lookup = misc_info.find(key); + CF_EXPECTF(lookup != misc_info.end(), + "Unable to retrieve expected value from key: {}", key); + return lookup->second; +} + +std::string GetOrDefault(const MiscInfo& misc_info, const std::string& key, + const std::string& default_value) { + auto result = GetExpected(misc_info, key); + return result.ok() ? *result : default_value; +} + +std::string MergePartitionLists(const std::string& vendor, + const std::string& system) { + const std::string full_string = fmt::format("{} {}", vendor, system); + auto full_list = android::base::Tokenize(full_string, " "); + // std::set removes duplicates and orders the elements, which we want + std::set<std::string> full_set(full_list.begin(), full_list.end()); + return android::base::Join(full_set, " "); +} + +std::string GetPartitionList(const MiscInfo& vendor_info, + const MiscInfo& system_info, + const std::string& key) { + std::string vendor_list = GetOrDefault(vendor_info, key, ""); + std::string system_list = GetOrDefault(system_info, key, ""); + return MergePartitionLists(vendor_list, system_list); +} } // namespace @@ -69,65 +101,66 @@ std::string WriteMiscInfo(const MiscInfo& misc_info) { return out.str(); } -std::vector<std::string> SuperPartitionComponents(const MiscInfo& info) { - auto value_it = info.find(kDynamicPartitions); - if (value_it == info.end()) { - return {}; +// based on build/make/tools/releasetools/merge/merge_target_files.py +Result<MiscInfo> GetCombinedDynamicPartitions(const MiscInfo& vendor_info, + const MiscInfo& system_info) { + CF_EXPECTF(CF_EXPECT(GetExpected(vendor_info, kDynamicPartitions)) == "true", + "Vendor build must have {}=true", kUseDynamicPartitions); + CF_EXPECTF(CF_EXPECT(GetExpected(system_info, kDynamicPartitions)) == "true", + "System build must have {}=true", kUseDynamicPartitions); + MiscInfo result; + // copy where both files are equal + for (const auto& key_val : vendor_info) { + const auto value_result = GetExpected(system_info, key_val.first); + if (value_result.ok() && *value_result == key_val.second) { + result[key_val.first] = key_val.second; + } } - auto components = android::base::Split(value_it->second, " "); - for (auto& component : components) { - component = android::base::Trim(component); + + result[kDynamicPartitions] = + GetPartitionList(vendor_info, system_info, kDynamicPartitions); + + const auto block_devices_result = + GetExpected(vendor_info, kSuperBlockDevices); + if (block_devices_result.ok()) { + result[kSuperBlockDevices] = *block_devices_result; + for (const auto& block_device : + android::base::Tokenize(result[kSuperBlockDevices], " ")) { + const auto key = "super_" + block_device + "_device_size"; + result[key] = CF_EXPECT(GetExpected(vendor_info, key)); + } } - components.erase(std::remove(components.begin(), components.end(), ""), - components.end()); - return components; -} -bool SetSuperPartitionComponents(const std::vector<std::string>& components, - MiscInfo* misc_info) { - auto super_partition_groups = misc_info->find(kSuperPartitionGroups); - if (super_partition_groups == misc_info->end()) { - LOG(ERROR) << "Failed to find super partition groups in misc_info"; - return false; + result[kSuperPartitionGroups] = + CF_EXPECT(GetExpected(vendor_info, kSuperPartitionGroups)); + for (const auto& group : + android::base::Tokenize(result[kSuperPartitionGroups], " ")) { + const auto group_size_key = "super_" + group + "_group_size"; + result[group_size_key] = + CF_EXPECT(GetExpected(vendor_info, group_size_key)); + + const auto partition_list_key = "super_" + group + "_partition_list"; + result[partition_list_key] = + GetPartitionList(vendor_info, system_info, partition_list_key); } - // Remove all existing update groups in misc_info - auto update_groups = - android::base::Split(super_partition_groups->second, " "); - for (const auto& group_name : update_groups) { - auto partition_list = android::base::StringPrintf("super_%s_partition_list", - group_name.c_str()); - auto partition_size = - android::base::StringPrintf("super_%s_group_size", group_name.c_str()); - for (const auto& key : {partition_list, partition_size}) { - auto it = misc_info->find(key); - if (it == misc_info->end()) { - LOG(ERROR) << "Failed to find " << key << " in misc_info"; - return false; - } - misc_info->erase(it); + // TODO(chadreynolds): add vabc_cow_version logic if we need to support older + // builds + for (const auto& key : + {"virtual_ab", "virtual_ab_retrofit", "lpmake", "super_metadata_device", + "super_partition_error_limit", "super_partition_size"}) { + const auto value_result = GetExpected(vendor_info, key); + if (value_result.ok()) { + result[key] = *value_result; } } + return std::move(result); +} - // For merged target-file, put all dynamic partitions under the - // google_dynamic_partitions update group. - // TODO(xunchang) use different update groups for system and vendor images. - (*misc_info)[kDynamicPartitions] = android::base::Join(components, " "); - (*misc_info)[kSuperPartitionGroups] = kGoogleDynamicPartitions; - std::string partitions_list_key = android::base::StringPrintf( - "super_%s_partition_list", kGoogleDynamicPartitions); - (*misc_info)[partitions_list_key] = android::base::Join(components, " "); - - // Use the entire super partition as the group size - std::string group_size_key = android::base::StringPrintf( - "super_%s_group_size", kGoogleDynamicPartitions); - auto super_size_it = misc_info->find("super_partition_size"); - if (super_size_it == misc_info->end()) { - LOG(ERROR) << "Failed to find super partition size"; - return false; +void MergeInKeys(const MiscInfo& source, MiscInfo& target) { + for (const auto& key_val : source) { + target[key_val.first] = key_val.second; } - (*misc_info)[group_size_key] = super_size_it->second; - return true; } } // namespace cuttlefish diff --git a/host/commands/assemble_cvd/misc_info.h b/host/commands/assemble_cvd/misc_info.h index f832a4c5f..d0abae896 100644 --- a/host/commands/assemble_cvd/misc_info.h +++ b/host/commands/assemble_cvd/misc_info.h @@ -23,13 +23,14 @@ namespace cuttlefish { +// TODO(chadreynolds): rename MiscInfo to more generic KeyValueFile since this +// logic is processing multiple filetypes now using MiscInfo = std::map<std::string, std::string>; Result<MiscInfo> ParseMiscInfo(const std::string& file_contents); std::string WriteMiscInfo(const MiscInfo& info); - -std::vector<std::string> SuperPartitionComponents(const MiscInfo&); -bool SetSuperPartitionComponents(const std::vector<std::string>& components, - MiscInfo* misc_info); +Result<MiscInfo> GetCombinedDynamicPartitions(const MiscInfo& vendor_info, + const MiscInfo& system_info); +void MergeInKeys(const MiscInfo& source, MiscInfo& target); } // namespace cuttlefish diff --git a/host/commands/assemble_cvd/super_image_mixer.cc b/host/commands/assemble_cvd/super_image_mixer.cc index b59d163fb..a5969080f 100644 --- a/host/commands/assemble_cvd/super_image_mixer.cc +++ b/host/commands/assemble_cvd/super_image_mixer.cc @@ -41,6 +41,7 @@ namespace cuttlefish { namespace { constexpr char kMiscInfoPath[] = "META/misc_info.txt"; +constexpr char kDynamicPartitionsPath[] = "META/dynamic_partitions_info.txt"; constexpr std::array kVendorTargetImages = { "IMAGES/boot.img", "IMAGES/dtbo.img", @@ -107,29 +108,39 @@ Result<TargetFiles> GetTargetFiles(const std::string& vendor_zip_path, return result; } +Result<MiscInfo> CombineDynamicPartitionsInfo(TargetFiles& target_files) { + CF_EXPECTF(Contains(target_files.vendor_contents, kDynamicPartitionsPath), + "Vendor target files zip does not contain {}", + kDynamicPartitionsPath); + CF_EXPECTF(Contains(target_files.system_contents, kDynamicPartitionsPath), + "System target files zip does not contain {}", + kDynamicPartitionsPath); + + const MiscInfo vendor_dp_info = CF_EXPECT(ParseMiscInfo( + target_files.vendor_zip.ExtractToMemory(kDynamicPartitionsPath))); + const MiscInfo system_dp_info = CF_EXPECT(ParseMiscInfo( + target_files.system_zip.ExtractToMemory(kDynamicPartitionsPath))); + + return CF_EXPECT( + GetCombinedDynamicPartitions(vendor_dp_info, system_dp_info)); +} + Result<void> CombineMiscInfo(TargetFiles& target_files, const std::string& misc_output_path) { CF_EXPECTF(Contains(target_files.vendor_contents, kMiscInfoPath), - "Default target files zip does not contain {}", kMiscInfoPath); + "Vendor target files zip does not contain {}", kMiscInfoPath); CF_EXPECTF(Contains(target_files.system_contents, kMiscInfoPath), "System target files zip does not contain {}", kMiscInfoPath); - const MiscInfo default_misc = CF_EXPECT( + // the combined misc info uses the vendor values as defaults + MiscInfo output_misc = CF_EXPECT( ParseMiscInfo(target_files.vendor_zip.ExtractToMemory(kMiscInfoPath))); const MiscInfo system_misc = CF_EXPECT( ParseMiscInfo(target_files.system_zip.ExtractToMemory(kMiscInfoPath))); - auto output_misc = default_misc; - auto system_super_partitions = SuperPartitionComponents(system_misc); - // Ensure specific skipped partitions end up in the misc_info.txt - for (auto partition : - {"odm", "odm_dlkm", "vendor", "vendor_dlkm", "system_dlkm"}) { - if (!Contains(system_super_partitions, partition)) { - system_super_partitions.push_back(partition); - } - } - CF_EXPECT(SetSuperPartitionComponents(system_super_partitions, &output_misc), - "Failed to update super partitions components for misc_info"); + const auto combined_dp_info = + CF_EXPECT(CombineDynamicPartitionsInfo(target_files)); + MergeInKeys(combined_dp_info, output_misc); SharedFD misc_output_file = SharedFD::Creat(misc_output_path.c_str(), 0644); CF_EXPECT(misc_output_file->IsOpen(), "Failed to open output misc file: " |