Rewrite misc_info.txt to include only system-known partitions. This handles the GSI case where product and partitions invented later are all collapsed into the system partition. Test: Combine with a later system image Bug: 150097754 Change-Id: I871342f6df0dba0cf5c35931e8e9c5867a770cf0
diff --git a/common/libs/utils/archive.cpp b/common/libs/utils/archive.cpp index c1c496d..36e6576 100644 --- a/common/libs/utils/archive.cpp +++ b/common/libs/utils/archive.cpp
@@ -73,4 +73,21 @@ return bsdtar_ret == 0; } +std::string Archive::ExtractToMemory(const std::string& path) { + cvd::Command bsdtar_cmd("/usr/bin/bsdtar"); + bsdtar_cmd.AddParameter("-xf"); + bsdtar_cmd.AddParameter(file); + bsdtar_cmd.AddParameter("-O"); + bsdtar_cmd.AddParameter(path); + std::string stdout, stderr; + auto ret = RunWithManagedStdio(std::move(bsdtar_cmd), nullptr, &stdout, + nullptr); + if (ret != 0) { + LOG(ERROR) << "Could not extract \"" << path << "\" from \"" << file + << "\" to memory."; + return ""; + } + return stdout; +} + } // namespace cvd
diff --git a/common/libs/utils/archive.h b/common/libs/utils/archive.h index fae9288..7563ca0 100644 --- a/common/libs/utils/archive.h +++ b/common/libs/utils/archive.h
@@ -31,6 +31,7 @@ bool ExtractAll(const std::string& target_directory = "."); bool ExtractFiles(const std::vector<std::string>& files, const std::string& target_directory = "."); + std::string ExtractToMemory(const std::string& path); }; } // namespace cvd
diff --git a/host/commands/assemble_cvd/Android.bp b/host/commands/assemble_cvd/Android.bp index 807f18c..ef77942 100644 --- a/host/commands/assemble_cvd/Android.bp +++ b/host/commands/assemble_cvd/Android.bp
@@ -36,6 +36,7 @@ "data_image.cc", "flags.cc", "image_aggregator.cc", + "misc_info.cc", "super_image_mixer.cc", ], header_libs: [
diff --git a/host/commands/assemble_cvd/misc_info.cc b/host/commands/assemble_cvd/misc_info.cc new file mode 100644 index 0000000..c708e87 --- /dev/null +++ b/host/commands/assemble_cvd/misc_info.cc
@@ -0,0 +1,80 @@ +// +// Copyright (C) 2020 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "misc_info.h" + +#include <algorithm> + +#include <android-base/logging.h> +#include <android-base/strings.h> + +MiscInfo ParseMiscInfo(const std::string& misc_info_contents) { + auto lines = android::base::Split(misc_info_contents, "\n"); + MiscInfo misc_info; + for (auto& line : lines) { + line = android::base::Trim(line); + if (line.size() == 0) { + continue; + } + auto eq_pos = line.find('='); + if (eq_pos == std::string::npos) { + LOG(WARNING) << "Line in unknown format: \"" << line << "\""; + continue; + } + // Not using android::base::Split here to only capture the first = + auto key = android::base::Trim(line.substr(0, eq_pos)); + auto value = android::base::Trim(line.substr(eq_pos + 1)); + if (misc_info.find(key) != misc_info.end()) { + LOG(ERROR) << "Duplicate key: \"" << key << "\". First value: \"" + << misc_info[key] << "\", Second value: \"" << value << "\""; + return {}; + } + misc_info[key] = value; + } + return misc_info; +} + +std::string WriteMiscInfo(const MiscInfo& misc_info) { + std::stringstream out; + for (const auto& entry : misc_info) { + out << entry.first << "=" << entry.second << "\n"; + } + return out.str(); +} + +static const std::string kDynamicPartitions = "dynamic_partition_list"; + +std::vector<std::string> SuperPartitionComponents(const MiscInfo& info) { + auto value_it = info.find(kDynamicPartitions); + if (value_it == info.end()) { + return {}; + } + auto components = android::base::Split(value_it->second, " "); + for (auto& component : components) { + component = android::base::Trim(component); + } + components.erase(std::remove(components.begin(), components.end(), ""), + components.end()); + return components; +} + +static const std::string kGoogleDynamicPartitions = + "super_google_dynamic_partitions_partition_list"; + +void SetSuperPartitionComponents(const std::vector<std::string>& components, + MiscInfo* misc_info) { + (*misc_info)[kDynamicPartitions] = android::base::Join(components, " "); + (*misc_info)[kGoogleDynamicPartitions] = android::base::Join(components, " "); +}
diff --git a/host/commands/assemble_cvd/misc_info.h b/host/commands/assemble_cvd/misc_info.h new file mode 100644 index 0000000..7c32e3b --- /dev/null +++ b/host/commands/assemble_cvd/misc_info.h
@@ -0,0 +1,28 @@ +// +// Copyright (C) 2020 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include <map> +#include <string> + +using MiscInfo = std::map<std::string, std::string>; + +MiscInfo ParseMiscInfo(const std::string& file_contents); +std::string WriteMiscInfo(const MiscInfo& info); + +std::vector<std::string> SuperPartitionComponents(const MiscInfo&); +void SetSuperPartitionComponents(const std::vector<std::string>& components, + MiscInfo* misc_info);
diff --git a/host/commands/assemble_cvd/super_image_mixer.cc b/host/commands/assemble_cvd/super_image_mixer.cc index 78d2750..ce75a67 100644 --- a/host/commands/assemble_cvd/super_image_mixer.cc +++ b/host/commands/assemble_cvd/super_image_mixer.cc
@@ -25,9 +25,11 @@ #include <android-base/strings.h> #include <glog/logging.h> +#include "common/libs/fs/shared_buf.h" #include "common/libs/utils/archive.h" #include "common/libs/utils/files.h" #include "common/libs/utils/subprocess.h" +#include "host/commands/assemble_cvd/misc_info.h" #include "host/libs/config/cuttlefish_config.h" #include "host/libs/config/fetcher_config.h" @@ -56,6 +58,7 @@ const std::set<std::string> kDefaultTargetImages = { "IMAGES/boot.img", "IMAGES/cache.img", + "IMAGES/odm.img", "IMAGES/recovery.img", "IMAGES/userdata.img", "IMAGES/vendor.img", @@ -81,14 +84,53 @@ LOG(ERROR) << "Could not create directory " << output_path; return false; } + std::string output_meta = output_path + "/META"; + if (mkdir(output_meta.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) < 0) { + LOG(ERROR) << "Could not create directory " << output_meta; + return false; + } if (std::find(default_target_contents.begin(), default_target_contents.end(), kMiscInfoPath) == default_target_contents.end()) { LOG(ERROR) << "Default target files zip does not have " << kMiscInfoPath; return false; } - if (!default_target_archive.ExtractFiles({kMiscInfoPath}, output_path)) { - LOG(ERROR) << "Failed to write misc info to output directory"; + if (std::find(system_target_contents.begin(), system_target_contents.end(), kMiscInfoPath) + == system_target_contents.end()) { + LOG(ERROR) << "System target files zip does not have " << kMiscInfoPath; + return false; + } + const auto default_misc = + ParseMiscInfo(default_target_archive.ExtractToMemory(kMiscInfoPath)); + if (default_misc.size() == 0) { + LOG(ERROR) << "Could not read the default misc_info.txt file."; + return false; + } + const auto system_misc = + ParseMiscInfo(system_target_archive.ExtractToMemory(kMiscInfoPath)); + if (system_misc.size() == 0) { + LOG(ERROR) << "Could not read the system misc_info.txt file."; + return false; + } + auto output_misc = default_misc; + auto system_super_partitions = SuperPartitionComponents(system_misc); + if (std::find(system_super_partitions.begin(), system_super_partitions.end(), + "odm") == system_super_partitions.end()) { + // odm is not one of the partitions skipped by the system check + system_super_partitions.push_back("odm"); + } + SetSuperPartitionComponents(system_super_partitions, &output_misc); + auto misc_output_path = output_path + "/" + kMiscInfoPath; + cvd::SharedFD misc_output_file = + cvd::SharedFD::Creat(misc_output_path.c_str(), 0644); + if (!misc_output_file->IsOpen()) { + LOG(ERROR) << "Failed to open output misc file: " + << misc_output_file->StrError(); + return false; + } + if (cvd::WriteAll(misc_output_file, WriteMiscInfo(output_misc)) < 0) { + LOG(ERROR) << "Failed to write output misc file contents: " + << misc_output_file->StrError(); return false; }