Discover the kernel/ramdisk from the fetcher config

This allows assemble_cvd to react to whether fetch_cvd downloaded a
kernel or ramdisk without that information having to be repeated as
arguments to kernel_path or initramfs_path.

Test: `acloud create` with a kernel_build
Bug: 143562630
Change-Id: I93e069eba25c4a0ebc53bcb448fc7a319ab11524
diff --git a/host/commands/assemble_cvd/flags.cc b/host/commands/assemble_cvd/flags.cc
index 54eefcc..50cdb68 100644
--- a/host/commands/assemble_cvd/flags.cc
+++ b/host/commands/assemble_cvd/flags.cc
@@ -214,7 +214,9 @@
 
 namespace {
 
-std::string kRamdiskConcatExt = ".concat";
+const std::string kKernelDefaultPath = "kernel";
+const std::string kInitramfsImg = "initramfs.img";
+const std::string kRamdiskConcatExt = ".concat";
 
 template<typename S, typename T>
 static std::string concat(const S& s, const T& t) {
@@ -273,7 +275,8 @@
 // Initializes the config object and saves it to file. It doesn't return it, all
 // further uses of the config should happen through the singleton
 bool InitializeCuttlefishConfiguration(
-    const cvd::BootImageUnpacker& boot_image_unpacker) {
+    const cvd::BootImageUnpacker& boot_image_unpacker,
+    const cvd::FetcherConfig& fetcher_config) {
   vsoc::CuttlefishConfig tmp_config_obj;
   auto& memory_layout = *vsoc::VSoCMemoryLayout::Get();
   // Set this first so that calls to PerInstancePath below are correct
@@ -316,12 +319,14 @@
   tmp_config_obj.set_adb_ip_and_port("127.0.0.1:" + std::to_string(GetHostPort()));
 
   tmp_config_obj.set_device_title(FLAGS_device_title);
-  if (FLAGS_kernel_path.size()) {
-    tmp_config_obj.set_kernel_image_path(FLAGS_kernel_path);
+  std::string discovered_kernel = fetcher_config.FindCvdFileWithSuffix(kKernelDefaultPath);
+  std::string foreign_kernel = FLAGS_kernel_path.size() ? FLAGS_kernel_path : discovered_kernel;
+  if (foreign_kernel.size()) {
+    tmp_config_obj.set_kernel_image_path(foreign_kernel);
     tmp_config_obj.set_use_unpacked_kernel(false);
   } else {
     tmp_config_obj.set_kernel_image_path(
-        tmp_config_obj.PerInstancePath("kernel"));
+        tmp_config_obj.PerInstancePath(kKernelDefaultPath.c_str()));
     tmp_config_obj.set_use_unpacked_kernel(true);
   }
   tmp_config_obj.set_decompress_kernel(FLAGS_decompress_kernel);
@@ -418,7 +423,9 @@
   // Boot as recovery is set so normal boot needs to be forced every boot
   tmp_config_obj.add_kernel_cmdline("androidboot.force_normal_boot=1");
 
-  if (FLAGS_kernel_path.size() && !FLAGS_initramfs_path.size()) {
+  std::string discovered_ramdisk = fetcher_config.FindCvdFileWithSuffix(kInitramfsImg);
+  std::string foreign_ramdisk = FLAGS_initramfs_path.size () ? FLAGS_initramfs_path : discovered_ramdisk;
+  if (foreign_kernel.size() && !foreign_ramdisk.size()) {
     // If there's a kernel that's passed in without an initramfs, that implies
     // user error or a kernel built with no modules. In either case, let's
     // choose to avoid loading the modules from the vendor ramdisk which are
@@ -427,8 +434,8 @@
     tmp_config_obj.set_final_ramdisk_path(ramdisk_path);
   } else {
     tmp_config_obj.set_final_ramdisk_path(ramdisk_path + kRamdiskConcatExt);
-    if(FLAGS_initramfs_path.size()) {
-      tmp_config_obj.set_initramfs_path(FLAGS_initramfs_path);
+    if(foreign_ramdisk.size()) {
+      tmp_config_obj.set_initramfs_path(foreign_ramdisk);
     }
   }
 
@@ -796,7 +803,7 @@
     cvd::BootImageUnpacker::FromImages(FLAGS_boot_image,
                                        FLAGS_vendor_boot_image);
 
-  if (!InitializeCuttlefishConfiguration(*boot_img_unpacker)) {
+  if (!InitializeCuttlefishConfiguration(*boot_img_unpacker, fetcher_config)) {
     LOG(ERROR) << "Failed to initialize configuration";
     exit(AssemblerExitCodes::kCuttlefishConfigurationInitError);
   }
@@ -829,7 +836,11 @@
   // boot ramdisk. If a kernel IS provided with no initramfs, it is safe to
   // safe to assume that the kernel was built with no modules and expects no
   // modules for cf to run properly.
-  if(!FLAGS_kernel_path.size() || FLAGS_initramfs_path.size()) {
+  std::string discovered_kernel = fetcher_config.FindCvdFileWithSuffix(kKernelDefaultPath);
+  std::string foreign_kernel = FLAGS_kernel_path.size() ? FLAGS_kernel_path : discovered_kernel;
+  std::string discovered_ramdisk = fetcher_config.FindCvdFileWithSuffix(kInitramfsImg);
+  std::string foreign_ramdisk = FLAGS_initramfs_path.size () ? FLAGS_initramfs_path : discovered_ramdisk;
+  if(!foreign_kernel.size() || foreign_ramdisk.size()) {
     const std::string& vendor_ramdisk_path =
       config->initramfs_path().size() ? config->initramfs_path()
                                       : config->vendor_ramdisk_image_path();
diff --git a/host/libs/config/fetcher_config.cpp b/host/libs/config/fetcher_config.cpp
index d218351..86e16dc 100644
--- a/host/libs/config/fetcher_config.cpp
+++ b/host/libs/config/fetcher_config.cpp
@@ -197,4 +197,20 @@
   return files;
 }
 
+std::string FetcherConfig::FindCvdFileWithSuffix(const std::string& suffix) const {
+  if (!dictionary_->isMember(kCvdFiles)) {
+    return {};
+  }
+  const auto& json_files = (*dictionary_)[kCvdFiles];
+  for (auto it = json_files.begin(); it != json_files.end(); it++) {
+    auto file = it.key().asString();
+    auto expected_pos = file.size() - suffix.size();
+    if (file.rfind(suffix) == expected_pos) {
+      return file;
+    }
+  }
+  LOG(ERROR) << "Could not find file ending in " << suffix;
+  return "";
+}
+
 } // namespace cvd
diff --git a/host/libs/config/fetcher_config.h b/host/libs/config/fetcher_config.h
index 41fd396..825fbc6 100644
--- a/host/libs/config/fetcher_config.h
+++ b/host/libs/config/fetcher_config.h
@@ -78,6 +78,8 @@
 
   bool add_cvd_file(const CvdFile& file, bool override_entry = false);
   std::map<std::string, CvdFile> get_cvd_files() const;
+
+  std::string FindCvdFileWithSuffix(const std::string& suffix) const;
 };
 
 } // namespace cvd