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

#include "android-base/file.h"
#include "android-base/logging.h"
#include "android-base/macros.h"
#include "android-base/properties.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_common.h"
#include "odr_compilation_log.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"

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.
constexpr const char* kCacheInfoFile = "cache-info.xml";

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

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

// Extra execution time for any child process spawned in a VM.
constexpr time_t kExtraChildProcessSecondsInVm = 30;

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

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

bool CheckComponents(const std::vector<art_apex::Component>& expected_components,
                     const std::vector<art_apex::Component>& actual_components,
                     std::string* error_msg) {
  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) {
  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;
}

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

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

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

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

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

void AddDex2OatProfileAndCompilerFilter(
    /*inout*/ std::vector<std::string>* args,
    /*inout*/ std::vector<std::unique_ptr<File>>* output_files,
    const std::string& profile_path) {
  std::unique_ptr<File> profile_file(OS::OpenFileForReading(profile_path.c_str()));
  if (profile_file && profile_file->IsOpened()) {
    args->emplace_back(android::base::StringPrintf("--profile-file-fd=%d", profile_file->Fd()));
    args->emplace_back("--compiler-filter=speed-profile");
    output_files->push_back(std::move(profile_file));
  } else {
    args->emplace_back("--compiler-filter=speed");
  }
}

bool AddBootClasspathFds(/*inout*/ std::vector<std::string>& args,
                         /*inout*/ std::vector<std::unique_ptr<File>>& output_files,
                         const std::vector<std::string>& bcp_jars) {
  auto bcp_fds = std::vector<std::string>();
  for (const std::string& jar : bcp_jars) {
    std::unique_ptr<File> jar_file(OS::OpenFileForReading(jar.c_str()));
    if (!jar_file || !jar_file->IsValid()) {
      LOG(ERROR) << "Failed to open a BCP jar " << jar;
      return false;
    }
    bcp_fds.push_back(std::to_string(jar_file->Fd()));
    output_files.push_back(std::move(jar_file));
  }
  args.emplace_back("--runtime-arg");
  args.emplace_back(Concatenate({"-Xbootclasspathfds:", android::base::Join(bcp_fds, ':')}));
  return true;
}

void AddCompiledBootClasspathFdsIfAny(
    /*inout*/ std::vector<std::string>& args,
    /*inout*/ std::vector<std::unique_ptr<File>>& output_files,
    const std::vector<std::string>& bcp_jars,
    const InstructionSet isa) {
  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;
  for (const std::string& jar : bcp_jars) {
    std::string image_path = GetApexDataBootImage(jar);
    image_path = image_path.empty() ? "" : GetSystemImageFilename(image_path.c_str(), isa);
    std::unique_ptr<File> image_file(OS::OpenFileForReading(image_path.c_str()));
    if (image_file && image_file->IsValid()) {
      bcp_image_fds.push_back(std::to_string(image_file->Fd()));
      opened_files.push_back(std::move(image_file));
      added_any = true;
    } else {
      bcp_image_fds.push_back("-1");
    }

    std::string oat_path = ReplaceFileExtension(image_path, "oat");
    std::unique_ptr<File> oat_file(OS::OpenFileForReading(oat_path.c_str()));
    if (oat_file && oat_file->IsValid()) {
      bcp_oat_fds.push_back(std::to_string(oat_file->Fd()));
      opened_files.push_back(std::move(oat_file));
      added_any = true;
    } else {
      bcp_oat_fds.push_back("-1");
    }

    std::string vdex_path = ReplaceFileExtension(image_path, "vdex");
    std::unique_ptr<File> vdex_file(OS::OpenFileForReading(vdex_path.c_str()));
    if (vdex_file && vdex_file->IsValid()) {
      bcp_vdex_fds.push_back(std::to_string(vdex_file->Fd()));
      opened_files.push_back(std::move(vdex_file));
      added_any = true;
    } else {
      bcp_vdex_fds.push_back("-1");
    }
  }
  // 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.emplace_back("--runtime-arg");
    args.emplace_back(
        Concatenate({"-Xbootclasspathimagefds:", android::base::Join(bcp_image_fds, ':')}));
    args.emplace_back("--runtime-arg");
    args.emplace_back(
        Concatenate({"-Xbootclasspathoatfds:", android::base::Join(bcp_oat_fds, ':')}));
    args.emplace_back("--runtime-arg");
    args.emplace_back(
        Concatenate({"-Xbootclasspathvdexfds:", android::base::Join(bcp_vdex_fds, ':')}));
  }
}

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

std::string JoinFilesAsFDs(const std::vector<std::unique_ptr<File>>& files, char delimiter) {
  std::stringstream output;
  bool is_first = true;
  for (const auto& f : files) {
    if (is_first) {
      is_first = false;
    } else {
      output << delimiter;
    }
    output << std::to_string(f->Fd());
  }
  return output.str();
}

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

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

}  // namespace

OnDeviceRefresh::OnDeviceRefresh(const OdrConfig& config)
    : OnDeviceRefresh(config,
                      Concatenate({kOdrefreshArtifactDirectory, "/", 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)} {
  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);
    }
  }

  systemserver_compilable_jars_ = android::base::Split(config_.GetSystemServerClasspath(), ":");
  boot_classpath_jars_ = android::base::Split(config_.GetBootClasspath(), ":");

  max_child_process_seconds_ = kMaxChildProcessSeconds;
  if (config_.UseCompilationOs()) {
    // Give extra time to all of the Comp OS cases for simplicity. But really, this is only needed
    // on cuttlefish, where we run Comp OS in a slow, *nested* VM.
    // TODO(197531822): Remove once we can give the VM more CPU and/or improve the file caching.
    max_child_process_seconds_ += kExtraChildProcessSecondsInVm;
  }
}

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

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

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

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

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

std::optional<art_apex::CacheInfo> OnDeviceRefresh::ReadCacheInfo() const {
  return art_apex::read(cache_info_filename_.c_str());
}

void OnDeviceRefresh::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<std::vector<apex::ApexInfo>> apex_info_list = GetApexInfoList();
  if (!apex_info_list.has_value()) {
    LOG(ERROR) << "Could not update " << QuotePath(cache_info_filename_) << " : no APEX info";
    return;
  }

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

  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::optional<std::vector<art_apex::Component>> bcp_components =
      GenerateBootClasspathComponents();
  if (!bcp_components.has_value()) {
    LOG(ERROR) << "No boot classpath components.";
    return;
  }

  std::optional<std::vector<art_apex::Component>> bcp_compilable_components =
      GenerateBootExtensionCompilableComponents();
  if (!bcp_compilable_components.has_value()) {
    LOG(ERROR) << "No boot classpath extension compilable 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_info},
                           {art_apex::ModuleInfoList(module_info_list)},
                           {art_apex::Classpath(bcp_components.value())},
                           {art_apex::Classpath(bcp_compilable_components.value())},
                           {art_apex::Classpath(system_server_components.value())});

  art_apex::write(out, info);
}

void OnDeviceRefresh::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));
}

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

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

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

std::string OnDeviceRefresh::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 OnDeviceRefresh::GetBootImageExtensionImagePath(bool on_system,
                                                            const InstructionSet isa) const {
  // Typically "/data/misc/apexdata/com.android.art/dalvik-cache/<isa>/boot-framework.art".
  return GetSystemImageFilename(GetBootImageExtensionImage(on_system).c_str(), isa);
}

std::string OnDeviceRefresh::GetSystemServerImagePath(bool on_system,
                                                      const std::string& jar_path) const {
  if (on_system) {
    // TODO(b/194150908): Define a path for "preopted" APEX artifacts.
    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());
  }
}

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

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

WARN_UNUSED bool OnDeviceRefresh::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;
}

WARN_UNUSED bool OnDeviceRefresh::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;
}

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

WARN_UNUSED bool OnDeviceRefresh::BootExtensionArtifactsExist(
    bool on_system,
    const InstructionSet isa,
    /*out*/ std::string* error_msg) const {
  const std::string apexdata_image_location = GetBootImageExtensionImagePath(on_system, isa);
  const OdrArtifacts artifacts = OdrArtifacts::ForBootImageExtension(apexdata_image_location);
  return ArtifactsExist(artifacts, /*check_art_file=*/true, error_msg);
}

WARN_UNUSED bool OnDeviceRefresh::SystemServerArtifactsExist(bool on_system,
                                                             /*out*/ std::string* error_msg) const {
  for (const std::string& jar_path : systemserver_compilable_jars_) {
    // Temporarily skip checking APEX jar artifacts on system to prevent compilation on the first
    // boot. Currently, APEX jar artifacts can never be found on system because we don't preopt
    // them.
    // TODO(b/194150908): Preopt APEX jars for system server and put the artifacts on /system.
    if (on_system && StartsWith(jar_path, "/apex")) {
      continue;
    }
    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;
    if (!ArtifactsExist(artifacts, check_art_file, error_msg)) {
      return false;
    }
  }
  return true;
}

WARN_UNUSED bool OnDeviceRefresh::CheckBootExtensionArtifactsAreUpToDate(
    OdrMetrics& metrics,
    const InstructionSet isa,
    const apex::ApexInfo& art_apex_info,
    const std::optional<art_apex::CacheInfo>& cache_info,
    /*out*/ bool* cleanup_required) const {
  std::string error_msg;

  if (art_apex_info.getIsFactory()) {
    LOG(INFO) << "Factory ART APEX mounted.";

    // ART is not updated, so we can use the artifacts on /system. Check if they exist.
    if (BootExtensionArtifactsExist(/*on_system=*/true, isa, &error_msg)) {
      // We don't need the artifacts on /data since we can use those on /system.
      *cleanup_required = true;
      return true;
    }

    LOG(INFO) << "Incomplete boot extension artifacts on /system. " << error_msg;
    LOG(INFO) << "Checking cache.";
  }

  if (!cache_info.has_value()) {
    // If the cache info file does not exist, it means on-device compilation has not been done
    // before.
    PLOG(INFO) << "No prior cache-info file: " << QuotePath(cache_info_filename_);
    metrics.SetTrigger(OdrMetrics::Trigger::kMissingArtifacts);
    *cleanup_required = true;
    return false;
  }

  // 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(INFO) << "Missing ART APEX info from cache-info.";
    metrics.SetTrigger(OdrMetrics::Trigger::kApexVersionMismatch);
    *cleanup_required = true;
    return false;
  }

  if (cached_art_info->getVersionCode() != art_apex_info.getVersionCode()) {
    LOG(INFO) << "ART APEX version code mismatch (" << cached_art_info->getVersionCode()
              << " != " << art_apex_info.getVersionCode() << ").";
    metrics.SetTrigger(OdrMetrics::Trigger::kApexVersionMismatch);
    *cleanup_required = true;
    return false;
  }

  if (cached_art_info->getVersionName() != art_apex_info.getVersionName()) {
    LOG(INFO) << "ART APEX version name mismatch (" << cached_art_info->getVersionName()
              << " != " << art_apex_info.getVersionName() << ").";
    metrics.SetTrigger(OdrMetrics::Trigger::kApexVersionMismatch);
    *cleanup_required = true;
    return false;
  }

  // Check lastUpdateMillis for samegrade installs. If `cached_art_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_art_last_update_millis =
      cached_art_info->hasLastUpdateMillis() ? cached_art_info->getLastUpdateMillis() : -1;
  if (cached_art_last_update_millis != art_apex_info.getLastUpdateMillis()) {
    LOG(INFO) << "ART APEX last update time mismatch (" << cached_art_last_update_millis
              << " != " << art_apex_info.getLastUpdateMillis() << ").";
    metrics.SetTrigger(OdrMetrics::Trigger::kApexVersionMismatch);
    *cleanup_required = true;
    return false;
  }

  // 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_compilable_components =
      GenerateBootExtensionCompilableComponents();
  if (expected_bcp_compilable_components.size() != 0 &&
      (!cache_info->hasDex2oatBootClasspath() ||
       !cache_info->getFirstDex2oatBootClasspath()->hasComponent())) {
    LOG(INFO) << "Missing Dex2oatBootClasspath components.";
    metrics.SetTrigger(OdrMetrics::Trigger::kDexFilesChanged);
    *cleanup_required = true;
    return false;
  }

  const std::vector<art_apex::Component>& bcp_compilable_components =
      cache_info->getFirstDex2oatBootClasspath()->getComponent();
  if (!CheckComponents(expected_bcp_compilable_components, bcp_compilable_components, &error_msg)) {
    LOG(INFO) << "Dex2OatClasspath components mismatch: " << error_msg;
    metrics.SetTrigger(OdrMetrics::Trigger::kDexFilesChanged);
    *cleanup_required = true;
    return false;
  }

  // Cache info looks good, check all compilation artifacts exist.
  if (!BootExtensionArtifactsExist(/*on_system=*/false, isa, &error_msg)) {
    LOG(INFO) << "Incomplete boot extension artifacts. " << error_msg;
    metrics.SetTrigger(OdrMetrics::Trigger::kMissingArtifacts);
    *cleanup_required = true;
    return false;
  }

  *cleanup_required = false;
  return true;
}

WARN_UNUSED bool OnDeviceRefresh::CheckSystemServerArtifactsAreUpToDate(
    OdrMetrics& metrics,
    const std::vector<apex::ApexInfo>& apex_info_list,
    const std::optional<art_apex::CacheInfo>& cache_info,
    /*out*/ bool* cleanup_required) const {
  std::string error_msg;

  if (std::all_of(apex_info_list.begin(),
                  apex_info_list.end(),
                  [](const apex::ApexInfo& apex_info) { return apex_info.getIsFactory(); })) {
    LOG(INFO) << "Factory APEXes mounted.";

    // APEXes are not updated, so we can use the artifacts on /system. Check if they exist.
    if (SystemServerArtifactsExist(/*on_system=*/true, &error_msg)) {
      // We don't need the artifacts on /data since we can use those on /system.
      *cleanup_required = true;
      return true;
    }

    LOG(INFO) << "Incomplete system server artifacts on /system. " << error_msg;
    LOG(INFO) << "Checking cache.";
  }

  if (!cache_info.has_value()) {
    // If the cache info file does not exist, it means on-device compilation has not been done
    // before.
    PLOG(INFO) << "No prior cache-info file: " << QuotePath(cache_info_filename_);
    metrics.SetTrigger(OdrMetrics::Trigger::kMissingArtifacts);
    *cleanup_required = true;
    return false;
  }

  // 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(INFO) << "Missing APEX info list from cache-info.";
    metrics.SetTrigger(OdrMetrics::Trigger::kApexVersionMismatch);
    *cleanup_required = true;
    return false;
  }

  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()) {
    if (!module_info.hasName()) {
      LOG(INFO) << "Unexpected module info from cache-info. Missing module name.";
      metrics.SetTrigger(OdrMetrics::Trigger::kUnknown);
      *cleanup_required = true;
      return false;
    }
    cached_module_info_map[module_info.getName()] = &module_info;
  }

  for (const apex::ApexInfo& current_apex_info : apex_info_list) {
    auto it = cached_module_info_map.find(current_apex_info.getModuleName());
    if (it == cached_module_info_map.end()) {
      LOG(INFO) << "Missing APEX info from cache-info (" << current_apex_info.getModuleName()
                << ").";
      metrics.SetTrigger(OdrMetrics::Trigger::kApexVersionMismatch);
      *cleanup_required = true;
      return false;
    }

    const art_apex::ModuleInfo* cached_module_info = it->second;

    if (cached_module_info->getVersionCode() != current_apex_info.getVersionCode()) {
      LOG(INFO) << "APEX (" << current_apex_info.getModuleName() << ") version code mismatch ("
                << cached_module_info->getVersionCode()
                << " != " << current_apex_info.getVersionCode() << ").";
      metrics.SetTrigger(OdrMetrics::Trigger::kApexVersionMismatch);
      *cleanup_required = true;
      return false;
    }

    if (cached_module_info->getVersionName() != current_apex_info.getVersionName()) {
      LOG(INFO) << "APEX (" << current_apex_info.getModuleName() << ") version name mismatch ("
                << cached_module_info->getVersionName()
                << " != " << current_apex_info.getVersionName() << ").";
      metrics.SetTrigger(OdrMetrics::Trigger::kApexVersionMismatch);
      *cleanup_required = true;
      return false;
    }

    if (!cached_module_info->hasLastUpdateMillis() ||
        cached_module_info->getLastUpdateMillis() != current_apex_info.getLastUpdateMillis()) {
      LOG(INFO) << "APEX (" << current_apex_info.getModuleName() << ") last update time mismatch ("
                << cached_module_info->getLastUpdateMillis()
                << " != " << current_apex_info.getLastUpdateMillis() << ").";
      metrics.SetTrigger(OdrMetrics::Trigger::kApexVersionMismatch);
      *cleanup_required = true;
      return false;
    }
  }

  // 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::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);
    *cleanup_required = true;
    return false;
  }

  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);
    *cleanup_required = true;
    return false;
  }

  const std::vector<art_apex::Component> expected_bcp_components =
      GenerateBootClasspathComponents();
  if (expected_bcp_components.size() != 0 &&
      (!cache_info->hasBootClasspath() || !cache_info->getFirstBootClasspath()->hasComponent())) {
    LOG(INFO) << "Missing BootClasspath components.";
    metrics.SetTrigger(OdrMetrics::Trigger::kDexFilesChanged);
    *cleanup_required = true;
    return false;
  }

  const std::vector<art_apex::Component>& bcp_components =
      cache_info->getFirstBootClasspath()->getComponent();
  if (!CheckComponents(expected_bcp_components, bcp_components, &error_msg)) {
    LOG(INFO) << "BootClasspath components mismatch: " << error_msg;
    metrics.SetTrigger(OdrMetrics::Trigger::kDexFilesChanged);
    // Boot classpath components can be dependencies of system_server components, so system_server
    // components need to be recompiled if boot classpath components are changed.
    *cleanup_required = true;
    return false;
  }

  if (!SystemServerArtifactsExist(/*on_system=*/false, &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);
    *cleanup_required = false;
    return false;
  }

  *cleanup_required = false;
  return true;
}

WARN_UNUSED ExitCode OnDeviceRefresh::CheckArtifactsAreUpToDate(
    OdrMetrics& metrics,
    /*out*/ std::vector<InstructionSet>* compile_boot_extensions,
    /*out*/ bool* compile_system_server) const {
  metrics.SetStage(OdrMetrics::Stage::kCheck);

  // Clean-up helper used to simplify clean-ups and handling failures there.
  auto cleanup_and_compile_all = [&, this]() {
    *compile_boot_extensions = config_.GetBootExtensionIsas();
    *compile_system_server = true;
    return RemoveArtifactsDirectory() ? ExitCode::kCompilationRequired : ExitCode::kCleanupFailed;
  };

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

  std::optional<art_apex::CacheInfo> cache_info = ReadCacheInfo();
  if (!cache_info.has_value() && OS::FileExists(cache_info_filename_.c_str())) {
    // 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.
    PLOG(ERROR) << "Failed to parse cache-info file: " << QuotePath(cache_info_filename_);
    metrics.SetTrigger(OdrMetrics::Trigger::kUnknown);
    return cleanup_and_compile_all();
  }

  InstructionSet system_server_isa = config_.GetSystemServerIsa();
  bool cleanup_required;

  for (const InstructionSet isa : config_.GetBootExtensionIsas()) {
    cleanup_required = false;
    if (!CheckBootExtensionArtifactsAreUpToDate(
            metrics, isa, art_apex_info.value(), cache_info, &cleanup_required)) {
      compile_boot_extensions->push_back(isa);
      // system_server artifacts are invalid without valid boot extension artifacts.
      if (isa == system_server_isa) {
        *compile_system_server = true;
        if (!RemoveSystemServerArtifactsFromData()) {
          return ExitCode::kCleanupFailed;
        }
      }
    }
    if (cleanup_required) {
      if (!RemoveBootExtensionArtifactsFromData(isa)) {
        return ExitCode::kCleanupFailed;
      }
    }
  }

  cleanup_required = false;
  if (!*compile_system_server &&
      !CheckSystemServerArtifactsAreUpToDate(
          metrics, apex_info_list.value(), cache_info, &cleanup_required)) {
    *compile_system_server = true;
  }
  if (cleanup_required) {
    if (!RemoveSystemServerArtifactsFromData()) {
      return ExitCode::kCleanupFailed;
    }
  }

  return (!compile_boot_extensions->empty() || *compile_system_server) ?
             ExitCode::kCompilationRequired :
             ExitCode::kOkay;
}

WARN_UNUSED bool OnDeviceRefresh::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 =
      exec_utils_->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;
}

WARN_UNUSED bool OnDeviceRefresh::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;
}

WARN_UNUSED bool OnDeviceRefresh::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_.GetBootClasspath()}));
    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 =
        exec_utils_->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 OnDeviceRefresh::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;
}

WARN_UNUSED ExitCode OnDeviceRefresh::VerifyArtifactsAreUpToDate() const {
  ExitCode exit_code = ExitCode::kOkay;
  for (const InstructionSet isa : config_.GetBootExtensionIsas()) {
    if (!VerifyBootExtensionArtifactsAreUpToDate(isa)) {
      // system_server artifacts are invalid without valid boot extension artifacts.
      if (!RemoveSystemServerArtifactsFromData() || !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 OnDeviceRefresh::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);

  std::vector<std::unique_ptr<File>> readonly_files_raii;
  const std::string boot_profile_file(GetAndroidRoot() + "/etc/boot-image.prof");
  AddDex2OatProfileAndCompilerFilter(&args, &readonly_files_raii, 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())) {
    std::unique_ptr<File> file(OS::OpenFileForReading(dirty_image_objects_file.c_str()));
    args.emplace_back(android::base::StringPrintf("--dirty-image-objects-fd=%d", file->Fd()));
    readonly_files_raii.push_back(std::move(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);
    std::unique_ptr<File> file(OS::OpenFileForReading(component.c_str()));
    args.emplace_back(android::base::StringPrintf("--dex-fd=%d", file->Fd()));
    readonly_files_raii.push_back(std::move(file));
  }

  args.emplace_back("--runtime-arg");
  args.emplace_back(Concatenate({"-Xbootclasspath:", config_.GetDex2oatBootClasspath()}));
  auto bcp_jars = android::base::Split(config_.GetDex2oatBootClasspath(), ":");
  if (!AddBootClasspathFds(args, readonly_files_raii, bcp_jars)) {
    return false;
  }

  const std::string image_location = GetBootImageExtensionImagePath(/*on_system=*/false, 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;
  }

  if (config_.UseCompilationOs()) {
    std::vector<std::string> prefix_args = {
        "/apex/com.android.compos/bin/pvm_exec",
        "--cid=" + config_.GetCompilationOsAddress(),
        "--in-fd=" + JoinFilesAsFDs(readonly_files_raii, ','),
        "--out-fd=" + JoinFilesAsFDs(staging_files, ','),
        "--",
    };
    args.insert(args.begin(), prefix_args.begin(), prefix_args.end());
  }

  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 = exec_utils_->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 OnDeviceRefresh::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::unique_ptr<File>> readonly_files_raii;
    std::vector<std::string> args;
    args.emplace_back(dex2oat);
    args.emplace_back("--dex-file=" + jar);

    std::unique_ptr<File> dex_file(OS::OpenFileForReading(jar.c_str()));
    args.emplace_back(android::base::StringPrintf("--dex-fd=%d", dex_file->Fd()));
    readonly_files_raii.push_back(std::move(dex_file));

    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, &readonly_files_raii, 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;
      }
      std::unique_ptr<File> file(OS::OpenFileForReading(bcp_packages.c_str()));
      args.emplace_back(android::base::StringPrintf("--updatable-bcp-packages-fd=%d", file->Fd()));
      readonly_files_raii.push_back(std::move(file));
    }

    args.emplace_back("--runtime-arg");
    args.emplace_back(Concatenate({"-Xbootclasspath:", config_.GetBootClasspath()}));
    auto bcp_jars = android::base::Split(config_.GetBootClasspath(), ":");
    if (!AddBootClasspathFds(args, readonly_files_raii, bcp_jars)) {
      return false;
    }
    AddCompiledBootClasspathFdsIfAny(args, readonly_files_raii, bcp_jars, isa);

    const std::string context_path = android::base::Join(classloader_context, ':');
    args.emplace_back(Concatenate({"--class-loader-context=PCL[", context_path, "]"}));
    if (!classloader_context.empty()) {
      std::vector<int> fds;
      for (const std::string& path : classloader_context) {
        std::unique_ptr<File> file(OS::OpenFileForReading(path.c_str()));
        if (!file->IsValid()) {
          PLOG(ERROR) << "Failed to open classloader context " << path;
          metrics.SetStatus(OdrMetrics::Status::kIoError);
          return false;
        }
        fds.emplace_back(file->Fd());
        readonly_files_raii.emplace_back(std::move(file));
      }
      const std::string context_fds = android::base::Join(fds, ':');
      args.emplace_back(Concatenate({"--class-loader-context-fds=", context_fds}));
    }
    const std::string extension_image = GetBootImageExtensionImage(/*on_system=*/false);
    args.emplace_back(Concatenate({"--boot-image=", GetBootImage(), ":", extension_image}));

    if (config_.UseCompilationOs()) {
      std::vector<std::string> prefix_args = {
          "/apex/com.android.compos/bin/pvm_exec",
          "--cid=" + config_.GetCompilationOsAddress(),
          "--in-fd=" + JoinFilesAsFDs(readonly_files_raii, ','),
          "--out-fd=" + JoinFilesAsFDs(staging_files, ','),
          "--",
      };
      args.insert(args.begin(), prefix_args.begin(), prefix_args.end());
    }

    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 = exec_utils_->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;
}

WARN_UNUSED ExitCode
OnDeviceRefresh::Compile(OdrMetrics& metrics,
                         const std::vector<InstructionSet>& compile_boot_extensions,
                         bool compile_system_server) const {
  const char* staging_dir = nullptr;
  metrics.SetStage(OdrMetrics::Stage::kPreparation);

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

  // 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 : compile_boot_extensions) {
    auto stage = (isa == bcp_instruction_sets.front()) ? OdrMetrics::Stage::kPrimaryBootClasspath :
                                                         OdrMetrics::Stage::kSecondaryBootClasspath;
    metrics.SetStage(stage);
    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() && !RemoveDirectory(staging_dir)) {
        return ExitCode::kCleanupFailed;
      }
      return ExitCode::kCompilationFailed;
    }
  }

  if (compile_system_server) {
    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() && !RemoveDirectory(staging_dir)) {
        return ExitCode::kCleanupFailed;
      }
      return ExitCode::kCompilationFailed;
    }
  }

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

}  // namespace odrefresh
}  // namespace art
