/*
 * 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/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 <cstdarg>
#include <cstdint>
#include <cstdlib>
#include <fstream>
#include <initializer_list>
#include <iosfwd>
#include <iostream>
#include <memory>
#include <optional>
#include <ostream>
#include <regex>
#include <sstream>
#include <string>
#include <string_view>
#include <type_traits>
#include <utility>
#include <vector>

#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/stringprintf.h"
#include "android-base/strings.h"
#include "android/log.h"
#include "arch/instruction_set.h"
#include "base/file_utils.h"
#include "base/globals.h"
#include "base/macros.h"
#include "base/os.h"
#include "base/string_view_cpp20.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 "dexoptanalyzer.h"
#include "exec_utils.h"
#include "log/log.h"
#include "odr_artifacts.h"
#include "odr_compilation_log.h"
#include "odr_config.h"
#include "odr_fs_utils.h"
#include "odr_metrics.h"
#include "palette/palette.h"
#include "palette/palette_types.h"

namespace art {
namespace odrefresh {

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

namespace {

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

using ::android::base::Result;

static void UsageErrorV(const char* fmt, va_list ap) {
  std::string error;
  android::base::StringAppendV(&error, fmt, ap);
  if (isatty(fileno(stderr))) {
    std::cerr << error << std::endl;
  } else {
    LOG(ERROR) << error;
  }
}

static void UsageError(const char* fmt, ...) {
  va_list ap;
  va_start(ap, fmt);
  UsageErrorV(fmt, ap);
  va_end(ap);
}

NO_RETURN static void ArgumentError(const char* fmt, ...) {
  va_list ap;
  va_start(ap, fmt);
  UsageErrorV(fmt, ap);
  va_end(ap);
  UsageError("Try '--help' for more information.");
  exit(EX_USAGE);
}

NO_RETURN static void UsageHelp(const char* argv0) {
  std::string name(android::base::Basename(argv0));
  UsageError("Usage: %s ACTION", name.c_str());
  UsageError("On-device refresh tool for boot class path extensions and system server");
  UsageError("following an update of the ART APEX.");
  UsageError("");
  UsageError("Valid ACTION choices are:");
  UsageError("");
  UsageError(
      "--check          Check compilation artifacts are up-to-date based on metadata (fast).");
  UsageError("--compile        Compile boot class path extensions and system_server jars");
  UsageError("                 when necessary.");
  UsageError("--force-compile  Unconditionally compile the boot class path extensions and");
  UsageError("                 system_server jars.");
  UsageError("--verify         Verify artifacts are up-to-date with dexoptanalyzer (slow).");
  UsageError("--help           Display this help information.");
  exit(EX_USAGE);
}

static std::string Concatenate(std::initializer_list<std::string_view> args) {
  std::stringstream ss;
  for (auto arg : args) {
    ss << arg;
  }
  return ss.str();
}

static std::string GetEnvironmentVariableOrDie(const char* name) {
  const char* value = getenv(name);
  LOG_ALWAYS_FATAL_IF(value == nullptr, "%s is not defined.", name);
  return value;
}

static std::string QuotePath(std::string_view path) {
  return Concatenate({"'", path, "'"});
}

static 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.
static 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) {
    const std::string file_basename(android::base::Basename(file->GetPath()));
    const std::string output_file_path = Concatenate({output_directory_path, "/", file_basename});
    const 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;
    }

    static constexpr mode_t kFileMode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
    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;
    }

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

Result<int> ParseSecurityPatchStr(const std::string& security_patch_str) {
  std::regex security_patch_regex(R"re((\d{4})-(\d{2})-(\d{2}))re");
  std::smatch m;
  if (!std::regex_match(security_patch_str, m, security_patch_regex)) {
    return Errorf("Invalid security patch string \"{}\"", security_patch_str);
  }
  int year = 0, month = 0, day = 0;
  if (!android::base::ParseInt(m[1], &year) || !android::base::ParseInt(m[2], &month) ||
      !android::base::ParseInt(m[3], &day)) {
    // This should never happen because the string already matches the regex.
    return Errorf("Unknown error when parsing security patch string \"{}\"", security_patch_str);
  }
  return year * 10000 + month * 100 + day;
}

bool ShouldDisablePartialCompilation(const std::string& security_patch_str) {
  Result<int> security_patch_value = ParseSecurityPatchStr(security_patch_str);
  if (!security_patch_value.ok()) {
    LOG(ERROR) << security_patch_value.error();
    return false;
  }
  return security_patch_value.value() < ParseSecurityPatchStr("2022-03-05").value();
}

}  // namespace

bool ParseZygoteKind(const char* input, ZygoteKind* zygote_kind) {
  std::string_view z(input);
  if (z == "zygote32") {
    *zygote_kind = ZygoteKind::kZygote32;
    return true;
  } else if (z == "zygote32_64") {
    *zygote_kind = ZygoteKind::kZygote32_64;
    return true;
  } else if (z == "zygote64_32") {
    *zygote_kind = ZygoteKind::kZygote64_32;
    return true;
  } else if (z == "zygote64") {
    *zygote_kind = ZygoteKind::kZygote64;
    return true;
  }
  return false;
}

class OnDeviceRefresh final {
 private:
  // Maximum execution time for odrefresh from start to end.
  static constexpr time_t kMaximumExecutionSeconds = 300;

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

  // Configuration to use.
  const OdrConfig& config_;

  // Path to cache information file that is used to speed up artifact checking.
  const std::string cache_info_filename_;

  // List of boot extension components that should be compiled.
  std::vector<std::string> boot_extension_compilable_jars_;

  // List of system_server components that should be compiled.
  std::vector<std::string> systemserver_compilable_jars_;

  const time_t start_time_;

 public:
  explicit OnDeviceRefresh(const OdrConfig& config)
      : config_{config},
        cache_info_filename_{Concatenate({kOdrefreshArtifactDirectory, "/", kCacheInfoFile})},
        start_time_{time(nullptr)} {
    for (const std::string& jar : android::base::Split(config_.GetDex2oatBootClasspath(), ":")) {
      // Boot class path extensions are those not in the ART APEX. 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.
      if (!LocationIsOnArtModule(jar)) {
        boot_extension_compilable_jars_.emplace_back(jar);
      }
    }

    for (const std::string& jar : android::base::Split(config_.GetSystemServerClasspath(), ":")) {
      // Only consider DEX files on the SYSTEMSERVERCLASSPATH for compilation that do not reside
      // in APEX modules. Otherwise, we'll recompile on boot any time one of these APEXes updates.
      if (!LocationIsOnApex(jar)) {
        systemserver_compilable_jars_.emplace_back(jar);
      }
    }
  }

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

  time_t GetExecutionTimeRemaining() const {
    return kMaximumExecutionSeconds - GetExecutionTimeUsed();
  }

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

  // Gets the `ApexInfo` associated with the currently active ART APEX.
  std::optional<apex::ApexInfo> GetArtApexInfo() const {
    auto info_list = apex::readApexInfoList(config_.GetApexInfoListFile().c_str());
    if (!info_list.has_value()) {
      return {};
    }

    for (const apex::ApexInfo& info : info_list->getApexInfo()) {
      if (info.getIsActive() && info.getModuleName() == "com.android.art") {
        return info;
      }
    }
    return {};
  }

  // Reads the ART APEX cache information (if any) found in `kOdrefreshArtifactDirectory`.
  std::optional<art_apex::CacheInfo> ReadCacheInfo() {
    return art_apex::read(cache_info_filename_.c_str());
  }

  // Write ART APEX cache information to `kOdrefreshArtifactDirectory`.
  void WriteCacheInfo() const {
    if (OS::FileExists(cache_info_filename_.c_str())) {
      if (unlink(cache_info_filename_.c_str()) != 0) {
        PLOG(ERROR) << "Failed to unlink() file " << QuotePath(cache_info_filename_);
      }
    }

    const std::string dir_name = android::base::Dirname(cache_info_filename_);
    if (!EnsureDirectoryExists(dir_name)) {
      LOG(ERROR) << "Could not create directory: " << QuotePath(dir_name);
      return;
    }

    std::optional<art_apex::ArtModuleInfo> art_module_info = GenerateArtModuleInfo();
    if (!art_module_info.has_value()) {
      LOG(ERROR) << "Unable to generate cache provenance";
      return;
    }

    // There can be only one CacheProvence in the XML file, but `xsdc` does not have
    // minOccurs/maxOccurs in the xsd schema.
    const std::vector<art_apex::ArtModuleInfo> art_module_infos { art_module_info.value() };

    std::optional<std::vector<art_apex::Component>> bcp_components =
        GenerateBootExtensionComponents();
    if (!bcp_components.has_value()) {
      LOG(ERROR) << "No boot classpath extension components.";
      return;
    }

    std::optional<std::vector<art_apex::Component>> system_server_components =
        GenerateSystemServerComponents();
    if (!system_server_components.has_value()) {
      LOG(ERROR) << "No system_server extension components.";
      return;
    }

    std::ofstream out(cache_info_filename_.c_str());
    art_apex::CacheInfo info{art_module_infos,
                             {{art_apex::Dex2oatBootClasspath{bcp_components.value()}}},
                             {{art_apex::SystemServerClasspath{system_server_components.value()}}}};

    art_apex::write(out, info);
  }

  // Returns cache provenance information based on the current ART APEX version and filesystem
  // information.
  std::optional<art_apex::ArtModuleInfo> GenerateArtModuleInfo() const {
    auto info = GetArtApexInfo();
    if (!info.has_value()) {
      LOG(ERROR) << "Could not update " << QuotePath(cache_info_filename_) << " : no ART Apex info";
      return {};
    }
    // The lastUpdateMillis is an addition to ApexInfoList.xsd to support samegrade installs.
    int64_t last_update_millis = info->hasLastUpdateMillis() ? info->getLastUpdateMillis() : 0;
    return art_apex::ArtModuleInfo{
        info->getVersionCode(), info->getVersionName(), last_update_millis};
  }

  bool CheckComponents(const std::vector<art_apex::Component>& expected_components,
                       const std::vector<art_apex::Component>& actual_components,
                       std::string* error_msg) const {
    if (expected_components.size() != actual_components.size()) {
      return false;
    }

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

      if (expected.getFile() != actual.getFile()) {
        *error_msg = android::base::StringPrintf("Component %zu file differs ('%s' != '%s')",
                                                 i,
                                                 expected.getFile().c_str(),
                                                 actual.getFile().c_str());
        return false;
      }
      if (expected.getSize() != actual.getSize()) {
        *error_msg = android::base::StringPrintf("Component %zu size differs (%" PRIu64
                                                 " != %" PRIu64 ")",
                                                 i,
                                                 expected.getSize(),
                                                 actual.getSize());
        return false;
      }
      if (expected.getChecksums() != actual.getChecksums()) {
        *error_msg = android::base::StringPrintf("Component %zu checksums differ ('%s' != '%s')",
                                                 i,
                                                 expected.getChecksums().c_str(),
                                                 actual.getChecksums().c_str());
        return false;
      }
    }

    return true;
  }

  std::vector<art_apex::Component> GenerateComponents(const std::vector<std::string>& jars) const {
    std::vector<art_apex::Component> components;

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

      std::vector<uint32_t> checksums;
      std::vector<std::string> dex_locations;
      std::string error_msg;
      if (!loader.GetMultiDexChecksums(path.c_str(), &checksums, &dex_locations, &error_msg)) {
        LOG(ERROR) << "Failed to get components: " << error_msg;
        return {};
      }

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

      components.emplace_back(
          art_apex::Component{path, static_cast<uint64_t>(sb.st_size), checksum});
    }

    return components;
  }

  std::vector<art_apex::Component> GenerateBootExtensionComponents() const {
    return GenerateComponents(boot_extension_compilable_jars_);
  }

  std::vector<art_apex::Component> GenerateSystemServerComponents() const {
    return GenerateComponents(systemserver_compilable_jars_);
  }

  // Checks whether a group of artifacts exists. Returns true if all are present, false otherwise.
  static bool ArtifactsExist(const OdrArtifacts& artifacts, /*out*/ std::string* error_msg) {
    const auto paths = {
        artifacts.ImagePath().c_str(), artifacts.OatPath().c_str(), artifacts.VdexPath().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;
      }
    }
    return true;
  }

  // Checks whether all boot extension artifacts are present on /data. Returns true if all are
  // present, false otherwise.
  WARN_UNUSED bool BootExtensionArtifactsExistOnData(const InstructionSet isa,
                                                     /*out*/ std::string* error_msg) const {
    const std::string apexdata_image_location = GetBootImageExtensionImagePath(isa);
    const OdrArtifacts artifacts = OdrArtifacts::ForBootImageExtension(apexdata_image_location);
    return ArtifactsExist(artifacts, error_msg);
  }

  // Checks whether all system_server artifacts are present on /data. The artifacts are checked in
  // their order of compilation. Returns true if all are present, false otherwise.
  WARN_UNUSED bool SystemServerArtifactsExistOnData(/*out*/ std::string* error_msg) const {
    for (const std::string& jar_path : systemserver_compilable_jars_) {
      const std::string image_location = GetSystemServerImagePath(/*on_system=*/false, jar_path);
      const OdrArtifacts artifacts = OdrArtifacts::ForSystemServer(image_location);
      if (!ArtifactsExist(artifacts, error_msg)) {
        return false;
      }
    }
    return true;
  }

  WARN_UNUSED ExitCode CheckArtifactsAreUpToDate(OdrMetrics& metrics) {
    metrics.SetStage(OdrMetrics::Stage::kCheck);

    // Clean-up helper used to simplify clean-ups and handling failures there.
    auto cleanup_return = [this](ExitCode exit_code) {
      return CleanApexdataDirectory() ? exit_code : ExitCode::kCleanupFailed;
    };

    const auto apex_info = GetArtApexInfo();
    if (!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::kApexVersionMismatch);
      return cleanup_return(ExitCode::kCompilationRequired);
    }

    // Generate current module info for the current ART APEX.
    const auto current_info = GenerateArtModuleInfo();
    if (!current_info.has_value()) {
      // This should never happen, further up-to-date checks are not possible if it does.
      LOG(ERROR) << "Failed to generate cache provenance.";
      metrics.SetTrigger(OdrMetrics::Trigger::kUnknown);
      return cleanup_return(ExitCode::kCompilationRequired);
    }

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

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

    if (apex_info->getIsFactory()) {
      // Remove any artifacts on /data as they are not necessary and no compilation is necessary.
      LOG(INFO) << "Factory APEX mounted.";
      return cleanup_return(ExitCode::kOkay);
    }

    if (!OS::FileExists(cache_info_filename_.c_str())) {
      // If the cache info file does not exist, assume compilation is required because the
      // file is missing and because the current ART APEX is not factory installed.
      PLOG(ERROR) << "No prior cache-info file: " << QuotePath(cache_info_filename_);
      metrics.SetTrigger(OdrMetrics::Trigger::kApexVersionMismatch);
      return cleanup_return(ExitCode::kCompilationRequired);
    }

    // Get and parse the ART APEX cache info file.
    std::optional<art_apex::CacheInfo> cache_info = ReadCacheInfo();
    if (!cache_info.has_value()) {
      // This should never happen, further up-to-date checks are not possible if it does.
      PLOG(ERROR) << "Failed to read cache-info file: " << QuotePath(cache_info_filename_);
      metrics.SetTrigger(OdrMetrics::Trigger::kUnknown);
      return cleanup_return(ExitCode::kCompilationRequired);
    }

    // Check whether the current cache ART module info differs from the current ART module info.
    // Always check APEX version.
    const auto cached_info = cache_info->getFirstArtModuleInfo();

    if (cached_info->getVersionCode() != current_info->getVersionCode()) {
      LOG(INFO) << "ART APEX version code mismatch ("
                << cached_info->getVersionCode()
                << " != " << current_info->getVersionCode() << ").";
      metrics.SetTrigger(OdrMetrics::Trigger::kApexVersionMismatch);
      return cleanup_return(ExitCode::kCompilationRequired);
    }

    if (cached_info->getVersionName() != current_info->getVersionName()) {
      LOG(INFO) << "ART APEX version name mismatch ("
                << cached_info->getVersionName()
                << " != " << current_info->getVersionName() << ").";
      metrics.SetTrigger(OdrMetrics::Trigger::kApexVersionMismatch);
      return cleanup_return(ExitCode::kCompilationRequired);
    }

    // Check lastUpdateMillis for samegrade installs. If `cached_info` is missing lastUpdateMillis
    // 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.
    if (!cached_info->hasLastUpdateMillis() ||
        cached_info->getLastUpdateMillis() != current_info->getLastUpdateMillis()) {
      LOG(INFO) << "ART APEX last update time mismatch ("
                << cached_info->getLastUpdateMillis()
                << " != " << current_info->getLastUpdateMillis() << ").";
      metrics.SetTrigger(OdrMetrics::Trigger::kApexVersionMismatch);
      return cleanup_return(ExitCode::kCompilationRequired);
    }

    // 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> expected_bcp_components =
        GenerateBootExtensionComponents();
    if (expected_bcp_components.size() != 0 &&
        (!cache_info->hasDex2oatBootClasspath() ||
         !cache_info->getFirstDex2oatBootClasspath()->hasComponent())) {
      LOG(INFO) << "Missing Dex2oatBootClasspath components.";
      metrics.SetTrigger(OdrMetrics::Trigger::kDexFilesChanged);
      return cleanup_return(ExitCode::kCompilationRequired);
    }

    std::string error_msg;
    const std::vector<art_apex::Component>& bcp_components =
        cache_info->getFirstDex2oatBootClasspath()->getComponent();
    if (!CheckComponents(expected_bcp_components, bcp_components, &error_msg)) {
      LOG(INFO) << "Dex2OatClasspath components mismatch: " << error_msg;
      metrics.SetTrigger(OdrMetrics::Trigger::kDexFilesChanged);
      return cleanup_return(ExitCode::kCompilationRequired);
    }

    // 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.
    auto cleanup_system_server_return = [this](ExitCode exit_code) {
      return RemoveSystemServerArtifactsFromData() ? exit_code : ExitCode::kCleanupFailed;
    };

    const std::vector<art_apex::Component> expected_system_server_components =
        GenerateSystemServerComponents();
    if (expected_system_server_components.size() != 0 &&
        (!cache_info->hasSystemServerClasspath() ||
         !cache_info->getFirstSystemServerClasspath()->hasComponent())) {
      LOG(INFO) << "Missing SystemServerClasspath components.";
      metrics.SetTrigger(OdrMetrics::Trigger::kDexFilesChanged);
      return cleanup_system_server_return(ExitCode::kCompilationRequired);
    }

    const std::vector<art_apex::Component>& system_server_components =
        cache_info->getFirstSystemServerClasspath()->getComponent();
    if (!CheckComponents(expected_system_server_components, system_server_components, &error_msg)) {
      LOG(INFO) << "SystemServerClasspath components mismatch: " << error_msg;
      metrics.SetTrigger(OdrMetrics::Trigger::kDexFilesChanged);
      return cleanup_system_server_return(ExitCode::kCompilationRequired);
    }

    // Cache info looks good, check all compilation artifacts exist.
    auto cleanup_boot_extensions_return = [this](ExitCode exit_code, InstructionSet isa) {
      return RemoveBootExtensionArtifactsFromData(isa) ? exit_code : ExitCode::kCleanupFailed;
    };

    for (const InstructionSet isa : config_.GetBootExtensionIsas()) {
      if (!BootExtensionArtifactsExistOnData(isa, &error_msg)) {
        LOG(INFO) << "Incomplete boot extension artifacts. " << error_msg;
        metrics.SetTrigger(OdrMetrics::Trigger::kMissingArtifacts);
        return cleanup_boot_extensions_return(ExitCode::kCompilationRequired, isa);
      }
    }

    if (!SystemServerArtifactsExistOnData(&error_msg)) {
      LOG(INFO) << "Incomplete system_server artifacts. " << error_msg;
      // No clean-up is required here: we have boot extension artifacts. The method
      // `SystemServerArtifactsExistOnData()` checks in compilation order so it is possible some of
      // the artifacts are here. We likely ran out of space compiling the system_server artifacts.
      // Any artifacts present are usable.
      metrics.SetTrigger(OdrMetrics::Trigger::kMissingArtifacts);
      return ExitCode::kCompilationRequired;
    }

    return ExitCode::kOkay;
  }

  static void AddDex2OatCommonOptions(/*inout*/ std::vector<std::string>* args) {
    args->emplace_back("--android-root=out/empty");
    args->emplace_back("--abort-on-hard-verifier-error");
    args->emplace_back("--no-abort-on-soft-verifier-error");
    args->emplace_back("--compilation-reason=boot");
    args->emplace_back("--image-format=lz4");
    args->emplace_back("--force-determinism");
    args->emplace_back("--resolve-startup-const-strings=true");
  }

  static void AddDex2OatConcurrencyArguments(/*inout*/ std::vector<std::string>* args) {
    static constexpr std::pair<const char*, const char*> kPropertyArgPairs[] = {
        std::make_pair("dalvik.vm.boot-dex2oat-cpu-set", "--cpu-set="),
        std::make_pair("dalvik.vm.boot-dex2oat-threads", "-j"),
    };
    for (auto property_arg_pair : kPropertyArgPairs) {
      auto [property, arg] = property_arg_pair;
      std::string value = android::base::GetProperty(property, {});
      if (!value.empty()) {
        args->push_back(arg + value);
      }
    }
  }

  static void AddDex2OatDebugInfo(/*inout*/ std::vector<std::string>* args) {
    args->emplace_back("--generate-mini-debug-info");
    args->emplace_back("--strip");
  }

  static void AddDex2OatInstructionSet(/*inout*/ std::vector<std::string>* args,
                                       InstructionSet isa) {
    const char* isa_str = GetInstructionSetString(isa);
    args->emplace_back(Concatenate({"--instruction-set=", isa_str}));
  }


  static void AddDex2OatProfileAndCompilerFilter(/*inout*/ std::vector<std::string>* args,
                                                 const std::string& profile_file) {
    if (OS::FileExists(profile_file.c_str(), /*check_file_type=*/true)) {
      args->emplace_back(Concatenate({"--profile-file=", profile_file}));
      args->emplace_back("--compiler-filter=speed-profile");
    } else {
      args->emplace_back("--compiler-filter=speed");
    }
  }

  WARN_UNUSED bool VerifySystemServerArtifactsAreUpToDate(bool on_system) const {
    std::vector<std::string> classloader_context;
    for (const std::string& jar_path : systemserver_compilable_jars_) {
      std::vector<std::string> args;
      args.emplace_back(config_.GetDexOptAnalyzer());
      args.emplace_back("--dex-file=" + jar_path);

      const std::string image_location = GetSystemServerImagePath(on_system, jar_path);

      // odrefresh produces app-image files, but these are not guaranteed for those pre-installed
      // on /system.
      if (!on_system && !OS::FileExists(image_location.c_str(), true)) {
        LOG(INFO) << "Missing image file: " << QuotePath(image_location);
        return false;
      }

      // Generate set of artifacts that are output by compilation.
      OdrArtifacts artifacts = OdrArtifacts::ForSystemServer(image_location);
      if (!on_system) {
        CHECK_EQ(artifacts.OatPath(),
                 GetApexDataOdexFilename(jar_path, config_.GetSystemServerIsa()));
        CHECK_EQ(artifacts.ImagePath(),
                 GetApexDataDalvikCacheFilename(jar_path, config_.GetSystemServerIsa(), "art"));
        CHECK_EQ(artifacts.OatPath(),
                 GetApexDataDalvikCacheFilename(jar_path, config_.GetSystemServerIsa(), "odex"));
        CHECK_EQ(artifacts.VdexPath(),
                 GetApexDataDalvikCacheFilename(jar_path, config_.GetSystemServerIsa(), "vdex"));
      }

      // Associate inputs and outputs with dexoptanalyzer arguments.
      std::pair<const std::string, const char*> location_args[] = {
          std::make_pair(artifacts.OatPath(), "--oat-fd="),
          std::make_pair(artifacts.VdexPath(), "--vdex-fd="),
          std::make_pair(jar_path, "--zip-fd=")
      };

      // Open file descriptors for dexoptanalyzer file inputs and add to the command-line.
      std::vector<std::unique_ptr<File>> files;
      for (const auto& location_arg : location_args) {
        auto& [location, arg] = location_arg;
        std::unique_ptr<File> file(OS::OpenFileForReading(location.c_str()));
        if (file == nullptr) {
          PLOG(ERROR) << "Failed to open \"" << location << "\"";
          return false;
        }
        args.emplace_back(android::base::StringPrintf("%s%d", arg, file->Fd()));
        files.emplace_back(file.release());
      }

      const std::string basename(android::base::Basename(jar_path));
      const std::string root = GetAndroidRoot();
      const std::string profile_file = Concatenate({root, "/framework/", basename, ".prof"});
      if (OS::FileExists(profile_file.c_str())) {
        args.emplace_back("--compiler-filter=speed-profile");
      } else {
        args.emplace_back("--compiler-filter=speed");
      }

      args.emplace_back(
          Concatenate({"--image=", GetBootImage(), ":", GetBootImageExtensionImage(on_system)}));
      args.emplace_back(
          Concatenate({"--isa=", GetInstructionSetString(config_.GetSystemServerIsa())}));
      args.emplace_back("--runtime-arg");
      args.emplace_back(Concatenate({"-Xbootclasspath:", config_.GetDex2oatBootClasspath()}));
      args.emplace_back(Concatenate(
          {"--class-loader-context=PCL[", android::base::Join(classloader_context, ':'), "]"}));

      classloader_context.emplace_back(jar_path);

      LOG(INFO) << "Checking " << jar_path << ": " << android::base::Join(args, ' ');
      std::string error_msg;
      bool timed_out = false;
      const time_t timeout = GetSubprocessTimeout();
      const int dexoptanalyzer_result = ExecAndReturnCode(args, timeout, &timed_out, &error_msg);
      if (dexoptanalyzer_result == -1) {
        LOG(ERROR) << "Unexpected exit from dexoptanalyzer: " << error_msg;
        if (timed_out) {
          // TODO(oth): record metric for timeout.
        }
        return false;
      }
      LOG(INFO) << "dexoptanalyzer returned " << dexoptanalyzer_result;

      bool unexpected_result = true;
      switch (static_cast<dexoptanalyzer::ReturnCode>(dexoptanalyzer_result)) {
        case art::dexoptanalyzer::ReturnCode::kNoDexOptNeeded:
          unexpected_result = false;
          break;

        // Recompile needed
        case art::dexoptanalyzer::ReturnCode::kDex2OatFromScratch:
        case art::dexoptanalyzer::ReturnCode::kDex2OatForBootImageOat:
        case art::dexoptanalyzer::ReturnCode::kDex2OatForFilterOat:
        case art::dexoptanalyzer::ReturnCode::kDex2OatForBootImageOdex:
        case art::dexoptanalyzer::ReturnCode::kDex2OatForFilterOdex:
          return false;

        // Unexpected issues (note no default-case here to catch missing enum values, but the
        // return code from dexoptanalyzer may also be outside expected values, such as a
        // process crash.
        case art::dexoptanalyzer::ReturnCode::kFlattenClassLoaderContextSuccess:
        case art::dexoptanalyzer::ReturnCode::kErrorInvalidArguments:
        case art::dexoptanalyzer::ReturnCode::kErrorCannotCreateRuntime:
        case art::dexoptanalyzer::ReturnCode::kErrorUnknownDexOptNeeded:
          break;
      }

      if (unexpected_result) {
        LOG(ERROR) << "Unexpected result from dexoptanalyzer: " << dexoptanalyzer_result;
        return false;
      }
    }
    return true;
  }

  WARN_UNUSED bool RemoveSystemServerArtifactsFromData() const {
    if (config_.GetDryRun()) {
      LOG(INFO) << "Removal of system_server artifacts on /data skipped (dry-run).";
      return true;
    }

    bool success = true;
    for (const std::string& jar_path : systemserver_compilable_jars_) {
      const std::string image_location =
          GetSystemServerImagePath(/*on_system=*/false, jar_path);
      const OdrArtifacts artifacts = OdrArtifacts::ForSystemServer(image_location);
      LOG(INFO) << "Removing system_server artifacts on /data for " << QuotePath(jar_path);
      success &= RemoveArtifacts(artifacts);
    }
    return success;
  }

  // Verify the validity of system server artifacts on both /system and /data.
  // This method has the side-effect of removing system server artifacts on /data, if there are
  // valid artifacts on /system, or if the artifacts on /data are not valid.
  // Returns true if valid artifacts are found.
  WARN_UNUSED bool VerifySystemServerArtifactsAreUpToDate() const {
    bool system_ok = VerifySystemServerArtifactsAreUpToDate(/*on_system=*/true);
    LOG(INFO) << "system_server artifacts on /system are " << (system_ok ? "ok" : "stale");
    bool data_ok = VerifySystemServerArtifactsAreUpToDate(/*on_system=*/false);
    LOG(INFO) << "system_server artifacts on /data are " << (data_ok ? "ok" : "stale");
    return system_ok || data_ok;
  }

  // Check the validity of boot class path extension artifacts.
  //
  // Returns true if artifacts exist and are valid according to dexoptanalyzer.
  WARN_UNUSED bool VerifyBootExtensionArtifactsAreUpToDate(const InstructionSet isa,
                                                           bool on_system) const {
    const std::string dex_file = boot_extension_compilable_jars_.front();
    const std::string image_location = GetBootImageExtensionImage(on_system);

    std::vector<std::string> args;
    args.emplace_back(config_.GetDexOptAnalyzer());
    args.emplace_back("--validate-bcp");
    args.emplace_back(Concatenate({"--image=", GetBootImage(), ":", image_location}));
    args.emplace_back(Concatenate({"--isa=", GetInstructionSetString(isa)}));
    args.emplace_back("--runtime-arg");
    args.emplace_back(Concatenate({"-Xbootclasspath:", config_.GetDex2oatBootClasspath()}));

    LOG(INFO) << "Checking " << dex_file << ": " << android::base::Join(args, ' ');

    std::string error_msg;
    bool timed_out = false;
    const time_t timeout = GetSubprocessTimeout();
    const int dexoptanalyzer_result = ExecAndReturnCode(args, timeout, &timed_out, &error_msg);
    if (dexoptanalyzer_result == -1) {
      LOG(ERROR) << "Unexpected exit from dexoptanalyzer: " << error_msg;
      if (timed_out) {
        // TODO(oth): record metric for timeout.
      }
      return false;
    }
    auto rc = static_cast<dexoptanalyzer::ReturnCode>(dexoptanalyzer_result);
    if (rc == dexoptanalyzer::ReturnCode::kNoDexOptNeeded) {
      return true;
    }
    return false;
  }

  // Remove boot extension artifacts from /data.
  WARN_UNUSED bool RemoveBootExtensionArtifactsFromData(InstructionSet isa) const {
    if (config_.GetDryRun()) {
      LOG(INFO) << "Removal of bcp extension artifacts on /data skipped (dry-run).";
      return true;
    }

    bool success = true;
    if (isa == config_.GetSystemServerIsa()) {
      // system_server artifacts are invalid without boot extension artifacts.
      success &= RemoveSystemServerArtifactsFromData();
    }

    const std::string apexdata_image_location = GetBootImageExtensionImagePath(isa);
    LOG(INFO) << "Removing boot class path artifacts on /data for "
              << QuotePath(apexdata_image_location);
    success &= RemoveArtifacts(OdrArtifacts::ForBootImageExtension(apexdata_image_location));
    return success;
  }

  // Verify whether boot extension artifacts for `isa` are valid on system partition or in apexdata.
  // This method has the side-effect of removing boot classpath extension artifacts on /data,
  // if there are valid artifacts on /system, or if the artifacts on /data are not valid.
  // Returns true if valid boot externsion artifacts are valid.
  WARN_UNUSED bool VerifyBootExtensionArtifactsAreUpToDate(InstructionSet isa) const {
    bool system_ok = VerifyBootExtensionArtifactsAreUpToDate(isa, /*on_system=*/true);
    LOG(INFO) << "Boot extension artifacts on /system are " << (system_ok ? "ok" : "stale");
    bool data_ok = VerifyBootExtensionArtifactsAreUpToDate(isa, /*on_system=*/false);
    LOG(INFO) << "Boot extension artifacts on /data are " << (data_ok ? "ok" : "stale");
    return system_ok || data_ok;
  }

  // Verify all artifacts are up-to-date.
  //
  // This method checks artifacts can be loaded by the runtime.
  //
  // Returns ExitCode::kOkay if artifacts are up-to-date, ExitCode::kCompilationRequired otherwise.
  //
  // NB This is the main function used by the --check command-line option. When invoked with
  // --compile, we only recompile the out-of-date artifacts, not all (see `Odrefresh::Compile`).
  WARN_UNUSED ExitCode VerifyArtifactsAreUpToDate() {
    ExitCode exit_code = ExitCode::kOkay;
    for (const InstructionSet isa : config_.GetBootExtensionIsas()) {
      if (!VerifyBootExtensionArtifactsAreUpToDate(isa)) {
        if (!RemoveBootExtensionArtifactsFromData(isa)) {
          return ExitCode::kCleanupFailed;
        }
        exit_code = ExitCode::kCompilationRequired;
      }
    }
    if (!VerifySystemServerArtifactsAreUpToDate()) {
      if (!RemoveSystemServerArtifactsFromData()) {
        return ExitCode::kCleanupFailed;
      }
      exit_code = ExitCode::kCompilationRequired;
    }
    return exit_code;
  }

  WARN_UNUSED bool CleanApexdataDirectory() const {
    const std::string& apex_data_path = GetArtApexData();
    if (config_.GetDryRun()) {
      LOG(INFO) << "Files under `" << QuotePath(apex_data_path) << " would be removed (dry-run).";
      return true;
    }
    return CleanDirectory(apex_data_path);
  }

  WARN_UNUSED bool RemoveArtifacts(const OdrArtifacts& artifacts) const {
    bool success = true;
    for (const auto& location :
         {artifacts.ImagePath(), artifacts.OatPath(), artifacts.VdexPath()}) {
      if (config_.GetDryRun()) {
        LOG(INFO) << "Removing " << QuotePath(location) << " (dry-run).";
        continue;
      }

      if (OS::FileExists(location.c_str()) && unlink(location.c_str()) != 0) {
        PLOG(ERROR) << "Failed to remove: " << QuotePath(location);
        success = false;
      }
    }
    return success;
  }

  static std::string GetBootImage() {
    // Typically "/apex/com.android.art/javalib/boot.art".
    return GetArtRoot() + "/javalib/boot.art";
  }

  std::string GetBootImageExtensionImage(bool on_system) const {
    CHECK(!boot_extension_compilable_jars_.empty());
    const std::string leading_jar = boot_extension_compilable_jars_[0];
    if (on_system) {
      const std::string jar_name = android::base::Basename(leading_jar);
      const std::string image_name = ReplaceFileExtension(jar_name, "art");
      // Typically "/system/framework/boot-framework.art".
      return Concatenate({GetAndroidRoot(), "/framework/boot-", image_name});
    } else {
      // Typically "/data/misc/apexdata/com.android.art/dalvik-cache/boot-framework.art".
      return GetApexDataBootImage(leading_jar);
    }
  }

  std::string GetBootImageExtensionImagePath(const InstructionSet isa) const {
    // Typically "/data/misc/apexdata/com.android.art/dalvik-cache/<isa>/boot-framework.art".
    return GetSystemImageFilename(GetBootImageExtensionImage(/*on_system=*/false).c_str(), isa);
  }

  std::string GetSystemServerImagePath(bool on_system, const std::string& jar_path) const {
    if (on_system) {
      const std::string jar_name = android::base::Basename(jar_path);
      const std::string image_name = ReplaceFileExtension(jar_name, "art");
      const char* isa_str = GetInstructionSetString(config_.GetSystemServerIsa());
      // Typically "/system/framework/oat/<isa>/services.art".
      return Concatenate({GetAndroidRoot(), "/framework/oat/", 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.c_str());
      return GetSystemImageFilename(image.c_str(), config_.GetSystemServerIsa());
    }
  }

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

  WARN_UNUSED bool CompileBootExtensionArtifacts(const InstructionSet isa,
                                                 const std::string& staging_dir,
                                                 OdrMetrics& metrics,
                                                 uint32_t* dex2oat_invocation_count,
                                                 std::string* error_msg) const {
    ScopedOdrCompilationTimer compilation_timer(metrics);
    std::vector<std::string> args;
    args.push_back(config_.GetDex2Oat());

    AddDex2OatCommonOptions(&args);
    AddDex2OatConcurrencyArguments(&args);
    AddDex2OatDebugInfo(&args);
    AddDex2OatInstructionSet(&args, isa);
    const std::string boot_profile_file(GetAndroidRoot() + "/etc/boot-image.prof");
    AddDex2OatProfileAndCompilerFilter(&args, boot_profile_file);

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

    // Set boot-image and expectation of compiling boot classpath extensions.
    args.emplace_back("--boot-image=" + GetBootImage());

    const std::string dirty_image_objects_file(GetAndroidRoot() + "/etc/dirty-image-objects");
    if (OS::FileExists(dirty_image_objects_file.c_str())) {
      args.emplace_back(Concatenate({"--dirty-image-objects=", dirty_image_objects_file}));
    } else {
      LOG(WARNING) << "Missing dirty objects file : " << QuotePath(dirty_image_objects_file);
    }

    // Add boot extensions to compile.
    for (const std::string& component : boot_extension_compilable_jars_) {
      args.emplace_back("--dex-file=" + component);
    }

    args.emplace_back("--runtime-arg");
    args.emplace_back(Concatenate({"-Xbootclasspath:", config_.GetDex2oatBootClasspath()}));

    const std::string image_location = GetBootImageExtensionImagePath(isa);
    const OdrArtifacts artifacts = OdrArtifacts::ForBootImageExtension(image_location);
    CHECK_EQ(GetApexDataOatFilename(boot_extension_compilable_jars_.front().c_str(), isa),
             artifacts.OatPath());

    args.emplace_back("--oat-location=" + artifacts.OatPath());
    const std::pair<const std::string, const char*> location_kind_pairs[] = {
        std::make_pair(artifacts.ImagePath(), "image"),
        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_pair : location_kind_pairs) {
      auto& [location, kind] = location_kind_pair;
      const std::string staging_location = GetStagingLocation(staging_dir, location);
      std::unique_ptr<File> staging_file(OS::CreateEmptyFile(staging_location.c_str()));
      if (staging_file == nullptr) {
        PLOG(ERROR) << "Failed to create " << kind << " file: " << staging_location;
        metrics.SetStatus(OdrMetrics::Status::kIoError);
        EraseFiles(staging_files);
        return false;
      }

      if (fchmod(staging_file->Fd(), S_IRUSR | S_IWUSR) != 0) {
        PLOG(ERROR) << "Could not set file mode on " << QuotePath(staging_location);
        metrics.SetStatus(OdrMetrics::Status::kIoError);
        EraseFiles(staging_files);
        return false;
      }

      args.emplace_back(android::base::StringPrintf("--%s-fd=%d", kind, staging_file->Fd()));
      staging_files.emplace_back(std::move(staging_file));
    }

    const std::string install_location = android::base::Dirname(image_location);
    if (!EnsureDirectoryExists(install_location)) {
      metrics.SetStatus(OdrMetrics::Status::kIoError);
      return false;
    }

    const time_t timeout = GetSubprocessTimeout();
    const std::string cmd_line = android::base::Join(args, ' ');
    LOG(INFO) << "Compiling boot extensions (" << isa << "): " << cmd_line
              << " [timeout " << timeout << "s]";
    if (config_.GetDryRun()) {
      LOG(INFO) << "Compilation skipped (dry-run).";
      return true;
    }

    bool timed_out = false;
    int dex2oat_exit_code = ExecAndReturnCode(args, timeout, &timed_out, error_msg);
    if (dex2oat_exit_code != 0) {
      if (timed_out) {
        metrics.SetStatus(OdrMetrics::Status::kTimeLimitExceeded);
      } else {
        metrics.SetStatus(OdrMetrics::Status::kDex2OatError);
      }
      EraseFiles(staging_files);
      return false;
    }

    if (!MoveOrEraseFiles(staging_files, install_location)) {
      metrics.SetStatus(OdrMetrics::Status::kInstallFailed);
      return false;
    }

    *dex2oat_invocation_count = *dex2oat_invocation_count + 1;
    ReportNextBootAnimationProgress(*dex2oat_invocation_count);

    return true;
  }

  WARN_UNUSED bool CompileSystemServerArtifacts(const std::string& staging_dir,
                                                OdrMetrics& metrics,
                                                uint32_t* dex2oat_invocation_count,
                                                std::string* error_msg) const {
    ScopedOdrCompilationTimer compilation_timer(metrics);
    std::vector<std::string> classloader_context;

    const std::string dex2oat = config_.GetDex2Oat();
    const InstructionSet isa = config_.GetSystemServerIsa();
    for (const std::string& jar : systemserver_compilable_jars_) {
      std::vector<std::string> args;
      args.emplace_back(dex2oat);
      args.emplace_back("--dex-file=" + jar);

      AddDex2OatCommonOptions(&args);
      AddDex2OatConcurrencyArguments(&args);
      AddDex2OatDebugInfo(&args);
      AddDex2OatInstructionSet(&args, isa);
      const std::string jar_name(android::base::Basename(jar));
      const std::string profile = Concatenate({GetAndroidRoot(), "/framework/", jar_name, ".prof"});
      std::string compiler_filter =
          android::base::GetProperty("dalvik.vm.systemservercompilerfilter", "speed");
      if (compiler_filter == "speed-profile") {
        AddDex2OatProfileAndCompilerFilter(&args, profile);
      } else {
        args.emplace_back("--compiler-filter=" + compiler_filter);
      }

      const std::string image_location = GetSystemServerImagePath(/*on_system=*/false, jar);
      const std::string install_location = android::base::Dirname(image_location);
      if (classloader_context.empty()) {
        // All images are in the same directory, we only need to check on the first iteration.
        if (!EnsureDirectoryExists(install_location)) {
          metrics.SetStatus(OdrMetrics::Status::kIoError);
          return false;
        }
      }

      OdrArtifacts artifacts = OdrArtifacts::ForSystemServer(image_location);
      CHECK_EQ(artifacts.OatPath(), GetApexDataOdexFilename(jar.c_str(), isa));

      const std::pair<const std::string, const char*> location_kind_pairs[] = {
          std::make_pair(artifacts.ImagePath(), "app-image"),
          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_pair : location_kind_pairs) {
        auto& [location, kind] = location_kind_pair;
        const std::string staging_location = GetStagingLocation(staging_dir, location);
        std::unique_ptr<File> staging_file(OS::CreateEmptyFile(staging_location.c_str()));
        if (staging_file == nullptr) {
          PLOG(ERROR) << "Failed to create " << kind << " file: " << staging_location;
          metrics.SetStatus(OdrMetrics::Status::kIoError);
          EraseFiles(staging_files);
          return false;
        }
        args.emplace_back(android::base::StringPrintf("--%s-fd=%d", kind, staging_file->Fd()));
        staging_files.emplace_back(std::move(staging_file));
      }
      args.emplace_back("--oat-location=" + artifacts.OatPath());

      if (!config_.GetUpdatableBcpPackagesFile().empty()) {
        const std::string& bcp_packages = config_.GetUpdatableBcpPackagesFile();
        if (!OS::FileExists(bcp_packages.c_str())) {
          *error_msg = "Cannot compile system_server JARs: missing " + QuotePath(bcp_packages);
          metrics.SetStatus(OdrMetrics::Status::kIoError);
          EraseFiles(staging_files);
          return false;
        }
        args.emplace_back("--updatable-bcp-packages-file=" + bcp_packages);
      }

      args.emplace_back("--runtime-arg");
      args.emplace_back(Concatenate({"-Xbootclasspath:", config_.GetDex2oatBootClasspath()}));
      const std::string context_path = android::base::Join(classloader_context, ':');
      args.emplace_back(Concatenate({"--class-loader-context=PCL[", context_path, "]"}));
      const std::string extension_image = GetBootImageExtensionImage(/*on_system=*/false);
      args.emplace_back(Concatenate({"--boot-image=", GetBootImage(), ":", extension_image}));

      const time_t timeout = GetSubprocessTimeout();
      const std::string cmd_line = android::base::Join(args, ' ');
      LOG(INFO) << "Compiling " << jar << ": " << cmd_line << " [timeout " << timeout << "s]";
      if (config_.GetDryRun()) {
        LOG(INFO) << "Compilation skipped (dry-run).";
        return true;
      }

      bool timed_out = false;
      int dex2oat_exit_code = ExecAndReturnCode(args, timeout, &timed_out, error_msg);
      if (dex2oat_exit_code != 0) {
        if (timed_out) {
          metrics.SetStatus(OdrMetrics::Status::kTimeLimitExceeded);
        } else {
          metrics.SetStatus(OdrMetrics::Status::kDex2OatError);
        }
        EraseFiles(staging_files);
        return false;
      }

      if (!MoveOrEraseFiles(staging_files, install_location)) {
        metrics.SetStatus(OdrMetrics::Status::kInstallFailed);
        return false;
      }

      *dex2oat_invocation_count = *dex2oat_invocation_count + 1;
      ReportNextBootAnimationProgress(*dex2oat_invocation_count);
      classloader_context.emplace_back(jar);
    }

    return true;
  }

  void ReportNextBootAnimationProgress(uint32_t current_compilation) const {
    uint32_t number_of_compilations =
        config_.GetBootExtensionIsas().size() + systemserver_compilable_jars_.size();
    // 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;
    android::base::SetProperty("service.bootanim.progress", std::to_string(value));
  }

  WARN_UNUSED bool CheckCompilationSpace() const {
    // 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 16MB as the largest size of an AOT artifact. Since there are three
    // AOT artifacts per compilation step - an image file, executable file, and a verification
    // data file - the threshold is three times 16MB.
    static constexpr uint64_t kMinimumSpaceForCompilation = 3 * 16 * 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;
  }

  WARN_UNUSED ExitCode Compile(OdrMetrics& metrics, bool force_compile) const {
    const char* staging_dir = nullptr;
    metrics.SetStage(OdrMetrics::Stage::kPreparation);
    // Clean-up existing files.
    if ((force_compile || !config_.GetPartialCompilation()) && !CleanApexdataDirectory()) {
      metrics.SetStatus(OdrMetrics::Status::kIoError);
      return ExitCode::kCleanupFailed;
    }

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

    // Emit cache info before compiling. This can be used to throttle compilation attempts later.
    WriteCacheInfo();

    std::string error_msg;

    uint32_t dex2oat_invocation_count = 0;
    ReportNextBootAnimationProgress(dex2oat_invocation_count);

    const auto& bcp_instruction_sets = config_.GetBootExtensionIsas();
    DCHECK(!bcp_instruction_sets.empty() && bcp_instruction_sets.size() <= 2);
    for (const InstructionSet isa : bcp_instruction_sets) {
      auto stage = (isa == bcp_instruction_sets.front()) ?
                       OdrMetrics::Stage::kPrimaryBootClasspath :
                       OdrMetrics::Stage::kSecondaryBootClasspath;
      metrics.SetStage(stage);
      if (force_compile || !BootExtensionArtifactsExistOnData(isa, &error_msg)) {
        // Remove artifacts we are about to generate. Ordinarily these are removed in the checking
        // step, but this is not always run (e.g. during manual testing).
        if (!RemoveBootExtensionArtifactsFromData(isa)) {
            return ExitCode::kCleanupFailed;
        }

        if (!CheckCompilationSpace()) {
          metrics.SetStatus(OdrMetrics::Status::kNoSpace);
          // Return kOkay so odsign will keep and sign whatever we have been able to compile.
          return ExitCode::kOkay;
        }

        if (!CompileBootExtensionArtifacts(
                isa, staging_dir, metrics, &dex2oat_invocation_count, &error_msg)) {
          LOG(ERROR) << "Compilation of BCP failed: " << error_msg;
          if (!config_.GetDryRun() && !CleanDirectory(staging_dir)) {
            return ExitCode::kCleanupFailed;
          }
          return ExitCode::kCompilationFailed;
        }
      }
    }

    if (force_compile || !SystemServerArtifactsExistOnData(&error_msg)) {
      metrics.SetStage(OdrMetrics::Stage::kSystemServerClasspath);

      if (!CheckCompilationSpace()) {
        metrics.SetStatus(OdrMetrics::Status::kNoSpace);
        // Return kOkay so odsign will keep and sign whatever we have been able to compile.
        return ExitCode::kOkay;
      }

      if (!CompileSystemServerArtifacts(
              staging_dir, metrics, &dex2oat_invocation_count, &error_msg)) {
        LOG(ERROR) << "Compilation of system_server failed: " << error_msg;
        if (!config_.GetDryRun() && !CleanDirectory(staging_dir)) {
          return ExitCode::kCleanupFailed;
        }
        return ExitCode::kCompilationFailed;
      }
    }

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

  static bool ArgumentMatches(std::string_view argument,
                              std::string_view prefix,
                              std::string* value) {
    if (StartsWith(argument, prefix)) {
      *value = std::string(argument.substr(prefix.size()));
      return true;
    }
    return false;
  }

  static bool ArgumentEquals(std::string_view argument, std::string_view expected) {
    return argument == expected;
  }

  static bool InitializeCommonConfig(std::string_view argument, OdrConfig* config) {
    static constexpr std::string_view kDryRunArgument{"--dry-run"};
    if (ArgumentEquals(argument, kDryRunArgument)) {
      config->SetDryRun();
      return true;
    }
    return false;
  }

  static int InitializeHostConfig(int argc, const char** argv, OdrConfig* config) {
    __android_log_set_logger(__android_log_stderr_logger);

    std::string current_binary;
    if (argv[0][0] == '/') {
      current_binary = argv[0];
    } else {
      std::vector<char> buf(PATH_MAX);
      if (getcwd(buf.data(), buf.size()) == nullptr) {
        PLOG(FATAL) << "Failed getwd()";
      }
      current_binary = Concatenate({buf.data(), "/", argv[0]});
    }
    config->SetArtBinDir(android::base::Dirname(current_binary));

    int n = 1;
    for (; n < argc - 1; ++n) {
      const char* arg = argv[n];
      std::string value;
      if (ArgumentMatches(arg, "--android-root=", &value)) {
        setenv("ANDROID_ROOT", value.c_str(), 1);
      } else if (ArgumentMatches(arg, "--android-art-root=", &value)) {
        setenv("ANDROID_ART_ROOT", value.c_str(), 1);
      } else if (ArgumentMatches(arg, "--apex-info-list=", &value)) {
        config->SetApexInfoListFile(value);
      } else if (ArgumentMatches(arg, "--art-apex-data=", &value)) {
        setenv("ART_APEX_DATA", value.c_str(), 1);
      } else if (ArgumentMatches(arg, "--dex2oat-bootclasspath=", &value)) {
        config->SetDex2oatBootclasspath(value);
      } else if (ArgumentMatches(arg, "--isa=", &value)) {
        config->SetIsa(GetInstructionSetFromString(value.c_str()));
      } else if (ArgumentMatches(arg, "--system-server-classpath=", &value)) {
        config->SetSystemServerClasspath(arg);
      } else if (ArgumentMatches(arg, "--updatable-bcp-packages-file=", &value)) {
        config->SetUpdatableBcpPackagesFile(value);
      } else if (ArgumentMatches(arg, "--zygote-arch=", &value)) {
        ZygoteKind zygote_kind;
        if (!ParseZygoteKind(value.c_str(), &zygote_kind)) {
          ArgumentError("Unrecognized zygote kind: '%s'", value.c_str());
        }
        config->SetZygoteKind(zygote_kind);
      } else if (!InitializeCommonConfig(arg, config)) {
        UsageError("Unrecognized argument: '%s'", arg);
      }
    }
    return n;
  }

  static int InitializeTargetConfig(int argc, const char** argv, OdrConfig* config) {
    config->SetApexInfoListFile("/apex/apex-info-list.xml");
    config->SetArtBinDir(GetArtBinDir());
    config->SetDex2oatBootclasspath(GetEnvironmentVariableOrDie("DEX2OATBOOTCLASSPATH"));
    config->SetSystemServerClasspath(GetEnvironmentVariableOrDie("SYSTEMSERVERCLASSPATH"));
    config->SetIsa(kRuntimeISA);

    const std::string zygote = android::base::GetProperty("ro.zygote", {});
    ZygoteKind zygote_kind;
    if (!ParseZygoteKind(zygote.c_str(), &zygote_kind)) {
      LOG(FATAL) << "Unknown zygote: " << QuotePath(zygote);
    }
    config->SetZygoteKind(zygote_kind);

    const std::string updatable_packages =
        android::base::GetProperty("dalvik.vm.dex2oat-updatable-bcp-packages-file", {});
    config->SetUpdatableBcpPackagesFile(updatable_packages);

    if (ShouldDisablePartialCompilation(
            android::base::GetProperty("ro.build.version.security_patch", /*default_value=*/""))) {
      config->SetPartialCompilation(false);
    }

    int n = 1;
    for (; n < argc - 1; ++n) {
      if (!InitializeCommonConfig(argv[n], config)) {
        UsageError("Unrecognized argument: '%s'", argv[n]);
      }
    }
    return n;
  }

  static int InitializeConfig(int argc, const char** argv, OdrConfig* config) {
    if (kIsTargetBuild) {
      return InitializeTargetConfig(argc, argv, config);
    } else {
      return InitializeHostConfig(argc, argv, config);
    }
  }

  static int main(int argc, const char** argv) {
    OdrConfig config(argv[0]);
    int n = InitializeConfig(argc, argv, &config);
    argv += n;
    argc -= n;
    if (argc != 1) {
      UsageError("Expected 1 argument, but have %d.", argc);
    }

    OdrMetrics metrics(kOdrefreshArtifactDirectory);
    OnDeviceRefresh odr(config);
    for (int i = 0; i < argc; ++i) {
      std::string_view action(argv[i]);
      if (action == "--check") {
        // Fast determination of whether artifacts are up to date.
        return odr.CheckArtifactsAreUpToDate(metrics);
      } else if (action == "--compile") {
        const ExitCode exit_code = odr.CheckArtifactsAreUpToDate(metrics);
        if (exit_code != ExitCode::kCompilationRequired) {
          return exit_code;
        }
        OdrCompilationLog compilation_log;
        if (!compilation_log.ShouldAttemptCompile(metrics.GetArtApexVersion(),
                                                  metrics.GetArtApexLastUpdateMillis(),
                                                  metrics.GetTrigger())) {
          return ExitCode::kOkay;
        }
        ExitCode compile_result = odr.Compile(metrics, /*force_compile=*/false);
        compilation_log.Log(metrics.GetArtApexVersion(),
                            metrics.GetArtApexLastUpdateMillis(),
                            metrics.GetTrigger(),
                            compile_result);
        return compile_result;
      } else if (action == "--force-compile") {
        return odr.Compile(metrics, /*force_compile=*/true);
      } else if (action == "--verify") {
        // Slow determination of whether artifacts are up to date. These are too slow for checking
        // during boot (b/181689036).
        return odr.VerifyArtifactsAreUpToDate();
      } else if (action == "--help") {
        UsageHelp(argv[0]);
      } else {
        UsageError("Unknown argument: ", argv[i]);
      }
    }
    return ExitCode::kOkay;
  }

  DISALLOW_COPY_AND_ASSIGN(OnDeviceRefresh);
};

}  // namespace odrefresh
}  // namespace art

int main(int argc, const char** argv) {
  // odrefresh is launched by `init` which sets the umask of forked processed to
  // 077 (S_IRWXG | S_IRWXO). This blocks the ability to make files and directories readable
  // by others and prevents system_server from loading generated artifacts.
  umask(S_IWGRP | S_IWOTH);
  return art::odrefresh::OnDeviceRefresh::main(argc, argv);
}
