/*
 * 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 "odrefresh.h"

#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sysexits.h>
#include <time.h>
#include <unistd.h>

#include <algorithm>
#include <cerrno>
#include <cstdarg>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <filesystem>
#include <fstream>
#include <functional>
#include <initializer_list>
#include <iosfwd>
#include <iostream>
#include <iterator>
#include <memory>
#include <optional>
#include <ostream>
#include <set>
#include <sstream>
#include <string>
#include <string_view>
#include <system_error>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

#include "android-base/chrono_utils.h"
#include "android-base/file.h"
#include "android-base/function_ref.h"
#include "android-base/logging.h"
#include "android-base/macros.h"
#include "android-base/parseint.h"
#include "android-base/properties.h"
#include "android-base/result.h"
#include "android-base/scopeguard.h"
#include "android-base/stringprintf.h"
#include "android-base/strings.h"
#include "android-modules-utils/sdk_level.h"
#include "arch/instruction_set.h"
#include "base/file_utils.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/os.h"
#include "base/stl_util.h"
#include "base/unix_file/fd_file.h"
#include "com_android_apex.h"
#include "com_android_art.h"
#include "dex/art_dex_file_loader.h"
#include "exec_utils.h"
#include "gc/collector/mark_compact.h"
#include "odr_artifacts.h"
#include "odr_common.h"
#include "odr_config.h"
#include "odr_fs_utils.h"
#include "odr_metrics.h"
#include "odrefresh/odrefresh.h"
#include "tools/cmdline_builder.h"

namespace art {
namespace odrefresh {

namespace {

namespace apex = com::android::apex;
namespace art_apex = com::android::art;

using ::android::base::Basename;
using ::android::base::Dirname;
using ::android::base::Join;
using ::android::base::ParseInt;
using ::android::base::Result;
using ::android::base::ScopeGuard;
using ::android::base::SetProperty;
using ::android::base::Split;
using ::android::base::StringPrintf;
using ::android::base::Timer;
using ::android::modules::sdklevel::IsAtLeastU;
using ::android::modules::sdklevel::IsAtLeastV;
using ::art::tools::CmdlineBuilder;

// Name of cache info file in the ART Apex artifact cache.
constexpr const char* kCacheInfoFile = "cache-info.xml";

// Maximum execution time for odrefresh from start to end.
constexpr time_t kMaximumExecutionSeconds = 480;

// Maximum execution time for any child process spawned.
constexpr time_t kMaxChildProcessSeconds = 120;

constexpr mode_t kFileMode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;

constexpr const char* kFirstBootImageBasename = "boot.art";
constexpr const char* kMinimalBootImageBasename = "boot_minimal.art";

// The default compiler filter for primary boot image.
constexpr const char* kPrimaryCompilerFilter = "speed-profile";

// The compiler filter for boot image mainline extension. We don't have profiles for mainline BCP
// jars, so we always use "verify".
constexpr const char* kMainlineCompilerFilter = "verify";

void EraseFiles(const std::vector<std::unique_ptr<File>>& files) {
  for (auto& file : files) {
    file->Erase(/*unlink=*/true);
  }
}

// Moves `files` to the directory `output_directory_path`.
//
// If any of the files cannot be moved, then all copies of the files are removed from both
// the original location and the output location.
//
// Returns true if all files are moved, false otherwise.
bool MoveOrEraseFiles(const std::vector<std::unique_ptr<File>>& files,
                      std::string_view output_directory_path,
                      android::base::function_ref<int(const char*, unsigned int)> restorecon) {
  std::vector<std::unique_ptr<File>> output_files;
  for (auto& file : files) {
    std::string file_basename(Basename(file->GetPath()));
    std::string output_file_path = ART_FORMAT("{}/{}", output_directory_path, file_basename);
    std::string input_file_path = file->GetPath();

    if (IsAtLeastV()) {
      // Simply rename the existing file. Requires at least V as odrefresh does not have
      // `selinux_android_restorecon` permissions on U and lower.
      if (!file->Rename(output_file_path)) {
        PLOG(ERROR) << "Failed to rename " << QuotePath(input_file_path) << " to "
                    << QuotePath(output_file_path);
        EraseFiles(files);
        return false;
      }

      if (file->FlushCloseOrErase() != 0) {
        PLOG(ERROR) << "Failed to flush and close file " << QuotePath(output_file_path);
        EraseFiles(files);
        return false;
      }

      if (restorecon(output_file_path.c_str(), 0) < 0) {
        LOG(ERROR) << "Failed to set security context for file " << QuotePath(output_file_path);
        EraseFiles(files);
        return false;
      }
    } else {
      // Create a new file in the output directory, copy the input file's data across, then delete
      // the input file.
      output_files.emplace_back(OS::CreateEmptyFileWriteOnly(output_file_path.c_str()));
      if (output_files.back() == nullptr) {
        PLOG(ERROR) << "Failed to open " << QuotePath(output_file_path);
        output_files.pop_back();
        EraseFiles(output_files);
        EraseFiles(files);
        return false;
      }

      if (fchmod(output_files.back()->Fd(), kFileMode) != 0) {
        PLOG(ERROR) << "Could not set file mode on " << QuotePath(output_file_path);
        EraseFiles(output_files);
        EraseFiles(files);
        return false;
      }

      size_t file_bytes = file->GetLength();
      if (!output_files.back()->Copy(file.get(), /*offset=*/0, file_bytes)) {
        PLOG(ERROR) << "Failed to copy " << QuotePath(file->GetPath()) << " to "
                    << QuotePath(output_file_path);
        EraseFiles(output_files);
        EraseFiles(files);
        return false;
      }

      if (!file->Erase(/*unlink=*/true)) {
        PLOG(ERROR) << "Failed to erase " << QuotePath(file->GetPath());
        EraseFiles(output_files);
        EraseFiles(files);
        return false;
      }

      if (output_files.back()->FlushCloseOrErase() != 0) {
        PLOG(ERROR) << "Failed to flush and close file " << QuotePath(output_file_path);
        EraseFiles(output_files);
        EraseFiles(files);
        return false;
      }
    }
  }
  return true;
}

// Gets the `ApexInfo` associated with the currently active ART APEX.
std::optional<apex::ApexInfo> GetArtApexInfo(const std::vector<apex::ApexInfo>& info_list) {
  auto it = std::find_if(info_list.begin(), info_list.end(), [](const apex::ApexInfo& info) {
    return info.getModuleName() == "com.android.art";
  });
  return it != info_list.end() ? std::make_optional(*it) : std::nullopt;
}

// Returns cache provenance information based on the current APEX version and filesystem
// information.
art_apex::ModuleInfo GenerateModuleInfo(const apex::ApexInfo& apex_info) {
  // The lastUpdateMillis is an addition to ApexInfoList.xsd to support samegrade installs.
  int64_t last_update_millis =
      apex_info.hasLastUpdateMillis() ? apex_info.getLastUpdateMillis() : 0;
  return art_apex::ModuleInfo{apex_info.getModuleName(),
                              apex_info.getVersionCode(),
                              apex_info.getVersionName(),
                              last_update_millis};
}

// Returns cache provenance information for all APEXes.
std::vector<art_apex::ModuleInfo> GenerateModuleInfoList(
    const std::vector<apex::ApexInfo>& apex_info_list) {
  std::vector<art_apex::ModuleInfo> module_info_list;
  std::transform(apex_info_list.begin(),
                 apex_info_list.end(),
                 std::back_inserter(module_info_list),
                 GenerateModuleInfo);
  return module_info_list;
}

// Returns a rewritten path based on environment variables for interesting paths.
std::string RewriteParentDirectoryIfNeeded(const std::string& path) {
  if (path.starts_with("/system/")) {
    return GetAndroidRoot() + path.substr(7);
  } else if (path.starts_with("/system_ext/")) {
    return GetSystemExtRoot() + path.substr(11);
  } else {
    return path;
  }
}

template <typename T>
Result<void> CheckComponents(
    const std::vector<T>& expected_components,
    const std::vector<T>& actual_components,
    const std::function<Result<void>(const T& expected, const T& actual)>& custom_checker =
        [](const T&, const T&) -> Result<void> { return {}; }) {
  if (expected_components.size() != actual_components.size()) {
    return Errorf(
        "Component count differs ({} != {})", expected_components.size(), actual_components.size());
  }

  for (size_t i = 0; i < expected_components.size(); ++i) {
    const T& expected = expected_components[i];
    const T& actual = actual_components[i];

    if (expected.getFile() != actual.getFile()) {
      return Errorf(
          "Component {} file differs ('{}' != '{}')", i, expected.getFile(), actual.getFile());
    }

    if (expected.getSize() != actual.getSize()) {
      return Errorf(
          "Component {} size differs ({} != {})", i, expected.getSize(), actual.getSize());
    }

    if (expected.getChecksums() != actual.getChecksums()) {
      return Errorf("Component {} checksums differ ('{}' != '{}')",
                    i,
                    expected.getChecksums(),
                    actual.getChecksums());
    }

    Result<void> result = custom_checker(expected, actual);
    if (!result.ok()) {
      return Errorf("Component {} {}", i, result.error().message());
    }
  }

  return {};
}

Result<void> CheckSystemServerComponents(
    const std::vector<art_apex::SystemServerComponent>& expected_components,
    const std::vector<art_apex::SystemServerComponent>& actual_components) {
  return CheckComponents<art_apex::SystemServerComponent>(
      expected_components,
      actual_components,
      [](const art_apex::SystemServerComponent& expected,
         const art_apex::SystemServerComponent& actual) -> Result<void> {
        if (expected.getIsInClasspath() != actual.getIsInClasspath()) {
          return Errorf("isInClasspath differs ({} != {})",
                        expected.getIsInClasspath(),
                        actual.getIsInClasspath());
        }

        return {};
      });
}

template <typename T>
std::vector<T> GenerateComponents(
    const std::vector<std::string>& jars,
    const std::function<T(const std::string& path, uint64_t size, const std::string& checksum)>&
        custom_generator) {
  std::vector<T> components;

  for (const std::string& path : jars) {
    std::string actual_path = RewriteParentDirectoryIfNeeded(path);
    struct stat sb;
    if (stat(actual_path.c_str(), &sb) == -1) {
      PLOG(ERROR) << "Failed to stat component: " << QuotePath(actual_path);
      return {};
    }

    std::optional<uint32_t> checksum;
    std::string error_msg;
    ArtDexFileLoader dex_loader(actual_path);
    if (!dex_loader.GetMultiDexChecksum(&checksum, &error_msg)) {
      LOG(ERROR) << "Failed to get multi-dex checksum: " << error_msg;
      return {};
    }

    const std::string checksum_str =
        checksum.has_value() ? StringPrintf("%08x", checksum.value()) : std::string();

    Result<T> component = custom_generator(path, static_cast<uint64_t>(sb.st_size), checksum_str);
    if (!component.ok()) {
      LOG(ERROR) << "Failed to generate component: " << component.error();
      return {};
    }

    components.push_back(*std::move(component));
  }

  return components;
}

std::vector<art_apex::Component> GenerateComponents(const std::vector<std::string>& jars) {
  return GenerateComponents<art_apex::Component>(
      jars, [](const std::string& path, uint64_t size, const std::string& checksum) {
        return art_apex::Component{path, size, checksum};
      });
}

// Checks whether a group of artifacts exists. Returns true if all are present, false otherwise.
// If `checked_artifacts` is present, adds checked artifacts to `checked_artifacts`.
bool ArtifactsExist(const OdrArtifacts& artifacts,
                    bool check_art_file,
                    /*out*/ std::string* error_msg,
                    /*out*/ std::vector<std::string>* checked_artifacts = nullptr) {
  std::vector<const char*> paths{artifacts.OatPath().c_str(), artifacts.VdexPath().c_str()};
  if (check_art_file) {
    paths.push_back(artifacts.ImagePath().c_str());
  }
  for (const char* path : paths) {
    if (!OS::FileExists(path)) {
      if (errno == EACCES) {
        PLOG(ERROR) << "Failed to stat() " << path;
      }
      *error_msg = "Missing file: " + QuotePath(path);
      return false;
    }
  }
  // This should be done after checking all artifacts because either all of them are valid or none
  // of them is valid.
  if (checked_artifacts != nullptr) {
    for (const char* path : paths) {
      checked_artifacts->emplace_back(path);
    }
  }
  return true;
}

void AddDex2OatCommonOptions(/*inout*/ CmdlineBuilder& args) {
  args.Add("--android-root=out/empty");
  args.Add("--no-abort-on-hard-verifier-error");
  args.Add("--no-abort-on-soft-verifier-error");
  args.Add("--compilation-reason=boot");
  args.Add("--image-format=lz4");
  args.Add("--force-determinism");
  args.Add("--resolve-startup-const-strings=true");

  // Avoid storing dex2oat cmdline in oat header. We want to be sure that the compiled artifacts
  // are identical regardless of where the compilation happened. But some of the cmdline flags tends
  // to be unstable, e.g. those contains FD numbers. To avoid the problem, the whole cmdline is not
  // added to the oat header.
  args.Add("--avoid-storing-invocation");
}

bool IsCpuSetSpecValid(const std::string& cpu_set) {
  for (const std::string& str : Split(cpu_set, ",")) {
    int id;
    if (!ParseInt(str, &id, 0)) {
      return false;
    }
  }
  return true;
}

Result<void> AddDex2OatConcurrencyArguments(/*inout*/ CmdlineBuilder& args,
                                            bool is_compilation_os,
                                            const OdrSystemProperties& system_properties) {
  std::string threads;
  if (is_compilation_os) {
    threads = system_properties.GetOrEmpty("dalvik.vm.background-dex2oat-threads",
                                           "dalvik.vm.dex2oat-threads");
  } else {
    threads = system_properties.GetOrEmpty("dalvik.vm.boot-dex2oat-threads");
  }
  args.AddIfNonEmpty("-j%s", threads);

  std::string cpu_set;
  if (is_compilation_os) {
    cpu_set = system_properties.GetOrEmpty("dalvik.vm.background-dex2oat-cpu-set",
                                           "dalvik.vm.dex2oat-cpu-set");
  } else {
    cpu_set = system_properties.GetOrEmpty("dalvik.vm.boot-dex2oat-cpu-set");
  }
  if (!cpu_set.empty()) {
    if (!IsCpuSetSpecValid(cpu_set)) {
      return Errorf("Invalid CPU set spec '{}'", cpu_set);
    }
    args.Add("--cpu-set=%s", cpu_set);
  }

  return {};
}

void AddDex2OatDebugInfo(/*inout*/ CmdlineBuilder& args) {
  args.Add("--generate-mini-debug-info");
  args.Add("--strip");
}

void AddDex2OatInstructionSet(/*inout*/ CmdlineBuilder& args,
                              InstructionSet isa,
                              const OdrSystemProperties& system_properties) {
  const char* isa_str = GetInstructionSetString(isa);
  args.Add("--instruction-set=%s", isa_str);
  std::string features_prop = ART_FORMAT("dalvik.vm.isa.{}.features", isa_str);
  args.AddIfNonEmpty("--instruction-set-features=%s", system_properties.GetOrEmpty(features_prop));
  std::string variant_prop = ART_FORMAT("dalvik.vm.isa.{}.variant", isa_str);
  args.AddIfNonEmpty("--instruction-set-variant=%s", system_properties.GetOrEmpty(variant_prop));
}

// Returns true if any profile has been added, or false if no profile exists, or error if any error
// occurred.
Result<bool> AddDex2OatProfile(
    /*inout*/ CmdlineBuilder& args,
    /*inout*/ std::vector<std::unique_ptr<File>>& output_files,
    const std::vector<std::string>& profile_paths) {
  bool has_any_profile = false;
  for (const std::string& path : profile_paths) {
    std::unique_ptr<File> profile_file(OS::OpenFileForReading(path.c_str()));
    if (profile_file != nullptr) {
      args.Add("--profile-file-fd=%d", profile_file->Fd());
      output_files.emplace_back(std::move(profile_file));
      has_any_profile = true;
    } else if (errno != ENOENT) {
      return ErrnoErrorf("Failed to open profile file '{}'", path);
    }
  }
  return has_any_profile;
}

Result<void> AddBootClasspathFds(/*inout*/ CmdlineBuilder& args,
                                 /*inout*/ std::vector<std::unique_ptr<File>>& output_files,
                                 const std::vector<std::string>& bcp_jars) {
  std::vector<std::string> bcp_fds;
  for (const std::string& jar : bcp_jars) {
    // Special treatment for Compilation OS. JARs in staged APEX may not be visible to Android, and
    // may only be visible in the VM where the staged APEX is mounted. On the contrary, JARs in
    // /system is not available by path in the VM, and can only made available via (remote) FDs.
    if (jar.starts_with("/apex/")) {
      bcp_fds.emplace_back("-1");
    } else {
      std::string actual_path = RewriteParentDirectoryIfNeeded(jar);
      std::unique_ptr<File> jar_file(OS::OpenFileForReading(actual_path.c_str()));
      if (jar_file == nullptr) {
        return ErrnoErrorf("Failed to open a BCP jar '{}'", actual_path);
      }
      bcp_fds.push_back(std::to_string(jar_file->Fd()));
      output_files.push_back(std::move(jar_file));
    }
  }
  args.AddRuntime("-Xbootclasspathfds:%s", Join(bcp_fds, ':'));
  return {};
}

Result<void> AddCacheInfoFd(/*inout*/ CmdlineBuilder& args,
                            /*inout*/ std::vector<std::unique_ptr<File>>& readonly_files_raii,
                            const std::string& cache_info_filename) {
  std::unique_ptr<File> cache_info_file(OS::OpenFileForReading(cache_info_filename.c_str()));
  if (cache_info_file == nullptr) {
    return ErrnoErrorf("Failed to open a cache info file '{}'", cache_info_filename);
  }

  args.Add("--cache-info-fd=%d", cache_info_file->Fd());
  readonly_files_raii.push_back(std::move(cache_info_file));
  return {};
}

std::string GetBootImageComponentBasename(const std::string& jar_path, bool is_first_jar) {
  if (is_first_jar) {
    return kFirstBootImageBasename;
  }
  std::string jar_name = Basename(jar_path);
  return "boot-" + ReplaceFileExtension(jar_name, kArtExtension);
}

Result<void> AddCompiledBootClasspathFdsIfAny(
    /*inout*/ CmdlineBuilder& args,
    /*inout*/ std::vector<std::unique_ptr<File>>& output_files,
    const std::vector<std::string>& bcp_jars,
    InstructionSet isa,
    const std::vector<std::string>& boot_image_locations) {
  std::vector<std::string> bcp_image_fds;
  std::vector<std::string> bcp_oat_fds;
  std::vector<std::string> bcp_vdex_fds;
  std::vector<std::unique_ptr<File>> opened_files;
  bool added_any = false;
  std::string artifact_dir;
  for (size_t i = 0; i < bcp_jars.size(); i++) {
    const std::string& jar = bcp_jars[i];
    std::string basename = GetBootImageComponentBasename(jar, /*is_first_jar=*/i == 0);
    // If there is an entry in `boot_image_locations` for the current jar, update `artifact_dir` for
    // the current jar and the subsequent jars.
    for (const std::string& location : boot_image_locations) {
      if (Basename(location) == basename) {
        artifact_dir = Dirname(location);
        break;
      }
    }
    CHECK(!artifact_dir.empty());
    std::string image_path = ART_FORMAT("{}/{}", artifact_dir, basename);
    image_path = GetSystemImageFilename(image_path.c_str(), isa);
    std::unique_ptr<File> image_file(OS::OpenFileForReading(image_path.c_str()));
    if (image_file != nullptr) {
      bcp_image_fds.push_back(std::to_string(image_file->Fd()));
      opened_files.push_back(std::move(image_file));
      added_any = true;
    } else if (errno == ENOENT) {
      bcp_image_fds.push_back("-1");
    } else {
      return ErrnoErrorf("Failed to open boot image file '{}'", image_path);
    }

    std::string oat_path = ReplaceFileExtension(image_path, kOatExtension);
    std::unique_ptr<File> oat_file(OS::OpenFileForReading(oat_path.c_str()));
    if (oat_file != nullptr) {
      bcp_oat_fds.push_back(std::to_string(oat_file->Fd()));
      opened_files.push_back(std::move(oat_file));
      added_any = true;
    } else if (errno == ENOENT) {
      bcp_oat_fds.push_back("-1");
    } else {
      return ErrnoErrorf("Failed to open boot image file '{}'", oat_path);
    }

    std::string vdex_path = ReplaceFileExtension(image_path, kVdexExtension);
    std::unique_ptr<File> vdex_file(OS::OpenFileForReading(vdex_path.c_str()));
    if (vdex_file != nullptr) {
      bcp_vdex_fds.push_back(std::to_string(vdex_file->Fd()));
      opened_files.push_back(std::move(vdex_file));
      added_any = true;
    } else if (errno == ENOENT) {
      bcp_vdex_fds.push_back("-1");
    } else {
      return ErrnoErrorf("Failed to open boot image file '{}'", vdex_path);
    }
  }
  // Add same amount of FDs as BCP JARs, or none.
  if (added_any) {
    std::move(opened_files.begin(), opened_files.end(), std::back_inserter(output_files));

    args.AddRuntime("-Xbootclasspathimagefds:%s", Join(bcp_image_fds, ':'));
    args.AddRuntime("-Xbootclasspathoatfds:%s", Join(bcp_oat_fds, ':'));
    args.AddRuntime("-Xbootclasspathvdexfds:%s", Join(bcp_vdex_fds, ':'));
  }

  return {};
}

std::string GetStagingLocation(const std::string& staging_dir, const std::string& path) {
  return staging_dir + "/" + Basename(path);
}

WARN_UNUSED bool CheckCompilationSpace() {
  // Check the available storage space against an arbitrary threshold because dex2oat does not
  // report when it runs out of storage space and we do not want to completely fill
  // the users data partition.
  //
  // We do not have a good way of pre-computing the required space for a compilation step, but
  // typically observe no more than 48MiB as the largest total size of AOT artifacts for a single
  // dex2oat invocation, which includes an image file, an executable file, and a verification data
  // file.
  static constexpr uint64_t kMinimumSpaceForCompilation = 48 * 1024 * 1024;

  uint64_t bytes_available;
  const std::string& art_apex_data_path = GetArtApexData();
  if (!GetFreeSpace(art_apex_data_path, &bytes_available)) {
    return false;
  }

  if (bytes_available < kMinimumSpaceForCompilation) {
    LOG(WARNING) << "Low space for " << QuotePath(art_apex_data_path) << " (" << bytes_available
                 << " bytes)";
    return false;
  }

  return true;
}

bool HasVettedDeviceSystemServerProfiles() {
  // While system_server profiles were bundled on the device prior to U+, they were not used by
  // default or rigorously tested, so we cannot vouch for their efficacy.
  static const bool kDeviceIsAtLeastU = IsAtLeastU();
  return kDeviceIsAtLeastU;
}

}  // namespace

CompilationOptions CompilationOptions::CompileAll(const OnDeviceRefresh& odr) {
  CompilationOptions options;
  for (InstructionSet isa : odr.Config().GetBootClasspathIsas()) {
    options.boot_images_to_generate_for_isas.emplace_back(
        isa, BootImages{.primary_boot_image = true, .boot_image_mainline_extension = true});
  }
  options.system_server_jars_to_compile = odr.AllSystemServerJars();
  return options;
}

int BootImages::Count() const {
  int count = 0;
  if (primary_boot_image) {
    count++;
  }
  if (boot_image_mainline_extension) {
    count++;
  }
  return count;
}

OdrMetrics::BcpCompilationType BootImages::GetTypeForMetrics() const {
  if (primary_boot_image && boot_image_mainline_extension) {
    return OdrMetrics::BcpCompilationType::kPrimaryAndMainline;
  }
  if (boot_image_mainline_extension) {
    return OdrMetrics::BcpCompilationType::kMainline;
  }
  LOG(FATAL) << "Unexpected BCP compilation type";
  UNREACHABLE();
}

int CompilationOptions::CompilationUnitCount() const {
  int count = 0;
  for (const auto& [isa, boot_images] : boot_images_to_generate_for_isas) {
    count += boot_images.Count();
  }
  count += system_server_jars_to_compile.size();
  return count;
}

OnDeviceRefresh::OnDeviceRefresh(
    const OdrConfig& config,
    android::base::function_ref<int(const char*, const char*)> setfilecon,
    android::base::function_ref<int(const char*, unsigned int)> restorecon)
    : OnDeviceRefresh(config,
                      setfilecon,
                      restorecon,
                      config.GetArtifactDirectory() + "/" + kCacheInfoFile,
                      std::make_unique<ExecUtils>(),
                      CheckCompilationSpace) {}

OnDeviceRefresh::OnDeviceRefresh(
    const OdrConfig& config,
    android::base::function_ref<int(const char*, const char*)> setfilecon,
    android::base::function_ref<int(const char*, unsigned int)> restorecon,
    const std::string& cache_info_filename,
    std::unique_ptr<ExecUtils> exec_utils,
    android::base::function_ref<bool()> check_compilation_space)
    : config_(config),
      cache_info_filename_(cache_info_filename),
      start_time_(time(nullptr)),
      exec_utils_(std::move(exec_utils)),
      check_compilation_space_(check_compilation_space),
      setfilecon_(setfilecon),
      restorecon_(restorecon) {
  // Updatable APEXes should not have DEX files in the DEX2OATBOOTCLASSPATH. At the time of
  // writing i18n is a non-updatable APEX and so does appear in the DEX2OATBOOTCLASSPATH.
  dex2oat_boot_classpath_jars_ = Split(config_.GetDex2oatBootClasspath(), ":");

  all_systemserver_jars_ = Split(config_.GetSystemServerClasspath(), ":");
  systemserver_classpath_jars_ = {all_systemserver_jars_.begin(), all_systemserver_jars_.end()};
  boot_classpath_jars_ = Split(config_.GetBootClasspath(), ":");
  std::string standalone_system_server_jars_str = config_.GetStandaloneSystemServerJars();
  if (!standalone_system_server_jars_str.empty()) {
    std::vector<std::string> standalone_systemserver_jars =
        Split(standalone_system_server_jars_str, ":");
    std::move(standalone_systemserver_jars.begin(),
              standalone_systemserver_jars.end(),
              std::back_inserter(all_systemserver_jars_));
  }
}

time_t OnDeviceRefresh::GetExecutionTimeUsed() const { return time(nullptr) - start_time_; }

time_t OnDeviceRefresh::GetExecutionTimeRemaining() const {
  return std::max(static_cast<time_t>(0),
                  kMaximumExecutionSeconds - GetExecutionTimeUsed());
}

time_t OnDeviceRefresh::GetSubprocessTimeout() const {
  return std::min(GetExecutionTimeRemaining(), kMaxChildProcessSeconds);
}

Result<std::string> OnDeviceRefresh::CreateStagingDirectory() const {
  std::string staging_dir = GetArtApexData() + "/staging";

  std::error_code ec;
  if (std::filesystem::exists(staging_dir, ec)) {
    if (std::filesystem::remove_all(staging_dir, ec) < 0) {
      return Errorf(
          "Could not remove existing staging directory '{}': {}", staging_dir, ec.message());
    }
  }

  if (mkdir(staging_dir.c_str(), S_IRWXU) != 0) {
    return ErrnoErrorf("Could not create staging directory '{}'", staging_dir);
  }

  if (setfilecon_(staging_dir.c_str(), "u:object_r:apex_art_staging_data_file:s0") != 0) {
    return ErrnoErrorf("Could not set label on staging directory '{}'", staging_dir);
  }

  return staging_dir;
}

std::optional<std::vector<apex::ApexInfo>> OnDeviceRefresh::GetApexInfoList() const {
  std::optional<apex::ApexInfoList> info_list =
      apex::readApexInfoList(config_.GetApexInfoListFile().c_str());
  if (!info_list.has_value()) {
    return std::nullopt;
  }

  // We are only interested in active APEXes that contain compilable JARs.
  std::unordered_set<std::string_view> relevant_apexes;
  relevant_apexes.reserve(info_list->getApexInfo().size());
  for (const std::vector<std::string>* jar_list :
       {&all_systemserver_jars_, &boot_classpath_jars_}) {
    for (const std::string& jar : *jar_list) {
      std::string_view apex = ApexNameFromLocation(jar);
      if (!apex.empty()) {
        relevant_apexes.insert(apex);
      }
    }
  }
  // The ART APEX is always relevant no matter it contains any compilable JAR or not, because it
  // contains the runtime.
  relevant_apexes.insert("com.android.art");

  std::vector<apex::ApexInfo> filtered_info_list;
  std::copy_if(info_list->getApexInfo().begin(),
               info_list->getApexInfo().end(),
               std::back_inserter(filtered_info_list),
               [&](const apex::ApexInfo& info) {
                 return info.getIsActive() && relevant_apexes.count(info.getModuleName()) != 0;
               });
  return filtered_info_list;
}

Result<art_apex::CacheInfo> OnDeviceRefresh::ReadCacheInfo() const {
  std::optional<art_apex::CacheInfo> cache_info = art_apex::read(cache_info_filename_.c_str());
  if (!cache_info.has_value()) {
    if (errno != 0) {
      return ErrnoErrorf("Failed to load {}", QuotePath(cache_info_filename_));
    } else {
      return Errorf("Failed to parse {}", QuotePath(cache_info_filename_));
    }
  }
  return cache_info.value();
}

// This function has a large stack frame, so avoid inlining it because doing so
// could push its caller's stack frame over the limit. See b/330851312.
NO_INLINE Result<void> OnDeviceRefresh::WriteCacheInfo() const {
  if (OS::FileExists(cache_info_filename_.c_str())) {
    if (unlink(cache_info_filename_.c_str()) != 0) {
      return ErrnoErrorf("Failed to unlink file {}", QuotePath(cache_info_filename_));
    }
  }

  std::string dir_name = Dirname(cache_info_filename_);
  if (!EnsureDirectoryExists(dir_name)) {
    return Errorf("Could not create directory {}", QuotePath(dir_name));
  }

  std::vector<art_apex::KeyValuePair> system_properties;
  for (const auto& [key, value] : config_.GetSystemProperties()) {
    if (!art::ContainsElement(kIgnoredSystemProperties, key)) {
      system_properties.emplace_back(key, value);
    }
  }

  std::optional<std::vector<apex::ApexInfo>> apex_info_list = GetApexInfoList();
  if (!apex_info_list.has_value()) {
    return Errorf("Could not update {}: no APEX info", QuotePath(cache_info_filename_));
  }

  std::optional<apex::ApexInfo> art_apex_info = GetArtApexInfo(apex_info_list.value());
  if (!art_apex_info.has_value()) {
    return Errorf("Could not update {}: no ART APEX info", QuotePath(cache_info_filename_));
  }

  art_apex::ModuleInfo art_module_info = GenerateModuleInfo(art_apex_info.value());
  std::vector<art_apex::ModuleInfo> module_info_list =
      GenerateModuleInfoList(apex_info_list.value());

  std::vector<art_apex::Component> bcp_components = GenerateBootClasspathComponents();
  std::vector<art_apex::Component> dex2oat_bcp_components =
      GenerateDex2oatBootClasspathComponents();
  std::vector<art_apex::SystemServerComponent> system_server_components =
      GenerateSystemServerComponents();

  std::ofstream out(cache_info_filename_.c_str());
  if (out.fail()) {
    return ErrnoErrorf("Could not create cache info file {}", QuotePath(cache_info_filename_));
  }

  std::unique_ptr<art_apex::CacheInfo> info(new art_apex::CacheInfo(
      {art_apex::KeyValuePairList(system_properties)},
      {art_module_info},
      {art_apex::ModuleInfoList(module_info_list)},
      {art_apex::Classpath(bcp_components)},
      {art_apex::Classpath(dex2oat_bcp_components)},
      {art_apex::SystemServerComponents(system_server_components)},
      config_.GetCompilationOsMode() ? std::make_optional(true) : std::nullopt));

  art_apex::write(out, *info);
  out.close();
  if (out.fail()) {
    return ErrnoErrorf("Could not write cache info file {}", QuotePath(cache_info_filename_));
  }

  return {};
}

static void ReportNextBootAnimationProgress(uint32_t current_compilation,
                                            uint32_t number_of_compilations) {
  // We arbitrarily show progress until 90%, expecting that our compilations take a large chunk of
  // boot time.
  uint32_t value = (90 * current_compilation) / number_of_compilations;
  SetProperty("service.bootanim.progress", std::to_string(value));
}

std::vector<art_apex::Component> OnDeviceRefresh::GenerateBootClasspathComponents() const {
  return GenerateComponents(boot_classpath_jars_);
}

std::vector<art_apex::Component> OnDeviceRefresh::GenerateDex2oatBootClasspathComponents() const {
  return GenerateComponents(dex2oat_boot_classpath_jars_);
}

std::vector<art_apex::SystemServerComponent> OnDeviceRefresh::GenerateSystemServerComponents()
    const {
  return GenerateComponents<art_apex::SystemServerComponent>(
      all_systemserver_jars_,
      [&](const std::string& path, uint64_t size, const std::string& checksum) {
        bool isInClasspath = ContainsElement(systemserver_classpath_jars_, path);
        return art_apex::SystemServerComponent{path, size, checksum, isInClasspath};
      });
}

std::vector<std::string> OnDeviceRefresh::GetArtBcpJars() const {
  std::string art_root = GetArtRoot() + "/";
  std::vector<std::string> art_bcp_jars;
  for (const std::string& jar : dex2oat_boot_classpath_jars_) {
    if (jar.starts_with(art_root)) {
      art_bcp_jars.push_back(jar);
    }
  }
  CHECK(!art_bcp_jars.empty());
  return art_bcp_jars;
}

std::vector<std::string> OnDeviceRefresh::GetFrameworkBcpJars() const {
  std::string art_root = GetArtRoot() + "/";
  std::vector<std::string> framework_bcp_jars;
  for (const std::string& jar : dex2oat_boot_classpath_jars_) {
    if (!jar.starts_with(art_root)) {
      framework_bcp_jars.push_back(jar);
    }
  }
  CHECK(!framework_bcp_jars.empty());
  return framework_bcp_jars;
}

std::vector<std::string> OnDeviceRefresh::GetMainlineBcpJars() const {
  // Elements in `dex2oat_boot_classpath_jars_` should be at the beginning of
  // `boot_classpath_jars_`, followed by mainline BCP jars.
  CHECK_LT(dex2oat_boot_classpath_jars_.size(), boot_classpath_jars_.size());
  CHECK(std::equal(dex2oat_boot_classpath_jars_.begin(),
                   dex2oat_boot_classpath_jars_.end(),
                   boot_classpath_jars_.begin(),
                   boot_classpath_jars_.begin() + dex2oat_boot_classpath_jars_.size()));
  return {boot_classpath_jars_.begin() + dex2oat_boot_classpath_jars_.size(),
          boot_classpath_jars_.end()};
}

std::string OnDeviceRefresh::GetPrimaryBootImage(bool on_system, bool minimal) const {
  DCHECK(!on_system || !minimal);
  const char* basename = minimal ? kMinimalBootImageBasename : kFirstBootImageBasename;
  if (on_system) {
    // Typically "/system/framework/boot.art".
    return GetPrebuiltPrimaryBootImageDir() + "/" + basename;
  } else {
    // Typically "/data/misc/apexdata/com.android.art/dalvik-cache/boot.art".
    return config_.GetArtifactDirectory() + "/" + basename;
  }
}

std::string OnDeviceRefresh::GetPrimaryBootImagePath(bool on_system,
                                                     bool minimal,
                                                     InstructionSet isa) const {
  // Typically "/data/misc/apexdata/com.android.art/dalvik-cache/<isa>/boot.art".
  return GetSystemImageFilename(GetPrimaryBootImage(on_system, minimal).c_str(), isa);
}

std::string OnDeviceRefresh::GetSystemBootImageFrameworkExtension() const {
  std::vector<std::string> framework_bcp_jars = GetFrameworkBcpJars();
  std::string basename =
      GetBootImageComponentBasename(framework_bcp_jars[0], /*is_first_jar=*/false);
  // Typically "/system/framework/boot-framework.art".
  return ART_FORMAT("{}/framework/{}", GetAndroidRoot(), basename);
}

std::string OnDeviceRefresh::GetSystemBootImageFrameworkExtensionPath(InstructionSet isa) const {
  // Typically "/system/framework/<isa>/boot-framework.art".
  return GetSystemImageFilename(GetSystemBootImageFrameworkExtension().c_str(), isa);
}

std::string OnDeviceRefresh::GetBootImageMainlineExtension(bool on_system) const {
  std::vector<std::string> mainline_bcp_jars = GetMainlineBcpJars();
  std::string basename =
      GetBootImageComponentBasename(mainline_bcp_jars[0], /*is_first_jar=*/false);
  if (on_system) {
    // Typically "/system/framework/boot-framework-adservices.art".
    return ART_FORMAT("{}/framework/{}", GetAndroidRoot(), basename);
  } else {
    // Typically "/data/misc/apexdata/com.android.art/dalvik-cache/boot-framework-adservices.art".
    return ART_FORMAT("{}/{}", config_.GetArtifactDirectory(), basename);
  }
}

std::string OnDeviceRefresh::GetBootImageMainlineExtensionPath(bool on_system,
                                                               InstructionSet isa) const {
  // Typically
  // "/data/misc/apexdata/com.android.art/dalvik-cache/<isa>/boot-framework-adservices.art".
  return GetSystemImageFilename(GetBootImageMainlineExtension(on_system).c_str(), isa);
}

std::vector<std::string> OnDeviceRefresh::GetBestBootImages(InstructionSet isa,
                                                            bool include_mainline_extension) const {
  std::vector<std::string> locations;
  std::string unused_error_msg;
  bool primary_on_data = false;
  if (PrimaryBootImageExist(
          /*on_system=*/false, /*minimal=*/false, isa, &unused_error_msg)) {
    primary_on_data = true;
    locations.push_back(GetPrimaryBootImage(/*on_system=*/false, /*minimal=*/false));
  } else {
    locations.push_back(GetPrimaryBootImage(/*on_system=*/true, /*minimal=*/false));
    if (!IsAtLeastU()) {
      // Prior to U, there was a framework extension.
      locations.push_back(GetSystemBootImageFrameworkExtension());
    }
  }
  if (include_mainline_extension) {
    if (BootImageMainlineExtensionExist(/*on_system=*/false, isa, &unused_error_msg)) {
      locations.push_back(GetBootImageMainlineExtension(/*on_system=*/false));
    } else {
      // If the primary boot image is on /data, it means we have regenerated all boot images, so the
      // mainline extension must be on /data too.
      CHECK(!primary_on_data)
          << "Mainline extension not found while primary boot image is on /data";
      locations.push_back(GetBootImageMainlineExtension(/*on_system=*/true));
    }
  }
  return locations;
}

std::string OnDeviceRefresh::GetSystemServerImagePath(bool on_system,
                                                      const std::string& jar_path) const {
  if (on_system) {
    if (LocationIsOnApex(jar_path)) {
      return GetSystemOdexFilenameForApex(jar_path, config_.GetSystemServerIsa());
    }
    std::string jar_name = Basename(jar_path);
    std::string image_name = ReplaceFileExtension(jar_name, kArtExtension);
    const char* isa_str = GetInstructionSetString(config_.GetSystemServerIsa());
    // Typically "/system/framework/oat/<isa>/services.art".
    return ART_FORMAT("{}/oat/{}/{}", Dirname(jar_path), isa_str, image_name);
  } else {
    // Typically
    // "/data/misc/apexdata/.../dalvik-cache/<isa>/system@framework@services.jar@classes.art".
    const std::string image = GetApexDataImage(jar_path);
    return GetSystemImageFilename(image.c_str(), config_.GetSystemServerIsa());
  }
}

WARN_UNUSED bool OnDeviceRefresh::RemoveArtifactsDirectory() const {
  if (config_.GetDryRun()) {
    LOG(INFO) << "Directory " << QuotePath(config_.GetArtifactDirectory())
              << " and contents would be removed (dry-run).";
    return true;
  }
  return RemoveDirectory(config_.GetArtifactDirectory());
}

WARN_UNUSED bool OnDeviceRefresh::PrimaryBootImageExist(
    bool on_system,
    bool minimal,
    InstructionSet isa,
    /*out*/ std::string* error_msg,
    /*out*/ std::vector<std::string>* checked_artifacts) const {
  std::string path = GetPrimaryBootImagePath(on_system, minimal, isa);
  OdrArtifacts artifacts = OdrArtifacts::ForBootImage(path);
  if (!ArtifactsExist(artifacts, /*check_art_file=*/true, error_msg, checked_artifacts)) {
    return false;
  }
  // Prior to U, there was a split between the primary boot image and the extension on /system, so
  // they need to be checked separately. This does not apply to the boot image on /data.
  if (on_system && !IsAtLeastU()) {
    std::string extension_path = GetSystemBootImageFrameworkExtensionPath(isa);
    OdrArtifacts extension_artifacts = OdrArtifacts::ForBootImage(extension_path);
    if (!ArtifactsExist(
            extension_artifacts, /*check_art_file=*/true, error_msg, checked_artifacts)) {
      return false;
    }
  }
  return true;
}

WARN_UNUSED bool OnDeviceRefresh::BootImageMainlineExtensionExist(
    bool on_system,
    InstructionSet isa,
    /*out*/ std::string* error_msg,
    /*out*/ std::vector<std::string>* checked_artifacts) const {
  std::string path = GetBootImageMainlineExtensionPath(on_system, isa);
  OdrArtifacts artifacts = OdrArtifacts::ForBootImage(path);
  return ArtifactsExist(artifacts, /*check_art_file=*/true, error_msg, checked_artifacts);
}

bool OnDeviceRefresh::SystemServerArtifactsExist(
    bool on_system,
    /*out*/ std::string* error_msg,
    /*out*/ std::set<std::string>* jars_missing_artifacts,
    /*out*/ std::vector<std::string>* checked_artifacts) const {
  for (const std::string& jar_path : all_systemserver_jars_) {
    const std::string image_location = GetSystemServerImagePath(on_system, jar_path);
    const OdrArtifacts artifacts = OdrArtifacts::ForSystemServer(image_location);
    // .art files are optional and are not generated for all jars by the build system.
    const bool check_art_file = !on_system;
    std::string error_msg_tmp;
    if (!ArtifactsExist(artifacts, check_art_file, &error_msg_tmp, checked_artifacts)) {
      jars_missing_artifacts->insert(jar_path);
      *error_msg = error_msg->empty() ? error_msg_tmp : *error_msg + "\n" + error_msg_tmp;
    }
  }
  return jars_missing_artifacts->empty();
}

WARN_UNUSED bool OnDeviceRefresh::CheckSystemPropertiesAreDefault() const {
  // We don't have to check properties that match `kCheckedSystemPropertyPrefixes` here because none
  // of them is persistent. This only applies when `cache-info.xml` does not exist. When
  // `cache-info.xml` exists, we call `CheckSystemPropertiesHaveNotChanged` instead.
  DCHECK(std::none_of(std::begin(kCheckedSystemPropertyPrefixes),
                      std::end(kCheckedSystemPropertyPrefixes),
                      [](std::string_view prefix) { return prefix.starts_with("persist."); }));

  const OdrSystemProperties& system_properties = config_.GetSystemProperties();

  for (const SystemPropertyConfig& system_property_config : *kSystemProperties.get()) {
    // Note that the `kSystemPropertySystemServerCompilerFilterOverride` property has an empty
    // default value, so we use the `GetOrNull` method and check against nullopt
    std::optional<std::string> property = system_properties.GetOrNull(system_property_config.name);
    DCHECK(property.has_value()) << "Property " << system_property_config.name
                                 << " does not exist in system properties map!";

    if (*property != system_property_config.default_value) {
      LOG(INFO) << "System property " << system_property_config.name << " has a non-default value ("
                << *property << ").";
      return false;
    }
  }

  return true;
}

WARN_UNUSED bool OnDeviceRefresh::CheckSystemPropertiesHaveNotChanged(
    const art_apex::CacheInfo& cache_info) const {
  std::unordered_map<std::string, std::string> cached_system_properties;
  std::unordered_set<std::string> checked_properties;

  const art_apex::KeyValuePairList* list = cache_info.getFirstSystemProperties();
  if (list == nullptr) {
    // This should never happen. We have already checked the ART module version, and the cache
    // info is generated by the latest version of the ART module if it exists.
    LOG(ERROR) << "Missing system properties from cache-info.";
    return false;
  }

  for (const art_apex::KeyValuePair& pair : list->getItem()) {
    cached_system_properties[pair.getK()] = pair.getV();
    checked_properties.insert(pair.getK());
  }

  const OdrSystemProperties& system_properties = config_.GetSystemProperties();

  for (const auto& [key, value] : system_properties) {
    if (!art::ContainsElement(kIgnoredSystemProperties, key)) {
      checked_properties.insert(key);
    }
  }

  for (const std::string& name : checked_properties) {
    std::string property = system_properties.GetOrEmpty(name);
    std::string cached_property = cached_system_properties[name];

    if (property != cached_property) {
      LOG(INFO) << "System property " << name << " value changed (before: \"" << cached_property
                << "\", now: \"" << property << "\").";
      return false;
    }
  }

  return true;
}

WARN_UNUSED bool OnDeviceRefresh::CheckBuildUserfaultFdGc() const {
  bool build_enable_uffd_gc =
      config_.GetSystemProperties().GetBool("ro.dalvik.vm.enable_uffd_gc", /*default_value=*/false);
  bool is_at_most_u = !IsAtLeastV();
  bool kernel_supports_uffd = KernelSupportsUffd();
  if (!art::odrefresh::CheckBuildUserfaultFdGc(
          build_enable_uffd_gc, is_at_most_u, kernel_supports_uffd)) {
    // Normally, this should not happen. If this happens, the system image was probably built with a
    // wrong PRODUCT_ENABLE_UFFD_GC flag.
    LOG(WARNING) << ART_FORMAT(
        "Userfaultfd GC check failed (build_enable_uffd_gc: {}, is_at_most_u: {}, "
        "kernel_supports_uffd: {}).",
        build_enable_uffd_gc,
        is_at_most_u,
        kernel_supports_uffd);
    return false;
  }
  return true;
}

WARN_UNUSED PreconditionCheckResult OnDeviceRefresh::CheckPreconditionForSystem(
    const std::vector<apex::ApexInfo>& apex_info_list) const {
  if (!CheckSystemPropertiesAreDefault()) {
    return PreconditionCheckResult::NoneOk(OdrMetrics::Trigger::kApexVersionMismatch);
  }

  if (!CheckBuildUserfaultFdGc()) {
    return PreconditionCheckResult::NoneOk(OdrMetrics::Trigger::kApexVersionMismatch);
  }

  std::optional<apex::ApexInfo> art_apex_info = GetArtApexInfo(apex_info_list);
  if (!art_apex_info.has_value()) {
    // This should never happen, further up-to-date checks are not possible if it does.
    LOG(ERROR) << "Could not get ART APEX info.";
    return PreconditionCheckResult::NoneOk(OdrMetrics::Trigger::kUnknown);
  }

  if (!art_apex_info->getIsFactory()) {
    LOG(INFO) << "Updated ART APEX mounted";
    return PreconditionCheckResult::NoneOk(OdrMetrics::Trigger::kApexVersionMismatch);
  }

  if (std::any_of(apex_info_list.begin(),
                  apex_info_list.end(),
                  [](const apex::ApexInfo& apex_info) { return !apex_info.getIsFactory(); })) {
    LOG(INFO) << "Updated APEXes mounted";
    return PreconditionCheckResult::BootImageMainlineExtensionNotOk(
        OdrMetrics::Trigger::kApexVersionMismatch);
  }

  return PreconditionCheckResult::AllOk();
}

WARN_UNUSED static bool CheckModuleInfo(const art_apex::ModuleInfo& cached_info,
                                        const apex::ApexInfo& current_info) {
  if (cached_info.getVersionCode() != current_info.getVersionCode()) {
    LOG(INFO) << ART_FORMAT("APEX ({}) version code mismatch (before: {}, now: {})",
                            current_info.getModuleName(),
                            cached_info.getVersionCode(),
                            current_info.getVersionCode());
    return false;
  }

  if (cached_info.getVersionName() != current_info.getVersionName()) {
    LOG(INFO) << ART_FORMAT("APEX ({}) version name mismatch (before: {}, now: {})",
                            current_info.getModuleName(),
                            cached_info.getVersionName(),
                            current_info.getVersionName());
    return false;
  }

  // Check lastUpdateMillis for samegrade installs. If `cached_info` is missing the lastUpdateMillis
  // field then it is not current with the schema used by this binary so treat it as a samegrade
  // update. Otherwise check whether the lastUpdateMillis changed.
  const int64_t cached_last_update_millis =
      cached_info.hasLastUpdateMillis() ? cached_info.getLastUpdateMillis() : -1;
  if (cached_last_update_millis != current_info.getLastUpdateMillis()) {
    LOG(INFO) << ART_FORMAT("APEX ({}) last update time mismatch (before: {}, now: {})",
                            current_info.getModuleName(),
                            cached_info.getLastUpdateMillis(),
                            current_info.getLastUpdateMillis());
    return false;
  }

  return true;
}

WARN_UNUSED PreconditionCheckResult OnDeviceRefresh::CheckPreconditionForData(
    const std::vector<com::android::apex::ApexInfo>& apex_info_list) const {
  Result<art_apex::CacheInfo> cache_info = ReadCacheInfo();
  if (!cache_info.ok()) {
    if (cache_info.error().code() == ENOENT) {
      // If the cache info file does not exist, it usually means it's the first boot, or the
      // dalvik-cache directory is cleared by odsign due to corrupted files. Set the trigger to be
      // `kApexVersionMismatch` to force generate the cache info file and compile if necessary.
      LOG(INFO) << "No prior cache-info file: " << QuotePath(cache_info_filename_);
    } else {
      // This should not happen unless odrefresh is updated to a new version that is not compatible
      // with an old cache-info file. Further up-to-date checks are not possible if it does.
      LOG(ERROR) << cache_info.error().message();
    }
    return PreconditionCheckResult::NoneOk(OdrMetrics::Trigger::kApexVersionMismatch);
  }

  if (!CheckSystemPropertiesHaveNotChanged(cache_info.value())) {
    // We don't have a trigger kind for system property changes. For now, we reuse
    // `kApexVersionMismatch` as it implies the expected behavior: re-compile regardless of the last
    // compilation attempt.
    return PreconditionCheckResult::NoneOk(OdrMetrics::Trigger::kApexVersionMismatch);
  }

  // Check whether the current cache ART module info differs from the current ART module info.
  const art_apex::ModuleInfo* cached_art_info = cache_info->getFirstArtModuleInfo();
  if (cached_art_info == nullptr) {
    LOG(ERROR) << "Missing ART APEX info from cache-info.";
    return PreconditionCheckResult::NoneOk(OdrMetrics::Trigger::kApexVersionMismatch);
  }

  std::optional<apex::ApexInfo> current_art_info = GetArtApexInfo(apex_info_list);
  if (!current_art_info.has_value()) {
    // This should never happen, further up-to-date checks are not possible if it does.
    LOG(ERROR) << "Could not get ART APEX info.";
    return PreconditionCheckResult::NoneOk(OdrMetrics::Trigger::kUnknown);
  }

  if (!CheckModuleInfo(*cached_art_info, *current_art_info)) {
    return PreconditionCheckResult::NoneOk(OdrMetrics::Trigger::kApexVersionMismatch);
  }

  // Check boot class components.
  //
  // This checks the size and checksums of odrefresh compilable files on the DEX2OATBOOTCLASSPATH
  // (the Odrefresh constructor determines which files are compilable). If the number of files
  // there changes, or their size or checksums change then compilation will be triggered.
  //
  // The boot class components may change unexpectedly, for example an OTA could update
  // framework.jar.
  const std::vector<art_apex::Component> current_dex2oat_bcp_components =
      GenerateDex2oatBootClasspathComponents();

  const art_apex::Classpath* cached_dex2oat_bcp_components =
      cache_info->getFirstDex2oatBootClasspath();
  if (cached_dex2oat_bcp_components == nullptr) {
    LOG(INFO) << "Missing Dex2oatBootClasspath components.";
    return PreconditionCheckResult::NoneOk(OdrMetrics::Trigger::kApexVersionMismatch);
  }

  Result<void> result = CheckComponents(current_dex2oat_bcp_components,
                                        cached_dex2oat_bcp_components->getComponent());
  if (!result.ok()) {
    LOG(INFO) << "Dex2OatClasspath components mismatch: " << result.error();
    return PreconditionCheckResult::NoneOk(OdrMetrics::Trigger::kDexFilesChanged);
  }

  // Check whether the current cached module info differs from the current module info.
  const art_apex::ModuleInfoList* cached_module_info_list = cache_info->getFirstModuleInfoList();
  if (cached_module_info_list == nullptr) {
    LOG(ERROR) << "Missing APEX info list from cache-info.";
    return PreconditionCheckResult::BootImageMainlineExtensionNotOk(
        OdrMetrics::Trigger::kApexVersionMismatch);
  }

  std::unordered_map<std::string, const art_apex::ModuleInfo*> cached_module_info_map;
  for (const art_apex::ModuleInfo& module_info : cached_module_info_list->getModuleInfo()) {
    cached_module_info_map[module_info.getName()] = &module_info;
  }

  // Note that apex_info_list may omit APEXes that are included in cached_module_info - e.g. if an
  // apex used to be compilable, but now isn't. That won't be detected by this loop, but will be
  // detected below in CheckComponents.
  for (const apex::ApexInfo& current_apex_info : apex_info_list) {
    auto& apex_name = current_apex_info.getModuleName();

    auto it = cached_module_info_map.find(apex_name);
    if (it == cached_module_info_map.end()) {
      LOG(INFO) << "Missing APEX info from cache-info (" << apex_name << ").";
      return PreconditionCheckResult::BootImageMainlineExtensionNotOk(
          OdrMetrics::Trigger::kApexVersionMismatch);
    }

    const art_apex::ModuleInfo* cached_module_info = it->second;
    if (!CheckModuleInfo(*cached_module_info, current_apex_info)) {
      return PreconditionCheckResult::BootImageMainlineExtensionNotOk(
          OdrMetrics::Trigger::kApexVersionMismatch);
    }
  }

  const std::vector<art_apex::Component> current_bcp_components = GenerateBootClasspathComponents();

  const art_apex::Classpath* cached_bcp_components = cache_info->getFirstBootClasspath();
  if (cached_bcp_components == nullptr) {
    LOG(INFO) << "Missing BootClasspath components.";
    return PreconditionCheckResult::BootImageMainlineExtensionNotOk(
        OdrMetrics::Trigger::kApexVersionMismatch);
  }

  result = CheckComponents(current_bcp_components, cached_bcp_components->getComponent());
  if (!result.ok()) {
    LOG(INFO) << "BootClasspath components mismatch: " << result.error();
    // Boot classpath components can be dependencies of system_server components, so system_server
    // components need to be recompiled if boot classpath components are changed.
    return PreconditionCheckResult::BootImageMainlineExtensionNotOk(
        OdrMetrics::Trigger::kDexFilesChanged);
  }

  // Check system server components.
  //
  // This checks the size and checksums of odrefresh compilable files on the
  // SYSTEMSERVERCLASSPATH (the Odrefresh constructor determines which files are compilable). If
  // the number of files there changes, or their size or checksums change then compilation will be
  // triggered.
  //
  // The system_server components may change unexpectedly, for example an OTA could update
  // services.jar.
  const std::vector<art_apex::SystemServerComponent> current_system_server_components =
      GenerateSystemServerComponents();

  const art_apex::SystemServerComponents* cached_system_server_components =
      cache_info->getFirstSystemServerComponents();
  if (cached_system_server_components == nullptr) {
    LOG(INFO) << "Missing SystemServerComponents.";
    return PreconditionCheckResult::SystemServerNotOk(OdrMetrics::Trigger::kApexVersionMismatch);
  }

  result = CheckSystemServerComponents(current_system_server_components,
                                       cached_system_server_components->getComponent());
  if (!result.ok()) {
    LOG(INFO) << "SystemServerComponents mismatch: " << result.error();
    return PreconditionCheckResult::SystemServerNotOk(OdrMetrics::Trigger::kDexFilesChanged);
  }

  return PreconditionCheckResult::AllOk();
}

WARN_UNUSED BootImages OnDeviceRefresh::CheckBootClasspathArtifactsAreUpToDate(
    OdrMetrics& metrics,
    InstructionSet isa,
    const PreconditionCheckResult& system_result,
    const PreconditionCheckResult& data_result,
    /*out*/ std::vector<std::string>* checked_artifacts) const {
  const char* isa_str = GetInstructionSetString(isa);

  BootImages boot_images_on_system{.primary_boot_image = false,
                                   .boot_image_mainline_extension = false};
  if (system_result.IsPrimaryBootImageOk()) {
    // We can use the artifacts on /system. Check if they exist.
    std::string error_msg;
    if (PrimaryBootImageExist(/*on_system=*/true, /*minimal=*/false, isa, &error_msg)) {
      boot_images_on_system.primary_boot_image = true;
    } else {
      LOG(INFO) << "Incomplete primary boot image or framework extension on /system: " << error_msg;
    }
  }

  if (boot_images_on_system.primary_boot_image && system_result.IsBootImageMainlineExtensionOk()) {
    std::string error_msg;
    if (BootImageMainlineExtensionExist(/*on_system=*/true, isa, &error_msg)) {
      boot_images_on_system.boot_image_mainline_extension = true;
    } else {
      LOG(INFO) << "Incomplete boot image mainline extension on /system: " << error_msg;
    }
  }

  if (boot_images_on_system.Count() == BootImages::kMaxCount) {
    LOG(INFO) << ART_FORMAT("Boot images on /system OK ({})", isa_str);
    // Nothing to compile.
    return BootImages{.primary_boot_image = false, .boot_image_mainline_extension = false};
  }

  LOG(INFO) << ART_FORMAT("Checking boot images /data ({})", isa_str);
  BootImages boot_images_on_data{.primary_boot_image = false,
                                 .boot_image_mainline_extension = false};

  if (data_result.IsPrimaryBootImageOk()) {
    std::string error_msg;
    if (PrimaryBootImageExist(
            /*on_system=*/false, /*minimal=*/false, isa, &error_msg, checked_artifacts)) {
      boot_images_on_data.primary_boot_image = true;
    } else {
      LOG(INFO) << "Incomplete primary boot image on /data: " << error_msg;
      metrics.SetTrigger(OdrMetrics::Trigger::kMissingArtifacts);
      // Add the minimal boot image to `checked_artifacts` if exists. This is to prevent the minimal
      // boot image from being deleted. It does not affect the return value because we should still
      // attempt to generate a full boot image even if the minimal one exists.
      if (PrimaryBootImageExist(
              /*on_system=*/false, /*minimal=*/true, isa, &error_msg, checked_artifacts)) {
        LOG(INFO) << ART_FORMAT("Found minimal primary boot image ({})", isa_str);
      }
    }
  } else {
    metrics.SetTrigger(data_result.GetTrigger());
  }

  if (boot_images_on_system.primary_boot_image || boot_images_on_data.primary_boot_image) {
    if (data_result.IsBootImageMainlineExtensionOk()) {
      std::string error_msg;
      if (BootImageMainlineExtensionExist(
              /*on_system=*/false, isa, &error_msg, checked_artifacts)) {
        boot_images_on_data.boot_image_mainline_extension = true;
      } else {
        LOG(INFO) << "Incomplete boot image mainline extension on /data: " << error_msg;
        metrics.SetTrigger(OdrMetrics::Trigger::kMissingArtifacts);
      }
    } else {
      metrics.SetTrigger(data_result.GetTrigger());
    }
  }

  BootImages boot_images_to_generate{
      .primary_boot_image =
          !boot_images_on_system.primary_boot_image && !boot_images_on_data.primary_boot_image,
      .boot_image_mainline_extension = !boot_images_on_system.boot_image_mainline_extension &&
                                       !boot_images_on_data.boot_image_mainline_extension,
  };

  if (boot_images_to_generate.Count() == 0) {
    LOG(INFO) << ART_FORMAT("Boot images on /data OK ({})", isa_str);
  }

  return boot_images_to_generate;
}

std::set<std::string> OnDeviceRefresh::CheckSystemServerArtifactsAreUpToDate(
    OdrMetrics& metrics,
    const PreconditionCheckResult& system_result,
    const PreconditionCheckResult& data_result,
    /*out*/ std::vector<std::string>* checked_artifacts) const {
  std::set<std::string> jars_to_compile;
  std::set<std::string> jars_missing_artifacts_on_system;
  if (system_result.IsSystemServerOk()) {
    // We can use the artifacts on /system. Check if they exist.
    std::string error_msg;
    if (SystemServerArtifactsExist(
            /*on_system=*/true, &error_msg, &jars_missing_artifacts_on_system)) {
      LOG(INFO) << "system_server artifacts on /system OK";
      return {};
    }

    LOG(INFO) << "Incomplete system server artifacts on /system: " << error_msg;
    LOG(INFO) << "Checking system server artifacts /data";
  } else {
    jars_missing_artifacts_on_system = AllSystemServerJars();
  }

  std::set<std::string> jars_missing_artifacts_on_data;
  std::string error_msg;
  if (data_result.IsSystemServerOk()) {
    SystemServerArtifactsExist(
        /*on_system=*/false, &error_msg, &jars_missing_artifacts_on_data, checked_artifacts);
  } else {
    jars_missing_artifacts_on_data = AllSystemServerJars();
  }

  std::set_intersection(jars_missing_artifacts_on_system.begin(),
                        jars_missing_artifacts_on_system.end(),
                        jars_missing_artifacts_on_data.begin(),
                        jars_missing_artifacts_on_data.end(),
                        std::inserter(jars_to_compile, jars_to_compile.end()));
  if (!jars_to_compile.empty()) {
    if (data_result.IsSystemServerOk()) {
      LOG(INFO) << "Incomplete system_server artifacts on /data: " << error_msg;
      metrics.SetTrigger(OdrMetrics::Trigger::kMissingArtifacts);
    } else {
      metrics.SetTrigger(data_result.GetTrigger());
    }
    return jars_to_compile;
  }

  LOG(INFO) << "system_server artifacts on /data OK";
  return {};
}

Result<void> OnDeviceRefresh::CleanupArtifactDirectory(
    OdrMetrics& metrics, const std::vector<std::string>& artifacts_to_keep) const {
  const std::string& artifact_dir = config_.GetArtifactDirectory();
  std::unordered_set<std::string> artifact_set{artifacts_to_keep.begin(), artifacts_to_keep.end()};

  // When anything unexpected happens, remove all artifacts.
  auto remove_artifact_dir = android::base::make_scope_guard([&]() {
    if (!RemoveDirectory(artifact_dir)) {
      LOG(ERROR) << "Failed to remove the artifact directory";
    }
  });

  std::vector<std::filesystem::directory_entry> entries;
  std::error_code ec;
  for (const auto& entry : std::filesystem::recursive_directory_iterator(artifact_dir, ec)) {
    // Save the entries and use them later because modifications during the iteration will result in
    // undefined behavior;
    entries.push_back(entry);
  }
  if (ec && ec.value() != ENOENT) {
    metrics.SetStatus(ec.value() == EPERM ? OdrMetrics::Status::kDalvikCachePermissionDenied :
                                            OdrMetrics::Status::kIoError);
    return Errorf("Failed to iterate over entries in the artifact directory: {}", ec.message());
  }

  for (const std::filesystem::directory_entry& entry : entries) {
    std::string path = entry.path().string();
    if (entry.is_regular_file()) {
      if (!ContainsElement(artifact_set, path)) {
        LOG(INFO) << "Removing " << path;
        if (unlink(path.c_str()) != 0) {
          metrics.SetStatus(OdrMetrics::Status::kIoError);
          return ErrnoErrorf("Failed to remove file {}", QuotePath(path));
        }
      }
    } else if (!entry.is_directory()) {
      // Neither a regular file nor a directory. Unexpected file type.
      LOG(INFO) << "Removing " << path;
      if (unlink(path.c_str()) != 0) {
        metrics.SetStatus(OdrMetrics::Status::kIoError);
        return ErrnoErrorf("Failed to remove file {}", QuotePath(path));
      }
    }
  }

  remove_artifact_dir.Disable();
  return {};
}

Result<void> OnDeviceRefresh::RefreshExistingArtifacts() const {
  const std::string& artifact_dir = config_.GetArtifactDirectory();
  if (!OS::DirectoryExists(artifact_dir.c_str())) {
    return {};
  }

  std::vector<std::filesystem::directory_entry> entries;
  std::error_code ec;
  for (const auto& entry : std::filesystem::recursive_directory_iterator(artifact_dir, ec)) {
    // Save the entries and use them later because modifications during the iteration will result in
    // undefined behavior;
    entries.push_back(entry);
  }
  if (ec) {
    return Errorf("Failed to iterate over entries in the artifact directory: {}", ec.message());
  }

  for (const std::filesystem::directory_entry& entry : entries) {
    std::string path = entry.path().string();
    if (entry.is_regular_file()) {
      // Unexpected files are already removed by `CleanupArtifactDirectory`. We can safely assume
      // that all the remaining files are good.
      LOG(INFO) << "Refreshing " << path;
      std::string content;
      if (!android::base::ReadFileToString(path, &content)) {
        return Errorf("Failed to read file {}", QuotePath(path));
      }
      if (unlink(path.c_str()) != 0) {
        return ErrnoErrorf("Failed to remove file {}", QuotePath(path));
      }
      if (!android::base::WriteStringToFile(content, path)) {
        return Errorf("Failed to write file {}", QuotePath(path));
      }
      if (chmod(path.c_str(), kFileMode) != 0) {
        return ErrnoErrorf("Failed to chmod file {}", QuotePath(path));
      }
    }
  }

  return {};
}

WARN_UNUSED ExitCode
OnDeviceRefresh::CheckArtifactsAreUpToDate(OdrMetrics& metrics,
                                           /*out*/ CompilationOptions* compilation_options) const {
  metrics.SetStage(OdrMetrics::Stage::kCheck);

  // Clean-up helper used to simplify clean-ups and handling failures there.
  auto cleanup_and_compile_all = [&, this]() {
    *compilation_options = CompilationOptions::CompileAll(*this);
    if (!RemoveArtifactsDirectory()) {
      metrics.SetStatus(OdrMetrics::Status::kIoError);
      return ExitCode::kCleanupFailed;
    }
    return ExitCode::kCompilationRequired;
  };

  std::optional<std::vector<apex::ApexInfo>> apex_info_list = GetApexInfoList();
  if (!apex_info_list.has_value()) {
    // This should never happen, further up-to-date checks are not possible if it does.
    LOG(ERROR) << "Could not get APEX info.";
    metrics.SetTrigger(OdrMetrics::Trigger::kUnknown);
    return cleanup_and_compile_all();
  }

  std::optional<apex::ApexInfo> art_apex_info = GetArtApexInfo(apex_info_list.value());
  if (!art_apex_info.has_value()) {
    // This should never happen, further up-to-date checks are not possible if it does.
    LOG(ERROR) << "Could not get ART APEX info.";
    metrics.SetTrigger(OdrMetrics::Trigger::kUnknown);
    return cleanup_and_compile_all();
  }

  // Record ART APEX version for metrics reporting.
  metrics.SetArtApexVersion(art_apex_info->getVersionCode());

  // Log the version so there's a starting point for any issues reported (b/197489543).
  LOG(INFO) << "ART APEX version " << art_apex_info->getVersionCode();

  // Record ART APEX last update milliseconds (used in compilation log).
  metrics.SetArtApexLastUpdateMillis(art_apex_info->getLastUpdateMillis());

  InstructionSet system_server_isa = config_.GetSystemServerIsa();
  std::vector<std::string> checked_artifacts;

  PreconditionCheckResult system_result = CheckPreconditionForSystem(apex_info_list.value());
  PreconditionCheckResult data_result = CheckPreconditionForData(apex_info_list.value());

  for (InstructionSet isa : config_.GetBootClasspathIsas()) {
    BootImages boot_images_to_generate = CheckBootClasspathArtifactsAreUpToDate(
        metrics, isa, system_result, data_result, &checked_artifacts);
    if (boot_images_to_generate.Count() > 0) {
      compilation_options->boot_images_to_generate_for_isas.emplace_back(isa,
                                                                         boot_images_to_generate);
      // system_server artifacts are invalid without valid boot classpath artifacts.
      if (isa == system_server_isa) {
        compilation_options->system_server_jars_to_compile = AllSystemServerJars();
      }
    }
  }

  if (compilation_options->system_server_jars_to_compile.empty()) {
    compilation_options->system_server_jars_to_compile = CheckSystemServerArtifactsAreUpToDate(
        metrics, system_result, data_result, &checked_artifacts);
  }

  bool compilation_required = compilation_options->CompilationUnitCount() > 0;

  if (!compilation_required && !data_result.IsAllOk()) {
    // Return kCompilationRequired to generate the cache info even if there's nothing to compile.
    compilation_required = true;
    metrics.SetTrigger(data_result.GetTrigger());
  }

  // Always keep the cache info.
  checked_artifacts.push_back(cache_info_filename_);

  Result<void> result = CleanupArtifactDirectory(metrics, checked_artifacts);
  if (!result.ok()) {
    LOG(ERROR) << result.error();
    return ExitCode::kCleanupFailed;
  }

  return compilation_required ? ExitCode::kCompilationRequired : ExitCode::kOkay;
}

WARN_UNUSED CompilationResult OnDeviceRefresh::RunDex2oat(
    const std::string& staging_dir,
    const std::string& debug_message,
    InstructionSet isa,
    const std::vector<std::string>& dex_files,
    const std::vector<std::string>& boot_classpath,
    const std::vector<std::string>& input_boot_images,
    const OdrArtifacts& artifacts,
    CmdlineBuilder&& extra_args,
    /*inout*/ std::vector<std::unique_ptr<File>>& readonly_files_raii) const {
  CmdlineBuilder args;
  args.Add(config_.GetDex2Oat());

  AddDex2OatCommonOptions(args);
  AddDex2OatDebugInfo(args);
  AddDex2OatInstructionSet(args, isa, config_.GetSystemProperties());
  Result<void> result = AddDex2OatConcurrencyArguments(
      args, config_.GetCompilationOsMode(), config_.GetSystemProperties());
  if (!result.ok()) {
    return CompilationResult::Error(OdrMetrics::Status::kUnknown, result.error().message());
  }

  // dex2oat reads some system properties from cache-info.xml generated by odrefresh.
  result = AddCacheInfoFd(args, readonly_files_raii, cache_info_filename_);
  if (!result.ok()) {
    return CompilationResult::Error(OdrMetrics::Status::kUnknown, result.error().message());
  }

  for (const std::string& dex_file : dex_files) {
    std::string actual_path = RewriteParentDirectoryIfNeeded(dex_file);
    args.Add("--dex-file=%s", dex_file);
    std::unique_ptr<File> file(OS::OpenFileForReading(actual_path.c_str()));
    if (file == nullptr) {
      return CompilationResult::Error(
          OdrMetrics::Status::kIoError,
          ART_FORMAT("Failed to open dex file '{}': {}", actual_path, strerror(errno)));
    }
    args.Add("--dex-fd=%d", file->Fd());
    readonly_files_raii.push_back(std::move(file));
  }

  args.AddRuntime("-Xbootclasspath:%s", Join(boot_classpath, ":"));
  result = AddBootClasspathFds(args, readonly_files_raii, boot_classpath);
  if (!result.ok()) {
    return CompilationResult::Error(OdrMetrics::Status::kIoError, result.error().message());
  }

  if (!input_boot_images.empty()) {
    args.Add("--boot-image=%s", Join(input_boot_images, ':'));
    result = AddCompiledBootClasspathFdsIfAny(
        args, readonly_files_raii, boot_classpath, isa, input_boot_images);
    if (!result.ok()) {
      return CompilationResult::Error(OdrMetrics::Status::kIoError, result.error().message());
    }
  }

  args.Add("--oat-location=%s", artifacts.OatPath());
  std::pair<std::string, const char*> location_kind_pairs[] = {
      std::make_pair(artifacts.ImagePath(), artifacts.ImageKind()),
      std::make_pair(artifacts.OatPath(), "oat"),
      std::make_pair(artifacts.VdexPath(), "output-vdex")};

  std::string install_location = Dirname(artifacts.OatPath());
  if (!EnsureDirectoryExists(install_location)) {
    return CompilationResult::Error(
        OdrMetrics::Status::kIoError,
        ART_FORMAT("Error encountered when preparing directory '{}'", install_location));
  }

  std::vector<std::unique_ptr<File>> output_files;
  for (const auto& [location, kind] : location_kind_pairs) {
    std::string output_location =
        staging_dir.empty() ? location : GetStagingLocation(staging_dir, location);
    std::unique_ptr<File> output_file(OS::CreateEmptyFile(output_location.c_str()));
    if (output_file == nullptr) {
      return CompilationResult::Error(
          OdrMetrics::Status::kIoError,
          ART_FORMAT("Failed to create {} file '{}': {}", kind, output_location, strerror(errno)));
    }
    args.Add(StringPrintf("--%s-fd=%d", kind, output_file->Fd()));
    output_files.emplace_back(std::move(output_file));
  }

  // We don't care about file state on failure.
  auto cleanup = ScopeGuard([&] {
    for (const std::unique_ptr<File>& file : output_files) {
      file->MarkUnchecked();
    }
  });

  args.Concat(std::move(extra_args));

  Timer timer;
  time_t timeout = GetSubprocessTimeout();
  std::string cmd_line = Join(args.Get(), ' ');
  LOG(INFO) << ART_FORMAT("{}: {} [timeout {}s]", debug_message, cmd_line, timeout);
  if (config_.GetDryRun()) {
    LOG(INFO) << "Compilation skipped (dry-run).";
    return CompilationResult::Ok();
  }

  std::string error_msg;
  ExecResult dex2oat_result = exec_utils_->ExecAndReturnResult(args.Get(), timeout, &error_msg);

  if (dex2oat_result.exit_code != 0) {
    return CompilationResult::Dex2oatError(
        dex2oat_result.exit_code < 0 ?
            error_msg :
            ART_FORMAT("dex2oat returned an unexpected code: {}", dex2oat_result.exit_code),
        timer.duration().count(),
        dex2oat_result);
  }

  if (staging_dir.empty()) {
    for (const std::unique_ptr<File>& file : output_files) {
      if (file->FlushCloseOrErase() != 0) {
        return CompilationResult::Error(
            OdrMetrics::Status::kIoError,
            ART_FORMAT("Failed to flush close file '{}'", file->GetPath()));
      }
    }
  } else {
    for (const std::unique_ptr<File>& file : output_files) {
      if (file->Flush() != 0) {
        return CompilationResult::Error(OdrMetrics::Status::kIoError,
                                        ART_FORMAT("Failed to flush file '{}'", file->GetPath()));
      }
    }
    if (!MoveOrEraseFiles(output_files, install_location, restorecon_)) {
      return CompilationResult::Error(
          OdrMetrics::Status::kIoError,
          ART_FORMAT("Failed to commit artifacts to '{}'", install_location));
    }
  }

  cleanup.Disable();
  return CompilationResult::Dex2oatOk(timer.duration().count(), dex2oat_result);
}

WARN_UNUSED CompilationResult
OnDeviceRefresh::RunDex2oatForBootClasspath(const std::string& staging_dir,
                                            const std::string& debug_name,
                                            InstructionSet isa,
                                            const std::vector<std::string>& dex_files,
                                            const std::vector<std::string>& boot_classpath,
                                            const std::vector<std::string>& input_boot_images,
                                            const std::string& output_path) const {
  CmdlineBuilder args;
  std::vector<std::unique_ptr<File>> readonly_files_raii;

  // Compile as a single image for fewer files and slightly less memory overhead.
  args.Add("--single-image");

  if (input_boot_images.empty()) {
    // Primary boot image.
    std::string art_boot_profile_file = GetArtRoot() + "/etc/boot-image.prof";
    std::string framework_boot_profile_file = GetAndroidRoot() + "/etc/boot-image.prof";
    Result<bool> has_any_profile = AddDex2OatProfile(
        args, readonly_files_raii, {art_boot_profile_file, framework_boot_profile_file});
    if (!has_any_profile.ok()) {
      return CompilationResult::Error(OdrMetrics::Status::kIoError,
                                      has_any_profile.error().message());
    }
    if (!*has_any_profile) {
      return CompilationResult::Error(OdrMetrics::Status::kIoError, "Missing boot image profile");
    }
    const std::string& compiler_filter = config_.GetBootImageCompilerFilter();
    if (!compiler_filter.empty()) {
      args.Add("--compiler-filter=%s", compiler_filter);
    } else {
      args.Add("--compiler-filter=%s", kPrimaryCompilerFilter);
    }

    args.Add(StringPrintf("--base=0x%08x", ART_BASE_ADDRESS));

    for (const std::string& prefix : {GetAndroidRoot(), GetArtRoot()}) {
      std::string dirty_image_objects_file = prefix + "/etc/dirty-image-objects";
      std::unique_ptr<File> file(OS::OpenFileForReading(dirty_image_objects_file.c_str()));
      if (file != nullptr) {
        args.Add("--dirty-image-objects-fd=%d", file->Fd());
        readonly_files_raii.push_back(std::move(file));
      } else if (errno == ENOENT) {
        LOG(WARNING) << ART_FORMAT("Missing dirty objects file '{}'", dirty_image_objects_file);
      } else {
        return CompilationResult::Error(OdrMetrics::Status::kIoError,
                                        ART_FORMAT("Failed to open dirty objects file '{}': {}",
                                                   dirty_image_objects_file,
                                                   strerror(errno)));
      }
    }

    std::string preloaded_classes_file(GetAndroidRoot() + "/etc/preloaded-classes");
    std::unique_ptr<File> file(OS::OpenFileForReading(preloaded_classes_file.c_str()));
    if (file != nullptr) {
      args.Add("--preloaded-classes-fds=%d", file->Fd());
      readonly_files_raii.push_back(std::move(file));
    } else if (errno == ENOENT) {
      LOG(WARNING) << ART_FORMAT("Missing preloaded classes file '{}'", preloaded_classes_file);
    } else {
      return CompilationResult::Error(OdrMetrics::Status::kIoError,
                                      ART_FORMAT("Failed to open preloaded classes file '{}': {}",
                                                 preloaded_classes_file,
                                                 strerror(errno)));
    }
  } else {
    // Mainline extension.
    args.Add("--compiler-filter=%s", kMainlineCompilerFilter);
  }

  const OdrSystemProperties& system_properties = config_.GetSystemProperties();
  args.AddRuntimeIfNonEmpty("-Xms%s", system_properties.GetOrEmpty("dalvik.vm.image-dex2oat-Xms"))
      .AddRuntimeIfNonEmpty("-Xmx%s", system_properties.GetOrEmpty("dalvik.vm.image-dex2oat-Xmx"));

  return RunDex2oat(
      staging_dir,
      ART_FORMAT("Compiling boot classpath ({}, {})", GetInstructionSetString(isa), debug_name),
      isa,
      dex_files,
      boot_classpath,
      input_boot_images,
      OdrArtifacts::ForBootImage(output_path),
      std::move(args),
      readonly_files_raii);
}

WARN_UNUSED CompilationResult
OnDeviceRefresh::CompileBootClasspath(const std::string& staging_dir,
                                      InstructionSet isa,
                                      BootImages boot_images,
                                      const std::function<void()>& on_dex2oat_success) const {
  DCHECK_GT(boot_images.Count(), 0);
  DCHECK_IMPLIES(boot_images.primary_boot_image, boot_images.boot_image_mainline_extension);

  CompilationResult result = CompilationResult::Ok();

  if (config_.GetMinimal()) {
    result.Merge(
        CompilationResult::Error(OdrMetrics::Status::kUnknown, "Minimal boot image requested"));
  }

  if (!check_compilation_space_()) {
    result.Merge(CompilationResult::Error(OdrMetrics::Status::kNoSpace, "Insufficient space"));
  }

  if (result.IsOk() && boot_images.primary_boot_image) {
    CompilationResult primary_result = RunDex2oatForBootClasspath(
        staging_dir,
        "primary",
        isa,
        dex2oat_boot_classpath_jars_,
        dex2oat_boot_classpath_jars_,
        /*input_boot_images=*/{},
        GetPrimaryBootImagePath(/*on_system=*/false, /*minimal=*/false, isa));
    result.Merge(primary_result);

    if (primary_result.IsOk()) {
      on_dex2oat_success();

      // Remove the minimal boot image only if the full boot image is successfully generated.
      std::string path = GetPrimaryBootImagePath(/*on_system=*/false, /*minimal=*/true, isa);
      OdrArtifacts artifacts = OdrArtifacts::ForBootImage(path);
      unlink(artifacts.ImagePath().c_str());
      unlink(artifacts.OatPath().c_str());
      unlink(artifacts.VdexPath().c_str());
    }
  }

  if (!result.IsOk() && boot_images.primary_boot_image) {
    LOG(ERROR) << "Compilation of primary BCP failed: " << result.error_msg;

    // Fall back to generating a minimal boot image.
    // The compilation of the full boot image will be retried on later reboots with a backoff
    // time, and the minimal boot image will be removed once the compilation of the full boot
    // image succeeds.
    std::string ignored_error_msg;
    if (PrimaryBootImageExist(
            /*on_system=*/false, /*minimal=*/true, isa, &ignored_error_msg)) {
      LOG(INFO) << "Minimal boot image already up-to-date";
      return result;
    }
    std::vector<std::string> art_bcp_jars = GetArtBcpJars();
    CompilationResult minimal_result = RunDex2oatForBootClasspath(
        staging_dir,
        "minimal",
        isa,
        art_bcp_jars,
        art_bcp_jars,
        /*input_boot_images=*/{},
        GetPrimaryBootImagePath(/*on_system=*/false, /*minimal=*/true, isa));
    result.Merge(minimal_result);

    if (!minimal_result.IsOk()) {
      LOG(ERROR) << "Compilation of minimal BCP failed: " << result.error_msg;
    }

    return result;
  }

  if (result.IsOk() && boot_images.boot_image_mainline_extension) {
    CompilationResult mainline_result =
        RunDex2oatForBootClasspath(staging_dir,
                                   "mainline",
                                   isa,
                                   GetMainlineBcpJars(),
                                   boot_classpath_jars_,
                                   GetBestBootImages(isa, /*include_mainline_extension=*/false),
                                   GetBootImageMainlineExtensionPath(/*on_system=*/false, isa));
    result.Merge(mainline_result);

    if (mainline_result.IsOk()) {
      on_dex2oat_success();
    }
  }

  if (!result.IsOk() && boot_images.boot_image_mainline_extension) {
    LOG(ERROR) << "Compilation of mainline BCP failed: " << result.error_msg;
  }

  return result;
}

WARN_UNUSED CompilationResult OnDeviceRefresh::RunDex2oatForSystemServer(
    const std::string& staging_dir,
    const std::string& dex_file,
    const std::vector<std::string>& classloader_context) const {
  CmdlineBuilder args;
  std::vector<std::unique_ptr<File>> readonly_files_raii;
  InstructionSet isa = config_.GetSystemServerIsa();
  std::string output_path = GetSystemServerImagePath(/*on_system=*/false, dex_file);

  std::string actual_jar_path = RewriteParentDirectoryIfNeeded(dex_file);
  std::string profile = actual_jar_path + ".prof";
  const std::string& compiler_filter = config_.GetSystemServerCompilerFilter();
  bool maybe_add_profile = !compiler_filter.empty() || HasVettedDeviceSystemServerProfiles();
  bool has_added_profile = false;
  if (maybe_add_profile) {
    Result<bool> has_any_profile = AddDex2OatProfile(args, readonly_files_raii, {profile});
    if (!has_any_profile.ok()) {
      return CompilationResult::Error(OdrMetrics::Status::kIoError,
                                      has_any_profile.error().message());
    }
    has_added_profile = *has_any_profile;
  }
  if (!compiler_filter.empty()) {
    args.Add("--compiler-filter=%s", compiler_filter);
  } else if (has_added_profile) {
    args.Add("--compiler-filter=speed-profile");
  } else {
    args.Add("--compiler-filter=speed");
  }

  std::string context_path = Join(classloader_context, ':');
  if (art::ContainsElement(systemserver_classpath_jars_, dex_file)) {
    args.Add("--class-loader-context=PCL[%s]", context_path);
  } else {
    args.Add("--class-loader-context=PCL[];PCL[%s]", context_path);
  }
  if (!classloader_context.empty()) {
    std::vector<int> fds;
    for (const std::string& path : classloader_context) {
      std::string actual_path = RewriteParentDirectoryIfNeeded(path);
      std::unique_ptr<File> file(OS::OpenFileForReading(actual_path.c_str()));
      if (file == nullptr) {
        return CompilationResult::Error(
            OdrMetrics::Status::kIoError,
            ART_FORMAT(
                "Failed to open classloader context '{}': {}", actual_path, strerror(errno)));
      }
      fds.emplace_back(file->Fd());
      readonly_files_raii.emplace_back(std::move(file));
    }
    args.Add("--class-loader-context-fds=%s", Join(fds, ':'));
  }

  const OdrSystemProperties& system_properties = config_.GetSystemProperties();
  args.AddRuntimeIfNonEmpty("-Xms%s", system_properties.GetOrEmpty("dalvik.vm.dex2oat-Xms"))
      .AddRuntimeIfNonEmpty("-Xmx%s", system_properties.GetOrEmpty("dalvik.vm.dex2oat-Xmx"));

  return RunDex2oat(staging_dir,
                    ART_FORMAT("Compiling {}", Basename(dex_file)),
                    isa,
                    {dex_file},
                    boot_classpath_jars_,
                    GetBestBootImages(isa, /*include_mainline_extension=*/true),
                    OdrArtifacts::ForSystemServer(output_path),
                    std::move(args),
                    readonly_files_raii);
}

WARN_UNUSED CompilationResult
OnDeviceRefresh::CompileSystemServer(const std::string& staging_dir,
                                     const std::set<std::string>& system_server_jars_to_compile,
                                     const std::function<void()>& on_dex2oat_success) const {
  DCHECK(!system_server_jars_to_compile.empty());

  CompilationResult result = CompilationResult::Ok();
  std::vector<std::string> classloader_context;

  if (!check_compilation_space_()) {
    LOG(ERROR) << "Compilation of system_server failed: Insufficient space";
    return CompilationResult::Error(OdrMetrics::Status::kNoSpace, "Insufficient space");
  }

  for (const std::string& jar : all_systemserver_jars_) {
    if (ContainsElement(system_server_jars_to_compile, jar)) {
      CompilationResult current_result =
          RunDex2oatForSystemServer(staging_dir, jar, classloader_context);
      result.Merge(current_result);

      if (current_result.IsOk()) {
        on_dex2oat_success();
      } else {
        LOG(ERROR) << ART_FORMAT("Compilation of {} failed: {}", Basename(jar), result.error_msg);
      }
    }

    if (ContainsElement(systemserver_classpath_jars_, jar)) {
      classloader_context.emplace_back(jar);
    }
  }

  return result;
}

WARN_UNUSED ExitCode OnDeviceRefresh::Compile(OdrMetrics& metrics,
                                              CompilationOptions compilation_options) const {
  std::string staging_dir;
  metrics.SetStage(OdrMetrics::Stage::kPreparation);

  // If partial compilation is disabled, we should compile everything regardless of what's in
  // `compilation_options`.
  if (!config_.GetPartialCompilation()) {
    compilation_options = CompilationOptions::CompileAll(*this);
    if (!RemoveArtifactsDirectory()) {
      metrics.SetStatus(OdrMetrics::Status::kIoError);
      return ExitCode::kCleanupFailed;
    }
  }

  if (!EnsureDirectoryExists(config_.GetArtifactDirectory())) {
    LOG(ERROR) << "Failed to prepare artifact directory";
    metrics.SetStatus(errno == EPERM ? OdrMetrics::Status::kDalvikCachePermissionDenied :
                                       OdrMetrics::Status::kIoError);
    return ExitCode::kCleanupFailed;
  }

  if (config_.GetRefresh()) {
    Result<void> result = RefreshExistingArtifacts();
    if (!result.ok()) {
      LOG(ERROR) << "Failed to refresh existing artifacts: " << result.error();
      metrics.SetStatus(OdrMetrics::Status::kIoError);
      return ExitCode::kCleanupFailed;
    }
  }

  // Emit cache info before compiling. This can be used to throttle compilation attempts later.
  Result<void> result = WriteCacheInfo();
  if (!result.ok()) {
    LOG(ERROR) << result.error();
    metrics.SetStatus(OdrMetrics::Status::kIoError);
    return ExitCode::kCleanupFailed;
  }

  if (config_.GetCompilationOsMode()) {
    // We don't need to stage files in CompOS. If the compilation fails (partially or entirely),
    // CompOS will not sign any artifacts, and odsign will discard CompOS outputs entirely.
    staging_dir = "";
  } else {
    // Create staging area and assign label for generating compilation artifacts.
    Result<std::string> res = CreateStagingDirectory();
    if (!res.ok()) {
      LOG(ERROR) << res.error().message();
      metrics.SetStatus(OdrMetrics::Status::kStagingFailed);
      return ExitCode::kCleanupFailed;
    }
    staging_dir = res.value();
  }

  uint32_t dex2oat_invocation_count = 0;
  uint32_t total_dex2oat_invocation_count = compilation_options.CompilationUnitCount();
  ReportNextBootAnimationProgress(dex2oat_invocation_count, total_dex2oat_invocation_count);
  auto advance_animation_progress = [&]() {
    ReportNextBootAnimationProgress(++dex2oat_invocation_count, total_dex2oat_invocation_count);
  };

  const std::vector<InstructionSet>& bcp_instruction_sets = config_.GetBootClasspathIsas();
  DCHECK(!bcp_instruction_sets.empty() && bcp_instruction_sets.size() <= 2);
  InstructionSet system_server_isa = config_.GetSystemServerIsa();

  bool system_server_isa_failed = false;
  std::optional<std::pair<OdrMetrics::Stage, OdrMetrics::Status>> first_failure;

  for (const auto& [isa, boot_images_to_generate] :
       compilation_options.boot_images_to_generate_for_isas) {
    OdrMetrics::Stage stage = (isa == bcp_instruction_sets.front()) ?
                                  OdrMetrics::Stage::kPrimaryBootClasspath :
                                  OdrMetrics::Stage::kSecondaryBootClasspath;
    CompilationResult bcp_result =
        CompileBootClasspath(staging_dir, isa, boot_images_to_generate, advance_animation_progress);
    metrics.SetDex2OatResult(stage, bcp_result.elapsed_time_ms, bcp_result.dex2oat_result);
    metrics.SetBcpCompilationType(stage, boot_images_to_generate.GetTypeForMetrics());
    if (!bcp_result.IsOk()) {
      if (isa == system_server_isa) {
        system_server_isa_failed = true;
      }
      first_failure = first_failure.value_or(std::make_pair(stage, bcp_result.status));
    }
  }

  // Don't compile system server if the compilation of BCP failed.
  if (!system_server_isa_failed && !compilation_options.system_server_jars_to_compile.empty() &&
      !config_.GetOnlyBootImages()) {
    OdrMetrics::Stage stage = OdrMetrics::Stage::kSystemServerClasspath;
    CompilationResult ss_result = CompileSystemServer(
        staging_dir, compilation_options.system_server_jars_to_compile, advance_animation_progress);
    metrics.SetDex2OatResult(stage, ss_result.elapsed_time_ms, ss_result.dex2oat_result);
    if (!ss_result.IsOk()) {
      first_failure = first_failure.value_or(std::make_pair(stage, ss_result.status));
    }
  }

  if (first_failure.has_value()) {
    LOG(ERROR) << "Compilation failed, stage: " << first_failure->first
               << " status: " << first_failure->second;
    metrics.SetStage(first_failure->first);
    metrics.SetStatus(first_failure->second);

    if (!config_.GetDryRun() && !RemoveDirectory(staging_dir)) {
      return ExitCode::kCleanupFailed;
    }
    return ExitCode::kCompilationFailed;
  }

  metrics.SetStage(OdrMetrics::Stage::kComplete);
  metrics.SetStatus(OdrMetrics::Status::kOK);
  return ExitCode::kCompilationSuccess;
}

}  // namespace odrefresh
}  // namespace art
