/*
 * 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/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 "palette/palette.h"
#include "palette/palette_types.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::SetProperty;
using ::android::base::Split;
using ::android::base::StartsWith;
using ::android::base::StringPrintf;
using ::android::base::Timer;
using ::android::modules::sdklevel::IsAtLeastU;
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) {
  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();

    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 (StartsWith(path, "/system/")) {
    return GetAndroidRoot() + path.substr(7);
  } else if (StartsWith(path, "/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::vector<uint32_t> checksums;
    std::vector<std::string> dex_locations;
    std::string error_msg;
    if (!ArtDexFileLoader::GetMultiDexChecksums(
            actual_path.c_str(), &checksums, &dex_locations, &error_msg)) {
      LOG(ERROR) << "Failed to get multi-dex checksums: " << error_msg;
      return {};
    }

    std::ostringstream oss;
    for (size_t i = 0; i < checksums.size(); ++i) {
      if (i != 0) {
        oss << ';';
      }
      oss << StringPrintf("%08x", checksums[i]);
    }
    const std::string checksum = oss.str();

    Result<T> component = custom_generator(path, static_cast<uint64_t>(sb.st_size), checksum);
    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("--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 char* isa_str = GetInstructionSetString(isa);
  args.Add("--instruction-set=%s", isa_str);
}

// 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 (StartsWith(jar, "/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_file);
  }

  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, "art");
}

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 = 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, "oat");
    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, "vdex");
    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)
    : OnDeviceRefresh(config,
                      config.GetArtifactDirectory() + "/" + kCacheInfoFile,
                      std::make_unique<ExecUtils>()) {}

OnDeviceRefresh::OnDeviceRefresh(const OdrConfig& config,
                                 const std::string& cache_info_filename,
                                 std::unique_ptr<ExecUtils> exec_utils)
    : config_{config},
      cache_info_filename_{cache_info_filename},
      start_time_{time(nullptr)},
      exec_utils_{std::move(exec_utils)} {
  // 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);
}

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();
}

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()) {
    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 (StartsWith(jar, 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 (!StartsWith(jar, 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, "art");
    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),
                      [](const char* prefix) { return StartsWith(prefix, "persist."); }));

  const OdrSystemProperties& system_properties = config_.GetSystemProperties();

  for (const SystemPropertyConfig& system_property_config : *kSystemProperties.get()) {
    std::string property = system_properties.GetOrEmpty(system_property_config.name);
    DCHECK_NE(property, "");

    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) {
    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 kernel_supports_uffd = KernelSupportsUffd();
  if (!art::odrefresh::CheckBuildUserfaultFdGc(build_enable_uffd_gc, kernel_supports_uffd)) {
    // Assuming the system property reflects how the dexpreopted boot image was
    // compiled, and it doesn't agree with runtime support, we need to recompile
    // it. This happens if we're running on S, T or U, or if the system image
    // was built with a wrong PRODUCT_ENABLE_UFFD_GC flag.
    LOG(INFO) << ART_FORMAT(
        "Userfaultfd GC check failed (build_enable_uffd_gc: {}, kernel_supports_uffd: {}).",
        build_enable_uffd_gc,
        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());
  }

  // If partial compilation is disabled, we should compile everything regardless of what's in
  // `compilation_options`.
  if (compilation_required && !config_.GetPartialCompilation()) {
    return cleanup_and_compile_all();
  }

  // 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);
  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::vector<std::unique_ptr<File>> staging_files;
  for (const auto& [location, kind] : location_kind_pairs) {
    std::string staging_location = GetStagingLocation(staging_dir, location);
    std::unique_ptr<File> staging_file(OS::CreateEmptyFile(staging_location.c_str()));
    if (staging_file == nullptr) {
      return CompilationResult::Error(
          OdrMetrics::Status::kIoError,
          ART_FORMAT("Failed to create {} file '{}': {}", kind, staging_location, strerror(errno)));
    }
    // Don't check the state of the staging file. It doesn't need to be flushed because it's removed
    // after the compilation regardless of success or failure.
    staging_file->MarkUnchecked();
    args.Add(StringPrintf("--%s-fd=%d", kind, staging_file->Fd()));
    staging_files.emplace_back(std::move(staging_file));
  }

  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));
  }

  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 (!MoveOrEraseFiles(staging_files, install_location)) {
    return CompilationResult::Error(
        OdrMetrics::Status::kIoError,
        ART_FORMAT("Failed to commit artifacts to '{}'", install_location));
  }

  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));

    std::string dirty_image_objects_file(GetAndroidRoot() + "/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");
    file.reset(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);
  }

  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 (!CheckCompilationSpace()) {
    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, ':'));
  }

  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 (!CheckCompilationSpace()) {
    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,
                                              const CompilationOptions& compilation_options) const {
  const char* staging_dir = nullptr;
  metrics.SetStage(OdrMetrics::Stage::kPreparation);

  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_.GetStagingDir().empty()) {
    staging_dir = config_.GetStagingDir().c_str();
  } else {
    // Create staging area and assign label for generating compilation artifacts.
    if (PaletteCreateOdrefreshStagingDirectory(&staging_dir) != PALETTE_STATUS_OK) {
      metrics.SetStatus(OdrMetrics::Status::kStagingFailed);
      return ExitCode::kCleanupFailed;
    }
  }

  std::string error_msg;

  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()) {
    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()) {
    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
