/*
 * Copyright (C) 2021 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 "artd.h"

#include <fcntl.h>
#include <sys/inotify.h>
#include <sys/mount.h>
#include <sys/poll.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <climits>
#include <csignal>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <filesystem>
#include <functional>
#include <iterator>
#include <map>
#include <memory>
#include <mutex>
#include <new>
#include <optional>
#include <ostream>
#include <regex>
#include <string>
#include <string_view>
#include <system_error>
#include <type_traits>
#include <unordered_set>
#include <utility>
#include <vector>

#include "aidl/com/android/server/art/ArtConstants.h"
#include "aidl/com/android/server/art/BnArtd.h"
#include "aidl/com/android/server/art/DexoptTrigger.h"
#include "aidl/com/android/server/art/IArtdCancellationSignal.h"
#include "aidl/com/android/server/art/IArtdNotification.h"
#include "android-base/errors.h"
#include "android-base/file.h"
#include "android-base/logging.h"
#include "android-base/parseint.h"
#include "android-base/result.h"
#include "android-base/scopeguard.h"
#include "android-base/strings.h"
#include "android-base/unique_fd.h"
#include "android/binder_auto_utils.h"
#include "android/binder_interface_utils.h"
#include "android/binder_manager.h"
#include "android/binder_process.h"
#include "base/compiler_filter.h"
#include "base/file_magic.h"
#include "base/file_utils.h"
#include "base/globals.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/mem_map.h"
#include "base/memfd.h"
#include "base/os.h"
#include "base/pidfd.h"
#include "base/time_utils.h"
#include "base/zip_archive.h"
#include "cmdline_types.h"
#include "dex/dex_file_loader.h"
#include "exec_utils.h"
#include "file_utils.h"
#include "fstab/fstab.h"
#include "oat/oat_file_assistant.h"
#include "oat/oat_file_assistant_context.h"
#include "odrefresh/odrefresh.h"
#include "path_utils.h"
#include "profman/profman_result.h"
#include "selinux/android.h"
#include "service.h"
#include "tools/binder_utils.h"
#include "tools/cmdline_builder.h"
#include "tools/tools.h"

namespace art {
namespace artd {

namespace {

using ::aidl::com::android::server::art::ArtConstants;
using ::aidl::com::android::server::art::ArtdDexoptResult;
using ::aidl::com::android::server::art::ArtifactsLocation;
using ::aidl::com::android::server::art::ArtifactsPath;
using ::aidl::com::android::server::art::CopyAndRewriteProfileResult;
using ::aidl::com::android::server::art::DexMetadataPath;
using ::aidl::com::android::server::art::DexoptOptions;
using ::aidl::com::android::server::art::DexoptTrigger;
using ::aidl::com::android::server::art::FileVisibility;
using ::aidl::com::android::server::art::FsPermission;
using ::aidl::com::android::server::art::GetDexoptNeededResult;
using ::aidl::com::android::server::art::GetDexoptStatusResult;
using ::aidl::com::android::server::art::IArtdCancellationSignal;
using ::aidl::com::android::server::art::IArtdNotification;
using ::aidl::com::android::server::art::MergeProfileOptions;
using ::aidl::com::android::server::art::OutputArtifacts;
using ::aidl::com::android::server::art::OutputProfile;
using ::aidl::com::android::server::art::PriorityClass;
using ::aidl::com::android::server::art::ProfilePath;
using ::aidl::com::android::server::art::RuntimeArtifactsPath;
using ::aidl::com::android::server::art::VdexPath;
using ::android::base::Basename;
using ::android::base::Dirname;
using ::android::base::ErrnoError;
using ::android::base::Error;
using ::android::base::Join;
using ::android::base::make_scope_guard;
using ::android::base::ParseInt;
using ::android::base::ReadFileToString;
using ::android::base::Result;
using ::android::base::Split;
using ::android::base::Tokenize;
using ::android::base::Trim;
using ::android::base::unique_fd;
using ::android::base::WriteStringToFd;
using ::android::base::WriteStringToFile;
using ::android::fs_mgr::FstabEntry;
using ::art::service::ValidateClassLoaderContext;
using ::art::service::ValidateDexPath;
using ::art::tools::CmdlineBuilder;
using ::art::tools::Fatal;
using ::art::tools::GetProcMountsAncestorsOfPath;
using ::art::tools::NonFatal;
using ::ndk::ScopedAStatus;

using PrimaryCurProfilePath = ProfilePath::PrimaryCurProfilePath;
using TmpProfilePath = ProfilePath::TmpProfilePath;
using WritableProfilePath = ProfilePath::WritableProfilePath;

constexpr const char* kServiceName = "artd";
constexpr const char* kPreRebootServiceName = "artd_pre_reboot";
constexpr const char* kArtdCancellationSignalType = "ArtdCancellationSignal";
constexpr const char* kDefaultPreRebootTmpDir = "/mnt/artd_tmp";

// Timeout for short operations, such as merging profiles.
constexpr int kShortTimeoutSec = 60;  // 1 minute.

// Timeout for long operations, such as compilation. We set it to be smaller than the Package
// Manager watchdog (PackageManagerService.WATCHDOG_TIMEOUT, 10 minutes), so that if the operation
// is called from the Package Manager's thread handler, it will be aborted before that watchdog
// would take down the system server.
constexpr int kLongTimeoutSec = 570;  // 9.5 minutes.

std::optional<int64_t> GetSize(std::string_view path) {
  std::error_code ec;
  int64_t size = std::filesystem::file_size(path, ec);
  if (ec) {
    // It is okay if the file does not exist. We don't have to log it.
    if (ec.value() != ENOENT) {
      LOG(ERROR) << ART_FORMAT("Failed to get the file size of '{}': {}", path, ec.message());
    }
    return std::nullopt;
  }
  return size;
}

bool DeleteFile(const std::string& path) {
  std::error_code ec;
  std::filesystem::remove(path, ec);
  if (ec) {
    LOG(ERROR) << ART_FORMAT("Failed to remove '{}': {}", path, ec.message());
    return false;
  }
  return true;
}

// Deletes a file. Returns the size of the deleted file, or 0 if the deleted file is empty or an
// error occurs.
int64_t GetSizeAndDeleteFile(const std::string& path) {
  std::optional<int64_t> size = GetSize(path);
  if (!size.has_value()) {
    return 0;
  }
  if (!DeleteFile(path)) {
    return 0;
  }
  return size.value();
}

Result<CompilerFilter::Filter> ParseCompilerFilter(const std::string& compiler_filter_str) {
  CompilerFilter::Filter compiler_filter;
  if (!CompilerFilter::ParseCompilerFilter(compiler_filter_str.c_str(), &compiler_filter)) {
    return Errorf("Failed to parse compiler filter '{}'", compiler_filter_str);
  }
  return compiler_filter;
}

OatFileAssistant::DexOptTrigger DexOptTriggerFromAidl(int32_t aidl_value) {
  OatFileAssistant::DexOptTrigger trigger{};
  if ((aidl_value & static_cast<int32_t>(DexoptTrigger::COMPILER_FILTER_IS_BETTER)) != 0) {
    trigger.targetFilterIsBetter = true;
  }
  if ((aidl_value & static_cast<int32_t>(DexoptTrigger::COMPILER_FILTER_IS_SAME)) != 0) {
    trigger.targetFilterIsSame = true;
  }
  if ((aidl_value & static_cast<int32_t>(DexoptTrigger::COMPILER_FILTER_IS_WORSE)) != 0) {
    trigger.targetFilterIsWorse = true;
  }
  if ((aidl_value & static_cast<int32_t>(DexoptTrigger::PRIMARY_BOOT_IMAGE_BECOMES_USABLE)) != 0) {
    trigger.primaryBootImageBecomesUsable = true;
  }
  if ((aidl_value & static_cast<int32_t>(DexoptTrigger::NEED_EXTRACTION)) != 0) {
    trigger.needExtraction = true;
  }
  return trigger;
}

ArtifactsLocation ArtifactsLocationToAidl(OatFileAssistant::Location location) {
  switch (location) {
    case OatFileAssistant::Location::kLocationNoneOrError:
      return ArtifactsLocation::NONE_OR_ERROR;
    case OatFileAssistant::Location::kLocationOat:
      return ArtifactsLocation::DALVIK_CACHE;
    case OatFileAssistant::Location::kLocationOdex:
      return ArtifactsLocation::NEXT_TO_DEX;
    case OatFileAssistant::Location::kLocationDm:
      return ArtifactsLocation::DM;
      // No default. All cases should be explicitly handled, or the compilation will fail.
  }
  // This should never happen. Just in case we get a non-enumerator value.
  LOG(FATAL) << "Unexpected Location " << location;
}

Result<bool> CreateDir(const std::string& path) {
  std::error_code ec;
  bool created = std::filesystem::create_directory(path, ec);
  if (ec) {
    return Errorf("Failed to create directory '{}': {}", path, ec.message());
  }
  return created;
}

Result<void> PrepareArtifactsDir(const std::string& path, const FsPermission& fs_permission) {
  bool created = OR_RETURN(CreateDir(path));

  auto cleanup = make_scope_guard([&] {
    if (created) {
      std::error_code ec;
      std::filesystem::remove(path, ec);
    }
  });

  if (chmod(path.c_str(), DirFsPermissionToMode(fs_permission)) != 0) {
    return ErrnoErrorf("Failed to chmod directory '{}'", path);
  }
  OR_RETURN(Chown(path, fs_permission));

  cleanup.Disable();
  return {};
}

Result<void> PrepareArtifactsDirs(const OutputArtifacts& output_artifacts,
                                  /*out*/ std::string* oat_dir_path) {
  if (output_artifacts.artifactsPath.isInDalvikCache) {
    return {};
  }

  std::filesystem::path oat_path(
      OR_RETURN(BuildArtifactsPath(output_artifacts.artifactsPath)).oat_path);
  std::filesystem::path isa_dir = oat_path.parent_path();
  std::filesystem::path oat_dir = isa_dir.parent_path();
  DCHECK_EQ(oat_dir.filename(), "oat");

  OR_RETURN(PrepareArtifactsDir(oat_dir, output_artifacts.permissionSettings.dirFsPermission));
  OR_RETURN(PrepareArtifactsDir(isa_dir, output_artifacts.permissionSettings.dirFsPermission));
  *oat_dir_path = oat_dir;
  return {};
}

Result<FileVisibility> GetFileVisibility(const std::string& file) {
  std::error_code ec;
  std::filesystem::file_status status = std::filesystem::status(file, ec);
  if (!std::filesystem::status_known(status)) {
    return Errorf("Failed to get status of '{}': {}", file, ec.message());
  }
  if (!std::filesystem::exists(status)) {
    return FileVisibility::NOT_FOUND;
  }

  return (status.permissions() & std::filesystem::perms::others_read) !=
                 std::filesystem::perms::none ?
             FileVisibility::OTHER_READABLE :
             FileVisibility::NOT_OTHER_READABLE;
}

Result<ArtdCancellationSignal*> ToArtdCancellationSignal(IArtdCancellationSignal* input) {
  if (input == nullptr) {
    return Error() << "Cancellation signal must not be nullptr";
  }
  // We cannot use `dynamic_cast` because ART code is compiled with `-fno-rtti`, so we have to check
  // the magic number.
  int64_t type;
  if (!input->getType(&type).isOk() ||
      type != reinterpret_cast<intptr_t>(kArtdCancellationSignalType)) {
    // The cancellation signal must be created by `Artd::createCancellationSignal`.
    return Error() << "Invalid cancellation signal type";
  }
  return static_cast<ArtdCancellationSignal*>(input);
}

Result<void> CopyFile(const std::string& src_path, const NewFile& dst_file) {
  std::string content;
  if (!ReadFileToString(src_path, &content)) {
    return Errorf("Failed to read file '{}': {}", src_path, strerror(errno));
  }
  if (!WriteStringToFd(content, dst_file.Fd())) {
    return Errorf("Failed to write file '{}': {}", dst_file.TempPath(), strerror(errno));
  }
  if (fsync(dst_file.Fd()) != 0) {
    return Errorf("Failed to flush file '{}': {}", dst_file.TempPath(), strerror(errno));
  }
  if (lseek(dst_file.Fd(), /*offset=*/0, SEEK_SET) != 0) {
    return Errorf(
        "Failed to reset the offset for file '{}': {}", dst_file.TempPath(), strerror(errno));
  }
  return {};
}

Result<void> SetLogVerbosity() {
  std::string options =
      android::base::GetProperty("dalvik.vm.artd-verbose", /*default_value=*/"oat");
  if (options.empty()) {
    return {};
  }

  CmdlineType<LogVerbosity> parser;
  CmdlineParseResult<LogVerbosity> result = parser.Parse(options);
  if (!result.IsSuccess()) {
    return Error() << result.GetMessage();
  }

  gLogVerbosity = result.ReleaseValue();
  return {};
}

CopyAndRewriteProfileResult AnalyzeCopyAndRewriteProfileFailure(
    File* src, ProfmanResult::CopyAndUpdateResult result) {
  DCHECK(result == ProfmanResult::kCopyAndUpdateNoMatch ||
         result == ProfmanResult::kCopyAndUpdateErrorFailedToLoadProfile);

  auto bad_profile = [&](std::string_view error_msg) {
    return CopyAndRewriteProfileResult{
        .status = CopyAndRewriteProfileResult::Status::BAD_PROFILE,
        .errorMsg = ART_FORMAT("Failed to load profile '{}': {}", src->GetPath(), error_msg)};
  };
  CopyAndRewriteProfileResult no_profile{.status = CopyAndRewriteProfileResult::Status::NO_PROFILE,
                                         .errorMsg = ""};

  int64_t length = src->GetLength();
  if (length < 0) {
    return bad_profile(strerror(-length));
  }
  if (length == 0) {
    return no_profile;
  }

  std::string error_msg;
  uint32_t magic;
  if (!ReadMagicAndReset(src->Fd(), &magic, &error_msg)) {
    return bad_profile(error_msg);
  }
  if (IsZipMagic(magic)) {
    std::unique_ptr<ZipArchive> zip_archive(
        ZipArchive::OpenFromOwnedFd(src->Fd(), src->GetPath().c_str(), &error_msg));
    if (zip_archive == nullptr) {
      return bad_profile(error_msg);
    }
    std::unique_ptr<ZipEntry> zip_entry(
        zip_archive->Find(ArtConstants::DEX_METADATA_PROFILE_ENTRY, &error_msg));
    if (zip_entry == nullptr || zip_entry->GetUncompressedLength() == 0) {
      return no_profile;
    }
  }

  if (result == ProfmanResult::kCopyAndUpdateNoMatch) {
    return bad_profile(
        "The profile does not match the APK (The checksums in the profile do not match the "
        "checksums of the .dex files in the APK)");
  }
  return bad_profile("The profile is in the wrong format or an I/O error has occurred");
}

// Returns the fd on success, or an invalid fd if the dex file contains no profile, or error if any
// error occurs.
Result<File> ExtractEmbeddedProfileToFd(const std::string& dex_path) {
  std::unique_ptr<File> dex_file = OR_RETURN(OpenFileForReading(dex_path));

  std::string error_msg;
  uint32_t magic;
  if (!ReadMagicAndReset(dex_file->Fd(), &magic, &error_msg)) {
    return Error() << error_msg;
  }
  if (!IsZipMagic(magic)) {
    if (DexFileLoader::IsMagicValid(magic)) {
      // The dex file can be a plain dex file. This is expected.
      return File();
    }
    return Error() << "File is neither a zip file nor a plain dex file";
  }

  std::unique_ptr<ZipArchive> zip_archive(
      ZipArchive::OpenFromOwnedFd(dex_file->Fd(), dex_path.c_str(), &error_msg));
  if (zip_archive == nullptr) {
    return Error() << error_msg;
  }
  constexpr const char* kEmbeddedProfileEntry = "assets/art-profile/baseline.prof";
  std::unique_ptr<ZipEntry> zip_entry(zip_archive->Find(kEmbeddedProfileEntry, &error_msg));
  size_t size;
  if (zip_entry == nullptr || (size = zip_entry->GetUncompressedLength()) == 0) {
    // From system/libziparchive/zip_error.cpp.
    constexpr const char* kEntryNotFound = "Entry not found";
    if (error_msg != kEntryNotFound) {
      LOG(WARNING) << ART_FORMAT(
          "Failed to find zip entry '{}' in '{}': {}", kEmbeddedProfileEntry, dex_path, error_msg);
    }
    // The dex file doesn't necessarily contain a profile. This is expected.
    return File();
  }

  // The name is for debugging only.
  std::string memfd_name =
      ART_FORMAT("{} extracted in memory from {}", kEmbeddedProfileEntry, dex_path);
  File memfd(memfd_create(memfd_name.c_str(), /*flags=*/0),
             memfd_name,
             /*check_usage=*/false);
  if (!memfd.IsValid()) {
    return ErrnoError() << "Failed to create memfd";
  }
  if (ftruncate(memfd.Fd(), size) != 0) {
    return ErrnoError() << "Failed to ftruncate memfd";
  }
  // Map with MAP_SHARED because we're feeding the fd to profman.
  MemMap mem_map = MemMap::MapFile(size,
                                   PROT_READ | PROT_WRITE,
                                   MAP_SHARED,
                                   memfd.Fd(),
                                   /*start=*/0,
                                   /*low_4gb=*/false,
                                   memfd_name.c_str(),
                                   &error_msg);
  if (!mem_map.IsValid()) {
    return Errorf("Failed to mmap memfd: {}", error_msg);
  }
  if (!zip_entry->ExtractToMemory(mem_map.Begin(), &error_msg)) {
    return Errorf("Failed to extract '{}': {}", kEmbeddedProfileEntry, error_msg);
  }

  // Reopen the memfd with readonly to make SELinux happy when the fd is passed to a child process
  // who doesn't have write permission. (b/303909581)
  std::string path = ART_FORMAT("/proc/self/fd/{}", memfd.Fd());
  // NOLINTNEXTLINE - O_CLOEXEC is omitted on purpose
  File memfd_readonly(open(path.c_str(), O_RDONLY),
                      memfd_name,
                      /*check_usage=*/false,
                      /*read_only_mode=*/true);
  if (!memfd_readonly.IsOpened()) {
    return ErrnoErrorf("Failed to open file '{}' ('{}')", path, memfd_name);
  }

  return memfd_readonly;
}

class FdLogger {
 public:
  void Add(const NewFile& file) { fd_mapping_.emplace_back(file.Fd(), file.TempPath()); }
  void Add(const File& file) { fd_mapping_.emplace_back(file.Fd(), file.GetPath()); }

  std::string GetFds() {
    std::vector<int> fds;
    fds.reserve(fd_mapping_.size());
    for (const auto& [fd, path] : fd_mapping_) {
      fds.push_back(fd);
    }
    return Join(fds, ':');
  }

 private:
  std::vector<std::pair<int, std::string>> fd_mapping_;

  friend std::ostream& operator<<(std::ostream& os, const FdLogger& fd_logger);
};

std::ostream& operator<<(std::ostream& os, const FdLogger& fd_logger) {
  for (const auto& [fd, path] : fd_logger.fd_mapping_) {
    os << fd << ":" << path << ' ';
  }
  return os;
}

}  // namespace

#define RETURN_FATAL_IF_PRE_REBOOT(options)                                 \
  if ((options).is_pre_reboot) {                                            \
    return Fatal("This method is not supported in Pre-reboot Dexopt mode"); \
  }

#define RETURN_FATAL_IF_NOT_PRE_REBOOT(options)                              \
  if (!(options).is_pre_reboot) {                                            \
    return Fatal("This method is only supported in Pre-reboot Dexopt mode"); \
  }

#define RETURN_FATAL_IF_ARG_IS_PRE_REBOOT_IMPL(expected, arg, log_name)                        \
  {                                                                                            \
    auto&& __return_fatal_tmp = PreRebootFlag(arg);                                            \
    if ((expected) != __return_fatal_tmp) {                                                    \
      return Fatal(ART_FORMAT("Expected flag 'isPreReboot' in argument '{}' to be {}, got {}", \
                              log_name,                                                        \
                              expected,                                                        \
                              __return_fatal_tmp));                                            \
    }                                                                                          \
  }

#define RETURN_FATAL_IF_PRE_REBOOT_MISMATCH(options, arg, log_name) \
  RETURN_FATAL_IF_ARG_IS_PRE_REBOOT_IMPL((options).is_pre_reboot, arg, log_name)

#define RETURN_FATAL_IF_ARG_IS_PRE_REBOOT(arg, log_name) \
  RETURN_FATAL_IF_ARG_IS_PRE_REBOOT_IMPL(false, arg, log_name)

Result<void> Restorecon(
    const std::string& path,
    const std::optional<OutputArtifacts::PermissionSettings::SeContext>& se_context,
    bool recurse) {
  if (!kIsTargetAndroid) {
    return {};
  }

  unsigned int flags = recurse ? SELINUX_ANDROID_RESTORECON_RECURSE : 0;
  int res = 0;
  if (se_context.has_value()) {
    res = selinux_android_restorecon_pkgdir(
        path.c_str(), se_context->seInfo.c_str(), se_context->uid, flags);
  } else {
    res = selinux_android_restorecon(path.c_str(), flags);
  }
  if (res != 0) {
    return ErrnoErrorf("Failed to restorecon directory '{}'", path);
  }
  return {};
}

ScopedAStatus Artd::isAlive(bool* _aidl_return) {
  *_aidl_return = true;
  return ScopedAStatus::ok();
}

ScopedAStatus Artd::deleteArtifacts(const ArtifactsPath& in_artifactsPath, int64_t* _aidl_return) {
  RETURN_FATAL_IF_PRE_REBOOT(options_);
  RETURN_FATAL_IF_ARG_IS_PRE_REBOOT(in_artifactsPath, "artifactsPath");

  RawArtifactsPath path = OR_RETURN_FATAL(BuildArtifactsPath(in_artifactsPath));

  *_aidl_return = 0;
  *_aidl_return += GetSizeAndDeleteFile(path.oat_path);
  *_aidl_return += GetSizeAndDeleteFile(path.vdex_path);
  *_aidl_return += GetSizeAndDeleteFile(path.art_path);

  return ScopedAStatus::ok();
}

ScopedAStatus Artd::getDexoptStatus(const std::string& in_dexFile,
                                    const std::string& in_instructionSet,
                                    const std::optional<std::string>& in_classLoaderContext,
                                    GetDexoptStatusResult* _aidl_return) {
  RETURN_FATAL_IF_PRE_REBOOT(options_);

  Result<OatFileAssistantContext*> ofa_context = GetOatFileAssistantContext();
  if (!ofa_context.ok()) {
    return NonFatal("Failed to get runtime options: " + ofa_context.error().message());
  }

  std::unique_ptr<ClassLoaderContext> context;
  std::string error_msg;
  auto oat_file_assistant = OatFileAssistant::Create(in_dexFile,
                                                     in_instructionSet,
                                                     in_classLoaderContext,
                                                     /*load_executable=*/false,
                                                     /*only_load_trusted_executable=*/true,
                                                     ofa_context.value(),
                                                     &context,
                                                     &error_msg);
  if (oat_file_assistant == nullptr) {
    return NonFatal("Failed to create OatFileAssistant: " + error_msg);
  }

  std::string ignored_odex_status;
  OatFileAssistant::Location location;
  oat_file_assistant->GetOptimizationStatus(&_aidl_return->locationDebugString,
                                            &_aidl_return->compilerFilter,
                                            &_aidl_return->compilationReason,
                                            &ignored_odex_status,
                                            &location);
  _aidl_return->artifactsLocation = ArtifactsLocationToAidl(location);

  // We ignore odex_status because it is not meaningful. It can only be either "up-to-date",
  // "apk-more-recent", or "io-error-no-oat", which means it doesn't give us information in addition
  // to what we can learn from compiler_filter because compiler_filter will be the actual compiler
  // filter, "run-from-apk-fallback", and "run-from-apk" in those three cases respectively.
  DCHECK(ignored_odex_status == "up-to-date" || ignored_odex_status == "apk-more-recent" ||
         ignored_odex_status == "io-error-no-oat");

  return ScopedAStatus::ok();
}

ndk::ScopedAStatus Artd::isProfileUsable(const ProfilePath& in_profile,
                                         const std::string& in_dexFile,
                                         bool* _aidl_return) {
  RETURN_FATAL_IF_ARG_IS_PRE_REBOOT(in_profile, "profile");

  std::string profile_path = OR_RETURN_FATAL(BuildProfileOrDmPath(in_profile));
  OR_RETURN_FATAL(ValidateDexPath(in_dexFile));

  FdLogger fd_logger;

  CmdlineBuilder art_exec_args = OR_RETURN_FATAL(GetArtExecCmdlineBuilder());

  CmdlineBuilder args;
  args.Add(OR_RETURN_FATAL(GetProfman()));

  Result<std::unique_ptr<File>> profile = OpenFileForReading(profile_path);
  if (!profile.ok()) {
    if (profile.error().code() == ENOENT) {
      *_aidl_return = false;
      return ScopedAStatus::ok();
    }
    return NonFatal(
        ART_FORMAT("Failed to open profile '{}': {}", profile_path, profile.error().message()));
  }
  args.Add("--reference-profile-file-fd=%d", profile.value()->Fd());
  fd_logger.Add(*profile.value());

  std::unique_ptr<File> dex_file = OR_RETURN_NON_FATAL(OpenFileForReading(in_dexFile));
  args.Add("--apk-fd=%d", dex_file->Fd());
  fd_logger.Add(*dex_file);

  art_exec_args.Add("--keep-fds=%s", fd_logger.GetFds()).Add("--").Concat(std::move(args));

  LOG(INFO) << "Running profman: " << Join(art_exec_args.Get(), /*separator=*/" ")
            << "\nOpened FDs: " << fd_logger;

  Result<int> result = ExecAndReturnCode(art_exec_args.Get(), kShortTimeoutSec);
  if (!result.ok()) {
    return NonFatal("Failed to run profman: " + result.error().message());
  }

  LOG(INFO) << ART_FORMAT("profman returned code {}", result.value());

  if (result.value() != ProfmanResult::kSkipCompilationSmallDelta &&
      result.value() != ProfmanResult::kSkipCompilationEmptyProfiles) {
    return NonFatal(ART_FORMAT("profman returned an unexpected code: {}", result.value()));
  }

  *_aidl_return = result.value() == ProfmanResult::kSkipCompilationSmallDelta;
  return ScopedAStatus::ok();
}

ndk::ScopedAStatus Artd::CopyAndRewriteProfileImpl(File src,
                                                   OutputProfile* dst_aidl,
                                                   const std::string& dex_path,
                                                   CopyAndRewriteProfileResult* aidl_return) {
  RETURN_FATAL_IF_PRE_REBOOT_MISMATCH(options_, *dst_aidl, "dst");
  std::string dst_path = OR_RETURN_FATAL(BuildFinalProfilePath(dst_aidl->profilePath));
  OR_RETURN_FATAL(ValidateDexPath(dex_path));

  FdLogger fd_logger;

  CmdlineBuilder art_exec_args = OR_RETURN_FATAL(GetArtExecCmdlineBuilder());

  CmdlineBuilder args;
  args.Add(OR_RETURN_FATAL(GetProfman())).Add("--copy-and-update-profile-key");

  args.Add("--profile-file-fd=%d", src.Fd());
  fd_logger.Add(src);

  std::unique_ptr<File> dex_file = OR_RETURN_NON_FATAL(OpenFileForReading(dex_path));
  args.Add("--apk-fd=%d", dex_file->Fd());
  fd_logger.Add(*dex_file);

  std::unique_ptr<NewFile> dst =
      OR_RETURN_NON_FATAL(NewFile::Create(dst_path, dst_aidl->fsPermission));
  args.Add("--reference-profile-file-fd=%d", dst->Fd());
  fd_logger.Add(*dst);

  art_exec_args.Add("--keep-fds=%s", fd_logger.GetFds()).Add("--").Concat(std::move(args));

  LOG(INFO) << "Running profman: " << Join(art_exec_args.Get(), /*separator=*/" ")
            << "\nOpened FDs: " << fd_logger;

  Result<int> result = ExecAndReturnCode(art_exec_args.Get(), kShortTimeoutSec);
  if (!result.ok()) {
    return NonFatal("Failed to run profman: " + result.error().message());
  }

  LOG(INFO) << ART_FORMAT("profman returned code {}", result.value());

  if (result.value() == ProfmanResult::kCopyAndUpdateNoMatch ||
      result.value() == ProfmanResult::kCopyAndUpdateErrorFailedToLoadProfile) {
    *aidl_return = AnalyzeCopyAndRewriteProfileFailure(
        &src, static_cast<ProfmanResult::CopyAndUpdateResult>(result.value()));
    return ScopedAStatus::ok();
  }

  if (result.value() != ProfmanResult::kCopyAndUpdateSuccess) {
    return NonFatal(ART_FORMAT("profman returned an unexpected code: {}", result.value()));
  }

  OR_RETURN_NON_FATAL(dst->Keep());
  aidl_return->status = CopyAndRewriteProfileResult::Status::SUCCESS;
  dst_aidl->profilePath.id = dst->TempId();
  dst_aidl->profilePath.tmpPath = dst->TempPath();
  return ScopedAStatus::ok();
}

ndk::ScopedAStatus Artd::copyAndRewriteProfile(const ProfilePath& in_src,
                                               OutputProfile* in_dst,
                                               const std::string& in_dexFile,
                                               CopyAndRewriteProfileResult* _aidl_return) {
  RETURN_FATAL_IF_ARG_IS_PRE_REBOOT(in_src, "src");

  std::string src_path = OR_RETURN_FATAL(BuildProfileOrDmPath(in_src));

  Result<std::unique_ptr<File>> src = OpenFileForReading(src_path);
  if (!src.ok()) {
    if (src.error().code() == ENOENT) {
      _aidl_return->status = CopyAndRewriteProfileResult::Status::NO_PROFILE;
      return ScopedAStatus::ok();
    }
    return NonFatal(
        ART_FORMAT("Failed to open src profile '{}': {}", src_path, src.error().message()));
  }

  return CopyAndRewriteProfileImpl(std::move(*src.value()), in_dst, in_dexFile, _aidl_return);
}

ndk::ScopedAStatus Artd::copyAndRewriteEmbeddedProfile(OutputProfile* in_dst,
                                                       const std::string& in_dexFile,
                                                       CopyAndRewriteProfileResult* _aidl_return) {
  OR_RETURN_FATAL(ValidateDexPath(in_dexFile));

  Result<File> src = ExtractEmbeddedProfileToFd(in_dexFile);
  if (!src.ok()) {
    return NonFatal(ART_FORMAT(
        "Failed to extract profile from dex file '{}': {}", in_dexFile, src.error().message()));
  }
  if (!src->IsValid()) {
    _aidl_return->status = CopyAndRewriteProfileResult::Status::NO_PROFILE;
    return ScopedAStatus::ok();
  }

  return CopyAndRewriteProfileImpl(std::move(src.value()), in_dst, in_dexFile, _aidl_return);
}

ndk::ScopedAStatus Artd::commitTmpProfile(const TmpProfilePath& in_profile) {
  RETURN_FATAL_IF_PRE_REBOOT_MISMATCH(options_, in_profile, "profile");
  std::string tmp_profile_path = OR_RETURN_FATAL(BuildTmpProfilePath(in_profile));
  std::string ref_profile_path = OR_RETURN_FATAL(BuildFinalProfilePath(in_profile));

  std::error_code ec;
  std::filesystem::rename(tmp_profile_path, ref_profile_path, ec);
  if (ec) {
    return NonFatal(ART_FORMAT(
        "Failed to move '{}' to '{}': {}", tmp_profile_path, ref_profile_path, ec.message()));
  }

  return ScopedAStatus::ok();
}

ndk::ScopedAStatus Artd::deleteProfile(const ProfilePath& in_profile) {
  // `in_profile` can be either a Pre-reboot path or an ordinary one.
  std::string profile_path = OR_RETURN_FATAL(BuildProfileOrDmPath(in_profile));
  DeleteFile(profile_path);

  return ScopedAStatus::ok();
}

ndk::ScopedAStatus Artd::getProfileVisibility(const ProfilePath& in_profile,
                                              FileVisibility* _aidl_return) {
  RETURN_FATAL_IF_ARG_IS_PRE_REBOOT(in_profile, "profile");
  std::string profile_path = OR_RETURN_FATAL(BuildProfileOrDmPath(in_profile));
  *_aidl_return = OR_RETURN_NON_FATAL(GetFileVisibility(profile_path));
  return ScopedAStatus::ok();
}

ndk::ScopedAStatus Artd::getArtifactsVisibility(const ArtifactsPath& in_artifactsPath,
                                                FileVisibility* _aidl_return) {
  // `in_artifactsPath` can be either a Pre-reboot path or an ordinary one.
  std::string oat_path = OR_RETURN_FATAL(BuildArtifactsPath(in_artifactsPath)).oat_path;
  *_aidl_return = OR_RETURN_NON_FATAL(GetFileVisibility(oat_path));
  return ScopedAStatus::ok();
}

ndk::ScopedAStatus Artd::getDexFileVisibility(const std::string& in_dexFile,
                                              FileVisibility* _aidl_return) {
  OR_RETURN_FATAL(ValidateDexPath(in_dexFile));
  *_aidl_return = OR_RETURN_NON_FATAL(GetFileVisibility(in_dexFile));
  return ScopedAStatus::ok();
}

ndk::ScopedAStatus Artd::getDmFileVisibility(const DexMetadataPath& in_dmFile,
                                             FileVisibility* _aidl_return) {
  std::string dm_path = OR_RETURN_FATAL(BuildDexMetadataPath(in_dmFile));
  *_aidl_return = OR_RETURN_NON_FATAL(GetFileVisibility(dm_path));
  return ScopedAStatus::ok();
}

ndk::ScopedAStatus Artd::mergeProfiles(const std::vector<ProfilePath>& in_profiles,
                                       const std::optional<ProfilePath>& in_referenceProfile,
                                       OutputProfile* in_outputProfile,
                                       const std::vector<std::string>& in_dexFiles,
                                       const MergeProfileOptions& in_options,
                                       bool* _aidl_return) {
  std::vector<std::string> profile_paths;
  for (const ProfilePath& profile : in_profiles) {
    RETURN_FATAL_IF_ARG_IS_PRE_REBOOT(profile, "profiles");
    std::string profile_path = OR_RETURN_FATAL(BuildProfileOrDmPath(profile));
    if (profile.getTag() == ProfilePath::dexMetadataPath) {
      return Fatal(ART_FORMAT("Does not support DM file, got '{}'", profile_path));
    }
    profile_paths.push_back(std::move(profile_path));
  }

  RETURN_FATAL_IF_PRE_REBOOT_MISMATCH(options_, *in_outputProfile, "outputProfile");
  std::string output_profile_path =
      OR_RETURN_FATAL(BuildFinalProfilePath(in_outputProfile->profilePath));
  for (const std::string& dex_file : in_dexFiles) {
    OR_RETURN_FATAL(ValidateDexPath(dex_file));
  }
  if (in_options.forceMerge + in_options.dumpOnly + in_options.dumpClassesAndMethods > 1) {
    return Fatal("Only one of 'forceMerge', 'dumpOnly', and 'dumpClassesAndMethods' can be set");
  }

  FdLogger fd_logger;

  CmdlineBuilder art_exec_args = OR_RETURN_FATAL(GetArtExecCmdlineBuilder());

  CmdlineBuilder args;
  args.Add(OR_RETURN_FATAL(GetProfman()));

  std::vector<std::unique_ptr<File>> profile_files;
  for (const std::string& profile_path : profile_paths) {
    Result<std::unique_ptr<File>> profile_file = OpenFileForReading(profile_path);
    if (!profile_file.ok()) {
      if (profile_file.error().code() == ENOENT) {
        // Skip non-existing file.
        continue;
      }
      return NonFatal(ART_FORMAT(
          "Failed to open profile '{}': {}", profile_path, profile_file.error().message()));
    }
    args.Add("--profile-file-fd=%d", profile_file.value()->Fd());
    fd_logger.Add(*profile_file.value());
    profile_files.push_back(std::move(profile_file.value()));
  }

  if (profile_files.empty()) {
    LOG(INFO) << "Merge skipped because there are no existing profiles";
    *_aidl_return = false;
    return ScopedAStatus::ok();
  }

  std::unique_ptr<NewFile> output_profile_file =
      OR_RETURN_NON_FATAL(NewFile::Create(output_profile_path, in_outputProfile->fsPermission));

  if (in_referenceProfile.has_value()) {
    if (in_options.dumpOnly || in_options.dumpClassesAndMethods) {
      return Fatal(
          "Reference profile must not be set when 'dumpOnly' or 'dumpClassesAndMethods' is set");
    }
    // `in_referenceProfile` can be either a Pre-reboot profile or an ordinary one.
    std::string reference_profile_path =
        OR_RETURN_FATAL(BuildProfileOrDmPath(*in_referenceProfile));
    if (in_referenceProfile->getTag() == ProfilePath::dexMetadataPath) {
      return Fatal(ART_FORMAT("Does not support DM file, got '{}'", reference_profile_path));
    }
    OR_RETURN_NON_FATAL(CopyFile(reference_profile_path, *output_profile_file));
  }

  if (in_options.dumpOnly || in_options.dumpClassesAndMethods) {
    args.Add("--dump-output-to-fd=%d", output_profile_file->Fd());
  } else {
    // profman is ok with this being an empty file when in_referenceProfile isn't set.
    args.Add("--reference-profile-file-fd=%d", output_profile_file->Fd());
  }
  fd_logger.Add(*output_profile_file);

  std::vector<std::unique_ptr<File>> dex_files;
  for (const std::string& dex_path : in_dexFiles) {
    std::unique_ptr<File> dex_file = OR_RETURN_NON_FATAL(OpenFileForReading(dex_path));
    args.Add("--apk-fd=%d", dex_file->Fd());
    fd_logger.Add(*dex_file);
    dex_files.push_back(std::move(dex_file));
  }

  if (in_options.dumpOnly || in_options.dumpClassesAndMethods) {
    args.Add(in_options.dumpOnly ? "--dump-only" : "--dump-classes-and-methods");
  } else {
    args.AddIfNonEmpty("--min-new-classes-percent-change=%s",
                       props_->GetOrEmpty("dalvik.vm.bgdexopt.new-classes-percent"))
        .AddIfNonEmpty("--min-new-methods-percent-change=%s",
                       props_->GetOrEmpty("dalvik.vm.bgdexopt.new-methods-percent"))
        .AddIf(in_options.forceMerge, "--force-merge-and-analyze")
        .AddIf(in_options.forBootImage, "--boot-image-merge");
  }

  art_exec_args.Add("--keep-fds=%s", fd_logger.GetFds()).Add("--").Concat(std::move(args));

  LOG(INFO) << "Running profman: " << Join(art_exec_args.Get(), /*separator=*/" ")
            << "\nOpened FDs: " << fd_logger;

  Result<int> result = ExecAndReturnCode(art_exec_args.Get(), kShortTimeoutSec);
  if (!result.ok()) {
    return NonFatal("Failed to run profman: " + result.error().message());
  }

  LOG(INFO) << ART_FORMAT("profman returned code {}", result.value());

  if (result.value() == ProfmanResult::kSkipCompilationSmallDelta ||
      result.value() == ProfmanResult::kSkipCompilationEmptyProfiles) {
    *_aidl_return = false;
    return ScopedAStatus::ok();
  }

  ProfmanResult::ProcessingResult expected_result =
      (in_options.dumpOnly || in_options.dumpClassesAndMethods) ? ProfmanResult::kSuccess :
                                                                  ProfmanResult::kCompile;
  if (result.value() != expected_result) {
    return NonFatal(ART_FORMAT("profman returned an unexpected code: {}", result.value()));
  }

  OR_RETURN_NON_FATAL(output_profile_file->Keep());
  *_aidl_return = true;
  in_outputProfile->profilePath.id = output_profile_file->TempId();
  in_outputProfile->profilePath.tmpPath = output_profile_file->TempPath();
  return ScopedAStatus::ok();
}

ndk::ScopedAStatus Artd::getDexoptNeeded(const std::string& in_dexFile,
                                         const std::string& in_instructionSet,
                                         const std::optional<std::string>& in_classLoaderContext,
                                         const std::string& in_compilerFilter,
                                         int32_t in_dexoptTrigger,
                                         GetDexoptNeededResult* _aidl_return) {
  Result<OatFileAssistantContext*> ofa_context = GetOatFileAssistantContext();
  if (!ofa_context.ok()) {
    return NonFatal("Failed to get runtime options: " + ofa_context.error().message());
  }

  std::unique_ptr<ClassLoaderContext> context;
  std::string error_msg;
  auto oat_file_assistant = OatFileAssistant::Create(in_dexFile,
                                                     in_instructionSet,
                                                     in_classLoaderContext,
                                                     /*load_executable=*/false,
                                                     /*only_load_trusted_executable=*/true,
                                                     ofa_context.value(),
                                                     &context,
                                                     &error_msg);
  if (oat_file_assistant == nullptr) {
    return NonFatal("Failed to create OatFileAssistant: " + error_msg);
  }

  OatFileAssistant::DexOptStatus status;
  _aidl_return->isDexoptNeeded =
      oat_file_assistant->GetDexOptNeeded(OR_RETURN_FATAL(ParseCompilerFilter(in_compilerFilter)),
                                          DexOptTriggerFromAidl(in_dexoptTrigger),
                                          &status);
  _aidl_return->isVdexUsable = status.IsVdexUsable();
  _aidl_return->artifactsLocation = ArtifactsLocationToAidl(status.GetLocation());

  std::optional<bool> has_dex_files = oat_file_assistant->HasDexFiles(&error_msg);
  if (!has_dex_files.has_value()) {
    return NonFatal("Failed to open dex file: " + error_msg);
  }
  _aidl_return->hasDexCode = *has_dex_files;

  return ScopedAStatus::ok();
}

ndk::ScopedAStatus Artd::dexopt(
    const OutputArtifacts& in_outputArtifacts,
    const std::string& in_dexFile,
    const std::string& in_instructionSet,
    const std::optional<std::string>& in_classLoaderContext,
    const std::string& in_compilerFilter,
    const std::optional<ProfilePath>& in_profile,
    const std::optional<VdexPath>& in_inputVdex,
    const std::optional<DexMetadataPath>& in_dmFile,
    PriorityClass in_priorityClass,
    const DexoptOptions& in_dexoptOptions,
    const std::shared_ptr<IArtdCancellationSignal>& in_cancellationSignal,
    ArtdDexoptResult* _aidl_return) {
  _aidl_return->cancelled = false;

  RETURN_FATAL_IF_PRE_REBOOT_MISMATCH(options_, in_outputArtifacts, "outputArtifacts");
  RawArtifactsPath artifacts_path =
      OR_RETURN_FATAL(BuildArtifactsPath(in_outputArtifacts.artifactsPath));
  OR_RETURN_FATAL(ValidateDexPath(in_dexFile));
  // `in_profile` can be either a Pre-reboot profile or an ordinary one.
  std::optional<std::string> profile_path =
      in_profile.has_value() ?
          std::make_optional(OR_RETURN_FATAL(BuildProfileOrDmPath(in_profile.value()))) :
          std::nullopt;
  ArtdCancellationSignal* cancellation_signal =
      OR_RETURN_FATAL(ToArtdCancellationSignal(in_cancellationSignal.get()));

  std::unique_ptr<ClassLoaderContext> context = nullptr;
  if (in_classLoaderContext.has_value()) {
    context = ClassLoaderContext::Create(in_classLoaderContext.value());
    if (context == nullptr) {
      return Fatal(
          ART_FORMAT("Class loader context '{}' is invalid", in_classLoaderContext.value()));
    }
  }

  std::string oat_dir_path;  // For restorecon, can be empty if the artifacts are in dalvik-cache.
  OR_RETURN_NON_FATAL(PrepareArtifactsDirs(in_outputArtifacts, &oat_dir_path));

  // First-round restorecon. artd doesn't have the permission to create files with the
  // `apk_data_file` label, so we need to restorecon the "oat" directory first so that files will
  // inherit `dalvikcache_data_file` rather than `apk_data_file`.
  if (!in_outputArtifacts.artifactsPath.isInDalvikCache) {
    OR_RETURN_NON_FATAL(restorecon_(
        oat_dir_path, in_outputArtifacts.permissionSettings.seContext, /*recurse=*/true));
  }

  FdLogger fd_logger;

  CmdlineBuilder art_exec_args = OR_RETURN_FATAL(GetArtExecCmdlineBuilder());

  CmdlineBuilder args;
  args.Add(OR_RETURN_FATAL(GetDex2Oat()));

  const FsPermission& fs_permission = in_outputArtifacts.permissionSettings.fileFsPermission;

  std::unique_ptr<File> dex_file = OR_RETURN_NON_FATAL(OpenFileForReading(in_dexFile));
  args.Add("--zip-fd=%d", dex_file->Fd()).Add("--zip-location=%s", in_dexFile);
  fd_logger.Add(*dex_file);
  struct stat dex_st = OR_RETURN_NON_FATAL(Fstat(*dex_file));
  if ((dex_st.st_mode & S_IROTH) == 0) {
    if (fs_permission.isOtherReadable) {
      return NonFatal(ART_FORMAT(
          "Outputs cannot be other-readable because the dex file '{}' is not other-readable",
          dex_file->GetPath()));
    }
    // Negative numbers mean no `chown`. 0 means root.
    // Note: this check is more strict than it needs to be. For example, it doesn't allow the
    // outputs to belong to a group that is a subset of the dex file's group. This is for
    // simplicity, and it's okay as we don't have to handle such complicated cases in practice.
    if ((fs_permission.uid > 0 && static_cast<uid_t>(fs_permission.uid) != dex_st.st_uid) ||
        (fs_permission.gid > 0 && static_cast<gid_t>(fs_permission.gid) != dex_st.st_uid &&
         static_cast<gid_t>(fs_permission.gid) != dex_st.st_gid)) {
      return NonFatal(ART_FORMAT(
          "Outputs' owner doesn't match the dex file '{}' (outputs: {}:{}, dex file: {}:{})",
          dex_file->GetPath(),
          fs_permission.uid,
          fs_permission.gid,
          dex_st.st_uid,
          dex_st.st_gid));
    }
  }

  std::unique_ptr<NewFile> oat_file =
      OR_RETURN_NON_FATAL(NewFile::Create(artifacts_path.oat_path, fs_permission));
  args.Add("--oat-fd=%d", oat_file->Fd()).Add("--oat-location=%s", artifacts_path.oat_path);
  fd_logger.Add(*oat_file);

  std::unique_ptr<NewFile> vdex_file =
      OR_RETURN_NON_FATAL(NewFile::Create(artifacts_path.vdex_path, fs_permission));
  args.Add("--output-vdex-fd=%d", vdex_file->Fd());
  fd_logger.Add(*vdex_file);

  std::vector<NewFile*> files_to_commit{oat_file.get(), vdex_file.get()};
  std::vector<std::string_view> files_to_delete;

  std::unique_ptr<NewFile> art_file = nullptr;
  if (in_dexoptOptions.generateAppImage) {
    art_file = OR_RETURN_NON_FATAL(NewFile::Create(artifacts_path.art_path, fs_permission));
    args.Add("--app-image-fd=%d", art_file->Fd());
    args.AddIfNonEmpty("--image-format=%s", props_->GetOrEmpty("dalvik.vm.appimageformat"));
    fd_logger.Add(*art_file);
    files_to_commit.push_back(art_file.get());
  } else {
    files_to_delete.push_back(artifacts_path.art_path);
  }

  std::unique_ptr<NewFile> swap_file = nullptr;
  if (ShouldCreateSwapFileForDexopt()) {
    std::string swap_file_path = ART_FORMAT("{}.swap", artifacts_path.oat_path);
    swap_file =
        OR_RETURN_NON_FATAL(NewFile::Create(swap_file_path, FsPermission{.uid = -1, .gid = -1}));
    args.Add("--swap-fd=%d", swap_file->Fd());
    fd_logger.Add(*swap_file);
  }

  std::vector<std::unique_ptr<File>> context_files;
  if (context != nullptr) {
    std::vector<std::string> flattened_context = context->FlattenDexPaths();
    std::string dex_dir = Dirname(in_dexFile);
    std::vector<int> context_fds;
    for (const std::string& context_element : flattened_context) {
      std::string context_path = std::filesystem::path(dex_dir).append(context_element);
      OR_RETURN_FATAL(ValidateDexPath(context_path));
      std::unique_ptr<File> context_file = OR_RETURN_NON_FATAL(OpenFileForReading(context_path));
      context_fds.push_back(context_file->Fd());
      fd_logger.Add(*context_file);
      context_files.push_back(std::move(context_file));
    }
    args.AddIfNonEmpty("--class-loader-context-fds=%s", Join(context_fds, /*separator=*/':'))
        .Add("--class-loader-context=%s", in_classLoaderContext.value())
        .Add("--classpath-dir=%s", dex_dir);
  }

  std::unique_ptr<File> input_vdex_file = nullptr;
  if (in_inputVdex.has_value()) {
    RETURN_FATAL_IF_ARG_IS_PRE_REBOOT(in_inputVdex.value(), "inputVdex");
    std::string input_vdex_path = OR_RETURN_FATAL(BuildVdexPath(in_inputVdex.value()));
    input_vdex_file = OR_RETURN_NON_FATAL(OpenFileForReading(input_vdex_path));
    args.Add("--input-vdex-fd=%d", input_vdex_file->Fd());
    fd_logger.Add(*input_vdex_file);
  }

  std::unique_ptr<File> dm_file = nullptr;
  if (in_dmFile.has_value()) {
    std::string dm_path = OR_RETURN_FATAL(BuildDexMetadataPath(in_dmFile.value()));
    dm_file = OR_RETURN_NON_FATAL(OpenFileForReading(dm_path));
    args.Add("--dm-fd=%d", dm_file->Fd());
    fd_logger.Add(*dm_file);
  }

  std::unique_ptr<File> profile_file = nullptr;
  if (profile_path.has_value()) {
    profile_file = OR_RETURN_NON_FATAL(OpenFileForReading(profile_path.value()));
    args.Add("--profile-file-fd=%d", profile_file->Fd());
    fd_logger.Add(*profile_file);
    struct stat profile_st = OR_RETURN_NON_FATAL(Fstat(*profile_file));
    if (fs_permission.isOtherReadable && (profile_st.st_mode & S_IROTH) == 0) {
      return NonFatal(ART_FORMAT(
          "Outputs cannot be other-readable because the profile '{}' is not other-readable",
          profile_file->GetPath()));
    }
    // TODO(b/260228411): Check uid and gid.
  }

  // Second-round restorecon. Restorecon recursively after the output files are created, so that the
  // SELinux context is applied to all of them. The SELinux context of a file is mostly inherited
  // from the parent directory upon creation, but the MLS label is not inherited, so we need to
  // restorecon every file so that they have the right MLS label. If the files are in dalvik-cache,
  // there's no need to restorecon because they inherits the SELinux context of the dalvik-cache
  // directory and they don't need to have MLS labels.
  if (!in_outputArtifacts.artifactsPath.isInDalvikCache) {
    OR_RETURN_NON_FATAL(restorecon_(
        oat_dir_path, in_outputArtifacts.permissionSettings.seContext, /*recurse=*/true));
  }

  AddBootImageFlags(args);
  AddCompilerConfigFlags(
      in_instructionSet, in_compilerFilter, in_priorityClass, in_dexoptOptions, args);
  AddPerfConfigFlags(in_priorityClass, art_exec_args, args);

  // For being surfaced in crash reports on crashes.
  args.Add("--comments=%s", in_dexoptOptions.comments);

  art_exec_args.Add("--keep-fds=%s", fd_logger.GetFds()).Add("--").Concat(std::move(args));

  LOG(INFO) << "Running dex2oat: " << Join(art_exec_args.Get(), /*separator=*/" ")
            << "\nOpened FDs: " << fd_logger;

  ProcessStat stat;
  std::string error_msg;
  ExecResult result = exec_utils_->ExecAndReturnResult(art_exec_args.Get(),
                                                       kLongTimeoutSec,
                                                       cancellation_signal->CreateExecCallbacks(),
                                                       /*new_process_group=*/true,
                                                       &stat,
                                                       &error_msg);
  _aidl_return->wallTimeMs = stat.wall_time_ms;
  _aidl_return->cpuTimeMs = stat.cpu_time_ms;

  auto result_info = ART_FORMAT("[status={},exit_code={},signal={}]",
                                static_cast<int>(result.status),
                                result.exit_code,
                                result.signal);
  if (result.status != ExecResult::kExited) {
    if (cancellation_signal->IsCancelled()) {
      _aidl_return->cancelled = true;
      return ScopedAStatus::ok();
    }
    return NonFatal(ART_FORMAT("Failed to run dex2oat: {} {}", error_msg, result_info));
  }

  LOG(INFO) << ART_FORMAT("dex2oat returned code {}", result.exit_code);

  if (result.exit_code != 0) {
    return NonFatal(
        ART_FORMAT("dex2oat returned an unexpected code: {} {}", result.exit_code, result_info));
  }

  int64_t size_bytes = 0;
  int64_t size_before_bytes = 0;
  for (const NewFile* file : files_to_commit) {
    size_bytes += GetSize(file->TempPath()).value_or(0);
    size_before_bytes += GetSize(file->FinalPath()).value_or(0);
  }
  for (std::string_view path : files_to_delete) {
    size_before_bytes += GetSize(path).value_or(0);
  }
  OR_RETURN_NON_FATAL(NewFile::CommitAllOrAbandon(files_to_commit, files_to_delete));

  _aidl_return->sizeBytes = size_bytes;
  _aidl_return->sizeBeforeBytes = size_before_bytes;
  return ScopedAStatus::ok();
}

ScopedAStatus ArtdCancellationSignal::cancel() {
  std::lock_guard<std::mutex> lock(mu_);
  is_cancelled_ = true;
  for (pid_t pid : pids_) {
    // Kill the whole process group.
    int res = kill_(-pid, SIGKILL);
    DCHECK_EQ(res, 0);
  }
  return ScopedAStatus::ok();
}

ScopedAStatus ArtdCancellationSignal::getType(int64_t* _aidl_return) {
  *_aidl_return = reinterpret_cast<intptr_t>(kArtdCancellationSignalType);
  return ScopedAStatus::ok();
}

ExecCallbacks ArtdCancellationSignal::CreateExecCallbacks() {
  return {
      .on_start =
          [&](pid_t pid) {
            std::lock_guard<std::mutex> lock(mu_);
            pids_.insert(pid);
            // Handle cancellation signals sent before the process starts.
            if (is_cancelled_) {
              int res = kill_(-pid, SIGKILL);
              DCHECK_EQ(res, 0);
            }
          },
      .on_end =
          [&](pid_t pid) {
            std::lock_guard<std::mutex> lock(mu_);
            // The pid should no longer receive kill signals sent by `cancellation_signal`.
            pids_.erase(pid);
          },
  };
}

bool ArtdCancellationSignal::IsCancelled() {
  std::lock_guard<std::mutex> lock(mu_);
  return is_cancelled_;
}

ScopedAStatus Artd::createCancellationSignal(
    std::shared_ptr<IArtdCancellationSignal>* _aidl_return) {
  *_aidl_return = ndk::SharedRefBase::make<ArtdCancellationSignal>(kill_);
  return ScopedAStatus::ok();
}

ScopedAStatus Artd::cleanup(const std::vector<ProfilePath>& in_profilesToKeep,
                            const std::vector<ArtifactsPath>& in_artifactsToKeep,
                            const std::vector<VdexPath>& in_vdexFilesToKeep,
                            const std::vector<RuntimeArtifactsPath>& in_runtimeArtifactsToKeep,
                            bool in_keepPreRebootStagedFiles,
                            int64_t* _aidl_return) {
  RETURN_FATAL_IF_PRE_REBOOT(options_);
  std::unordered_set<std::string> files_to_keep;
  for (const ProfilePath& profile : in_profilesToKeep) {
    RETURN_FATAL_IF_ARG_IS_PRE_REBOOT(profile, "profilesToKeep");
    files_to_keep.insert(OR_RETURN_FATAL(BuildProfileOrDmPath(profile)));
  }
  for (const ArtifactsPath& artifacts : in_artifactsToKeep) {
    RETURN_FATAL_IF_ARG_IS_PRE_REBOOT(artifacts, "artifactsToKeep");
    RawArtifactsPath path = OR_RETURN_FATAL(BuildArtifactsPath(artifacts));
    files_to_keep.insert(std::move(path.oat_path));
    files_to_keep.insert(std::move(path.vdex_path));
    files_to_keep.insert(std::move(path.art_path));
  }
  for (const VdexPath& vdex : in_vdexFilesToKeep) {
    RETURN_FATAL_IF_ARG_IS_PRE_REBOOT(vdex, "vdexFilesToKeep");
    files_to_keep.insert(OR_RETURN_FATAL(BuildVdexPath(vdex)));
  }
  std::string android_data = OR_RETURN_NON_FATAL(GetAndroidDataOrError());
  std::string android_expand = OR_RETURN_NON_FATAL(GetAndroidExpandOrError());
  for (const RuntimeArtifactsPath& runtime_image_path : in_runtimeArtifactsToKeep) {
    OR_RETURN_FATAL(ValidateRuntimeArtifactsPath(runtime_image_path));
    std::vector<std::string> files =
        ListRuntimeArtifactsFiles(android_data, android_expand, runtime_image_path);
    std::move(files.begin(), files.end(), std::inserter(files_to_keep, files_to_keep.end()));
  }
  *_aidl_return = 0;
  for (const std::string& file : ListManagedFiles(android_data, android_expand)) {
    if (files_to_keep.find(file) == files_to_keep.end() &&
        (!in_keepPreRebootStagedFiles || !IsPreRebootStagedFile(file))) {
      LOG(INFO) << ART_FORMAT("Cleaning up obsolete file '{}'", file);
      *_aidl_return += GetSizeAndDeleteFile(file);
    }
  }
  return ScopedAStatus::ok();
}

ScopedAStatus Artd::cleanUpPreRebootStagedFiles() {
  RETURN_FATAL_IF_PRE_REBOOT(options_);
  std::string android_data = OR_RETURN_NON_FATAL(GetAndroidDataOrError());
  std::string android_expand = OR_RETURN_NON_FATAL(GetAndroidExpandOrError());
  for (const std::string& file : ListManagedFiles(android_data, android_expand)) {
    if (IsPreRebootStagedFile(file)) {
      LOG(INFO) << ART_FORMAT("Cleaning up obsolete Pre-reboot staged file '{}'", file);
      DeleteFile(file);
    }
  }
  return ScopedAStatus::ok();
}

ScopedAStatus Artd::isInDalvikCache(const std::string& in_dexFile, bool* _aidl_return) {
  // The artifacts should be in the global dalvik-cache directory if:
  // (1). the dex file is on a system partition, even if the partition is remounted read-write,
  //      or
  // (2). the dex file is in any other readonly location. (At the time of writing, this only
  //      include Incremental FS.)
  //
  // We cannot rely on access(2) because:
  // - It doesn't take effective capabilities into account, from which artd gets root access
  //   to the filesystem.
  // - The `faccessat` variant with the `AT_EACCESS` flag, which takes effective capabilities
  //   into account, is not supported by bionic.

  OR_RETURN_FATAL(ValidateDexPath(in_dexFile));

  std::vector<FstabEntry> entries = OR_RETURN_NON_FATAL(GetProcMountsAncestorsOfPath(in_dexFile));
  // The last one controls because `/proc/mounts` reflects the sequence of `mount`.
  for (auto it = entries.rbegin(); it != entries.rend(); it++) {
    if (it->fs_type == "overlay") {
      // Ignore the overlays created by `remount`.
      continue;
    }
    // We need to special-case Incremental FS since it is tagged as read-write while it's actually
    // not.
    *_aidl_return = (it->flags & MS_RDONLY) != 0 || it->fs_type == "incremental-fs";
    return ScopedAStatus::ok();
  }

  return NonFatal(ART_FORMAT("Fstab entries not found for '{}'", in_dexFile));
}

ScopedAStatus Artd::deleteRuntimeArtifacts(const RuntimeArtifactsPath& in_runtimeArtifactsPath,
                                           int64_t* _aidl_return) {
  RETURN_FATAL_IF_PRE_REBOOT(options_);
  OR_RETURN_FATAL(ValidateRuntimeArtifactsPath(in_runtimeArtifactsPath));
  *_aidl_return = 0;
  std::string android_data = OR_LOG_AND_RETURN_OK(GetAndroidDataOrError());
  std::string android_expand = OR_LOG_AND_RETURN_OK(GetAndroidExpandOrError());
  for (const std::string& file :
       ListRuntimeArtifactsFiles(android_data, android_expand, in_runtimeArtifactsPath)) {
    *_aidl_return += GetSizeAndDeleteFile(file);
  }
  return ScopedAStatus::ok();
}

ScopedAStatus Artd::getArtifactsSize(const ArtifactsPath& in_artifactsPath, int64_t* _aidl_return) {
  RETURN_FATAL_IF_PRE_REBOOT(options_);
  RETURN_FATAL_IF_ARG_IS_PRE_REBOOT(in_artifactsPath, "artifactsPath");
  RawArtifactsPath path = OR_RETURN_FATAL(BuildArtifactsPath(in_artifactsPath));
  *_aidl_return = 0;
  *_aidl_return += GetSize(path.oat_path).value_or(0);
  *_aidl_return += GetSize(path.vdex_path).value_or(0);
  *_aidl_return += GetSize(path.art_path).value_or(0);
  return ScopedAStatus::ok();
}

ScopedAStatus Artd::getVdexFileSize(const VdexPath& in_vdexPath, int64_t* _aidl_return) {
  RETURN_FATAL_IF_PRE_REBOOT(options_);
  RETURN_FATAL_IF_ARG_IS_PRE_REBOOT(in_vdexPath, "vdexPath");
  std::string vdex_path = OR_RETURN_FATAL(BuildVdexPath(in_vdexPath));
  *_aidl_return = GetSize(vdex_path).value_or(0);
  return ScopedAStatus::ok();
}

ScopedAStatus Artd::getRuntimeArtifactsSize(const RuntimeArtifactsPath& in_runtimeArtifactsPath,
                                            int64_t* _aidl_return) {
  RETURN_FATAL_IF_PRE_REBOOT(options_);
  OR_RETURN_FATAL(ValidateRuntimeArtifactsPath(in_runtimeArtifactsPath));
  *_aidl_return = 0;
  std::string android_data = OR_LOG_AND_RETURN_OK(GetAndroidDataOrError());
  std::string android_expand = OR_LOG_AND_RETURN_OK(GetAndroidExpandOrError());
  for (const std::string& file :
       ListRuntimeArtifactsFiles(android_data, android_expand, in_runtimeArtifactsPath)) {
    *_aidl_return += GetSize(file).value_or(0);
  }
  return ScopedAStatus::ok();
}

ScopedAStatus Artd::getProfileSize(const ProfilePath& in_profile, int64_t* _aidl_return) {
  RETURN_FATAL_IF_PRE_REBOOT(options_);
  RETURN_FATAL_IF_ARG_IS_PRE_REBOOT(in_profile, "profile");
  std::string profile_path = OR_RETURN_FATAL(BuildProfileOrDmPath(in_profile));
  *_aidl_return = GetSize(profile_path).value_or(0);
  return ScopedAStatus::ok();
}

ScopedAStatus Artd::initProfileSaveNotification(const PrimaryCurProfilePath& in_profilePath,
                                                int in_pid,
                                                std::shared_ptr<IArtdNotification>* _aidl_return) {
  RETURN_FATAL_IF_PRE_REBOOT(options_);

  std::string path = OR_RETURN_FATAL(BuildPrimaryCurProfilePath(in_profilePath));

  unique_fd inotify_fd(inotify_init1(IN_NONBLOCK | IN_CLOEXEC));
  if (inotify_fd < 0) {
    return NonFatal(ART_FORMAT("Failed to inotify_init1: {}", strerror(errno)));
  }

  // Watch the dir rather than the file itself because profiles are moved in rather than updated in
  // place.
  std::string dir = Dirname(path);
  int wd = inotify_add_watch(inotify_fd, dir.c_str(), IN_MOVED_TO);
  if (wd < 0) {
    return NonFatal(ART_FORMAT("Failed to inotify_add_watch '{}': {}", dir, strerror(errno)));
  }

  unique_fd pidfd = PidfdOpen(in_pid, /*flags=*/0);
  if (pidfd < 0) {
    if (errno == ESRCH) {
      // The process has gone now.
      LOG(INFO) << ART_FORMAT("Process exited without sending notification '{}'", path);
      *_aidl_return = ndk::SharedRefBase::make<ArtdNotification>();
      return ScopedAStatus::ok();
    }
    return NonFatal(ART_FORMAT("Failed to pidfd_open {}: {}", in_pid, strerror(errno)));
  }

  *_aidl_return = ndk::SharedRefBase::make<ArtdNotification>(
      poll_, path, std::move(inotify_fd), std::move(pidfd));
  return ScopedAStatus::ok();
}

ScopedAStatus ArtdNotification::wait(int in_timeoutMs, bool* _aidl_return) {
  auto cleanup = make_scope_guard([&, this] { CleanUp(); });

  if (!mu_.try_lock()) {
    return Fatal("`wait` can be called only once");
  }
  std::lock_guard<std::mutex> lock(mu_, std::adopt_lock);
  LOG(INFO) << ART_FORMAT("Waiting for notification '{}'", path_);

  if (is_called_) {
    return Fatal("`wait` can be called only once");
  }
  is_called_ = true;

  if (done_) {
    *_aidl_return = true;
    return ScopedAStatus::ok();
  }

  struct pollfd pollfds[2]{
      {.fd = inotify_fd_.get(), .events = POLLIN},
      {.fd = pidfd_.get(), .events = POLLIN},
  };

  constexpr size_t kBufSize = sizeof(struct inotify_event) + NAME_MAX + 1;
  std::unique_ptr<uint8_t[]> buf(new (std::align_val_t(alignof(struct inotify_event)))
                                     uint8_t[kBufSize]);
  std::string basename = Basename(path_);

  uint64_t start_time = MilliTime();
  int64_t remaining_time_ms = in_timeoutMs;
  while (remaining_time_ms > 0) {
    int ret = TEMP_FAILURE_RETRY(poll_(pollfds, arraysize(pollfds), remaining_time_ms));
    if (ret < 0) {
      return NonFatal(
          ART_FORMAT("Failed to poll to wait for notification '{}': {}", path_, strerror(errno)));
    }
    if (ret == 0) {
      // Timeout.
      break;
    }
    if ((pollfds[0].revents & POLLIN) != 0) {
      ssize_t len = TEMP_FAILURE_RETRY(read(inotify_fd_, buf.get(), kBufSize));
      if (len < 0) {
        return NonFatal(ART_FORMAT(
            "Failed to read inotify fd for notification '{}': {}", path_, strerror(errno)));
      }
      const struct inotify_event* event;
      for (uint8_t* ptr = buf.get(); ptr < buf.get() + len;
           ptr += sizeof(struct inotify_event) + event->len) {
        event = (const struct inotify_event*)ptr;
        if (event->len > 0 && event->name == basename) {
          LOG(INFO) << ART_FORMAT("Received notification '{}'", path_);
          *_aidl_return = true;
          return ScopedAStatus::ok();
        }
      }
      remaining_time_ms = in_timeoutMs - (MilliTime() - start_time);
      continue;
    }
    if ((pollfds[1].revents & POLLIN) != 0) {
      LOG(INFO) << ART_FORMAT("Process exited without sending notification '{}'", path_);
      *_aidl_return = true;
      return ScopedAStatus::ok();
    }
    LOG(FATAL) << "Unreachable code";
    UNREACHABLE();
  }

  LOG(INFO) << ART_FORMAT("Timed out while waiting for notification '{}'", path_);
  *_aidl_return = false;
  return ScopedAStatus::ok();
}

ArtdNotification::~ArtdNotification() { CleanUp(); }

void ArtdNotification::CleanUp() {
  std::lock_guard<std::mutex> lock(mu_);
  inotify_fd_.reset();
  pidfd_.reset();
}

ScopedAStatus Artd::commitPreRebootStagedFiles(const std::vector<ArtifactsPath>& in_artifacts,
                                               const std::vector<WritableProfilePath>& in_profiles,
                                               bool* _aidl_return) {
  RETURN_FATAL_IF_PRE_REBOOT(options_);

  std::vector<std::pair<std::string, std::string>> files_to_move;
  std::vector<std::string> files_to_remove;

  for (const ArtifactsPath& artifacts : in_artifacts) {
    RETURN_FATAL_IF_ARG_IS_PRE_REBOOT(artifacts, "artifacts");

    ArtifactsPath pre_reboot_artifacts = artifacts;
    pre_reboot_artifacts.isPreReboot = true;

    auto src_artifacts = std::make_unique<RawArtifactsPath>(
        OR_RETURN_FATAL(BuildArtifactsPath(pre_reboot_artifacts)));
    auto dst_artifacts =
        std::make_unique<RawArtifactsPath>(OR_RETURN_FATAL(BuildArtifactsPath(artifacts)));

    if (OS::FileExists(src_artifacts->oat_path.c_str())) {
      files_to_move.emplace_back(src_artifacts->oat_path, dst_artifacts->oat_path);
      files_to_move.emplace_back(src_artifacts->vdex_path, dst_artifacts->vdex_path);
      if (OS::FileExists(src_artifacts->art_path.c_str())) {
        files_to_move.emplace_back(src_artifacts->art_path, dst_artifacts->art_path);
      } else {
        files_to_remove.push_back(dst_artifacts->art_path);
      }
    }
  }

  for (const WritableProfilePath& profile : in_profiles) {
    RETURN_FATAL_IF_ARG_IS_PRE_REBOOT(profile, "profiles");

    WritableProfilePath pre_reboot_profile = profile;
    PreRebootFlag(pre_reboot_profile) = true;

    auto src_profile = std::make_unique<std::string>(
        OR_RETURN_FATAL(BuildWritableProfilePath(pre_reboot_profile)));
    auto dst_profile =
        std::make_unique<std::string>(OR_RETURN_FATAL(BuildWritableProfilePath(profile)));

    if (OS::FileExists(src_profile->c_str())) {
      files_to_move.emplace_back(*src_profile, *dst_profile);
    }
  }

  OR_RETURN_NON_FATAL(MoveAllOrAbandon(files_to_move, files_to_remove));

  for (const auto& [src_path, dst_path] : files_to_move) {
    LOG(INFO) << ART_FORMAT("Committed Pre-reboot staged file '{}' to '{}'", src_path, dst_path);
  }

  *_aidl_return = !files_to_move.empty();
  return ScopedAStatus::ok();
}

ScopedAStatus Artd::checkPreRebootSystemRequirements(const std::string& in_chrootDir,
                                                     bool* _aidl_return) {
  RETURN_FATAL_IF_PRE_REBOOT(options_);
  BuildSystemProperties new_props =
      OR_RETURN_NON_FATAL(BuildSystemProperties::Create(in_chrootDir + "/system/build.prop"));
  std::string old_release_str = props_->GetOrEmpty("ro.build.version.release");
  int old_release;
  if (!ParseInt(old_release_str, &old_release)) {
    return NonFatal(
        ART_FORMAT("Failed to read or parse old release number, got '{}'", old_release_str));
  }
  std::string new_release_str = new_props.GetOrEmpty("ro.build.version.release");
  int new_release;
  if (!ParseInt(new_release_str, &new_release)) {
    return NonFatal(
        ART_FORMAT("Failed to read or parse new release number, got '{}'", new_release_str));
  }
  if (new_release - old_release >= 2) {
    // When the release version difference is large, there is no particular technical reason why we
    // can't run Pre-reboot Dexopt, but we cannot test and support those cases.
    LOG(WARNING) << ART_FORMAT(
        "Pre-reboot Dexopt not supported due to large difference in release versions (old_release: "
        "{}, new_release: {})",
        old_release,
        new_release);
    *_aidl_return = false;
    return ScopedAStatus::ok();
  }

  *_aidl_return = true;
  return ScopedAStatus::ok();
}

Result<void> Artd::Start() {
  OR_RETURN(SetLogVerbosity());
  MemMap::Init();
  Runtime::AllowPageSizeAccess();

  ScopedAStatus status = ScopedAStatus::fromStatus(AServiceManager_registerLazyService(
      this->asBinder().get(), options_.is_pre_reboot ? kPreRebootServiceName : kServiceName));
  if (!status.isOk()) {
    return Error() << status.getDescription();
  }

  ABinderProcess_startThreadPool();

  return {};
}

Result<OatFileAssistantContext*> Artd::GetOatFileAssistantContext() {
  std::lock_guard<std::mutex> lock(ofa_context_mu_);

  if (ofa_context_ == nullptr) {
    ofa_context_ = std::make_unique<OatFileAssistantContext>(
        std::make_unique<OatFileAssistantContext::RuntimeOptions>(
            OatFileAssistantContext::RuntimeOptions{
                .image_locations = *OR_RETURN(GetBootImageLocations()),
                .boot_class_path = *OR_RETURN(GetBootClassPath()),
                .boot_class_path_locations = *OR_RETURN(GetBootClassPath()),
                .deny_art_apex_data_files = DenyArtApexDataFiles(),
            }));
    std::string error_msg;
    if (!ofa_context_->FetchAll(&error_msg)) {
      return Error() << error_msg;
    }
  }

  return ofa_context_.get();
}

Result<const std::vector<std::string>*> Artd::GetBootImageLocations() {
  std::lock_guard<std::mutex> lock(cache_mu_);

  if (!cached_boot_image_locations_.has_value()) {
    std::string location_str;

    if (UseJitZygoteLocked()) {
      location_str = GetJitZygoteBootImageLocation();
    } else if (std::string value = GetUserDefinedBootImageLocationsLocked(); !value.empty()) {
      location_str = std::move(value);
    } else {
      std::string error_msg;
      std::string android_root = GetAndroidRootSafe(&error_msg);
      if (!error_msg.empty()) {
        return Errorf("Failed to get ANDROID_ROOT: {}", error_msg);
      }
      location_str = GetDefaultBootImageLocation(android_root, DenyArtApexDataFilesLocked());
    }

    cached_boot_image_locations_ = Split(location_str, ":");
  }

  return &cached_boot_image_locations_.value();
}

Result<const std::vector<std::string>*> Artd::GetBootClassPath() {
  std::lock_guard<std::mutex> lock(cache_mu_);

  if (!cached_boot_class_path_.has_value()) {
    const char* env_value = getenv("BOOTCLASSPATH");
    if (env_value == nullptr || strlen(env_value) == 0) {
      return Errorf("Failed to get environment variable 'BOOTCLASSPATH'");
    }
    cached_boot_class_path_ = Split(env_value, ":");
  }

  return &cached_boot_class_path_.value();
}

bool Artd::UseJitZygote() {
  std::lock_guard<std::mutex> lock(cache_mu_);
  return UseJitZygoteLocked();
}

bool Artd::UseJitZygoteLocked() {
  if (!cached_use_jit_zygote_.has_value()) {
    cached_use_jit_zygote_ =
        props_->GetBool("persist.device_config.runtime_native_boot.profilebootclasspath",
                        "dalvik.vm.profilebootclasspath",
                        /*default_value=*/false);
  }

  return cached_use_jit_zygote_.value();
}

const std::string& Artd::GetUserDefinedBootImageLocations() {
  std::lock_guard<std::mutex> lock(cache_mu_);
  return GetUserDefinedBootImageLocationsLocked();
}

const std::string& Artd::GetUserDefinedBootImageLocationsLocked() {
  if (!cached_user_defined_boot_image_locations_.has_value()) {
    cached_user_defined_boot_image_locations_ = props_->GetOrEmpty("dalvik.vm.boot-image");
  }

  return cached_user_defined_boot_image_locations_.value();
}

bool Artd::DenyArtApexDataFiles() {
  std::lock_guard<std::mutex> lock(cache_mu_);
  return DenyArtApexDataFilesLocked();
}

bool Artd::DenyArtApexDataFilesLocked() {
  if (!cached_deny_art_apex_data_files_.has_value()) {
    cached_deny_art_apex_data_files_ =
        !props_->GetBool("odsign.verification.success", /*default_value=*/false);
  }

  return cached_deny_art_apex_data_files_.value();
}

Result<std::string> Artd::GetProfman() { return BuildArtBinPath("profman"); }

Result<CmdlineBuilder> Artd::GetArtExecCmdlineBuilder() {
  std::string art_exec_path = OR_RETURN(BuildArtBinPath("art_exec"));
  if (options_.is_pre_reboot) {
    // "/mnt/compat_env" is prepared by dexopt_chroot_setup on Android V.
    std::string compat_art_exec_path = "/mnt/compat_env" + art_exec_path;
    if (OS::FileExists(compat_art_exec_path.c_str())) {
      art_exec_path = std::move(compat_art_exec_path);
    }
  }

  CmdlineBuilder args;
  args.Add(art_exec_path)
      .Add("--drop-capabilities")
      .AddIf(options_.is_pre_reboot, "--process-name-suffix=Pre-reboot Dexopt chroot");
  return args;
}

bool Artd::ShouldUseDex2Oat64() {
  return !props_->GetOrEmpty("ro.product.cpu.abilist64").empty() &&
         props_->GetBool("dalvik.vm.dex2oat64.enabled", /*default_value=*/false);
}

bool Artd::ShouldUseDebugBinaries() {
  return props_->GetOrEmpty("persist.sys.dalvik.vm.lib.2") == "libartd.so";
}

Result<std::string> Artd::GetDex2Oat() {
  std::string binary_name = ShouldUseDebugBinaries() ?
                                (ShouldUseDex2Oat64() ? "dex2oatd64" : "dex2oatd32") :
                                (ShouldUseDex2Oat64() ? "dex2oat64" : "dex2oat32");
  return BuildArtBinPath(binary_name);
}

bool Artd::ShouldCreateSwapFileForDexopt() {
  // Create a swap file by default. Dex2oat will decide whether to use it or not.
  return props_->GetBool("dalvik.vm.dex2oat-swap", /*default_value=*/true);
}

void Artd::AddBootImageFlags(/*out*/ CmdlineBuilder& args) {
  if (UseJitZygote()) {
    args.Add("--force-jit-zygote");
  } else {
    args.AddIfNonEmpty("--boot-image=%s", GetUserDefinedBootImageLocations());
  }
}

void Artd::AddCompilerConfigFlags(const std::string& instruction_set,
                                  const std::string& compiler_filter,
                                  PriorityClass priority_class,
                                  const DexoptOptions& dexopt_options,
                                  /*out*/ CmdlineBuilder& args) {
  args.Add("--instruction-set=%s", instruction_set);
  std::string features_prop = ART_FORMAT("dalvik.vm.isa.{}.features", instruction_set);
  args.AddIfNonEmpty("--instruction-set-features=%s", props_->GetOrEmpty(features_prop));
  std::string variant_prop = ART_FORMAT("dalvik.vm.isa.{}.variant", instruction_set);
  args.AddIfNonEmpty("--instruction-set-variant=%s", props_->GetOrEmpty(variant_prop));

  args.Add("--compiler-filter=%s", compiler_filter)
      .Add("--compilation-reason=%s", dexopt_options.compilationReason);

  args.AddIf(priority_class >= PriorityClass::INTERACTIVE, "--compact-dex-level=none");

  args.AddIfNonEmpty("--max-image-block-size=%s",
                     props_->GetOrEmpty("dalvik.vm.dex2oat-max-image-block-size"))
      .AddIfNonEmpty("--very-large-app-threshold=%s",
                     props_->GetOrEmpty("dalvik.vm.dex2oat-very-large"))
      .AddIfNonEmpty("--resolve-startup-const-strings=%s",
                     props_->GetOrEmpty("dalvik.vm.dex2oat-resolve-startup-strings"));

  args.AddIf(dexopt_options.debuggable, "--debuggable")
      .AddIf(props_->GetBool("debug.generate-debug-info", /*default_value=*/false),
             "--generate-debug-info")
      .AddIf(props_->GetBool("dalvik.vm.dex2oat-minidebuginfo", /*default_value=*/false),
             "--generate-mini-debug-info");

  args.AddRuntimeIf(DenyArtApexDataFiles(), "-Xdeny-art-apex-data-files")
      .AddRuntime("-Xtarget-sdk-version:%d", dexopt_options.targetSdkVersion)
      .AddRuntimeIf(dexopt_options.hiddenApiPolicyEnabled, "-Xhidden-api-policy:enabled");
}

void Artd::AddPerfConfigFlags(PriorityClass priority_class,
                              /*out*/ CmdlineBuilder& art_exec_args,
                              /*out*/ CmdlineBuilder& dex2oat_args) {
  // CPU set and number of threads.
  std::string default_cpu_set_prop = "dalvik.vm.dex2oat-cpu-set";
  std::string default_threads_prop = "dalvik.vm.dex2oat-threads";
  std::string cpu_set;
  std::string threads;
  if (priority_class >= PriorityClass::BOOT) {
    cpu_set = props_->GetOrEmpty("dalvik.vm.boot-dex2oat-cpu-set");
    threads = props_->GetOrEmpty("dalvik.vm.boot-dex2oat-threads");
  } else if (priority_class >= PriorityClass::INTERACTIVE_FAST) {
    cpu_set = props_->GetOrEmpty("dalvik.vm.restore-dex2oat-cpu-set", default_cpu_set_prop);
    threads = props_->GetOrEmpty("dalvik.vm.restore-dex2oat-threads", default_threads_prop);
  } else if (priority_class <= PriorityClass::BACKGROUND) {
    cpu_set = props_->GetOrEmpty("dalvik.vm.background-dex2oat-cpu-set", default_cpu_set_prop);
    threads = props_->GetOrEmpty("dalvik.vm.background-dex2oat-threads", default_threads_prop);
  } else {
    cpu_set = props_->GetOrEmpty(default_cpu_set_prop);
    threads = props_->GetOrEmpty(default_threads_prop);
  }
  dex2oat_args.AddIfNonEmpty("--cpu-set=%s", cpu_set).AddIfNonEmpty("-j%s", threads);

  if (priority_class < PriorityClass::BOOT) {
    art_exec_args
        .Add(priority_class <= PriorityClass::BACKGROUND ? "--set-task-profile=Dex2OatBackground" :
                                                           "--set-task-profile=Dex2OatBootComplete")
        .Add("--set-priority=background");
  }

  dex2oat_args.AddRuntimeIfNonEmpty("-Xms%s", props_->GetOrEmpty("dalvik.vm.dex2oat-Xms"))
      .AddRuntimeIfNonEmpty("-Xmx%s", props_->GetOrEmpty("dalvik.vm.dex2oat-Xmx"));

  // Enable compiling dex files in isolation on low ram devices.
  // It takes longer but reduces the memory footprint.
  dex2oat_args.AddIf(props_->GetBool("ro.config.low_ram", /*default_value=*/false),
                     "--compile-individually");

  for (const std::string& flag :
       Tokenize(props_->GetOrEmpty("dalvik.vm.dex2oat-flags"), /*delimiters=*/" ")) {
    dex2oat_args.AddIfNonEmpty("%s", flag);
  }
}

Result<int> Artd::ExecAndReturnCode(const std::vector<std::string>& args,
                                    int timeout_sec,
                                    const ExecCallbacks& callbacks,
                                    ProcessStat* stat) const {
  std::string error_msg;
  // Create a new process group so that we can kill the process subtree at once by killing the
  // process group.
  ExecResult result = exec_utils_->ExecAndReturnResult(
      args, timeout_sec, callbacks, /*new_process_group=*/true, stat, &error_msg);
  if (result.status != ExecResult::kExited) {
    return Error() << error_msg;
  }
  return result.exit_code;
}

Result<struct stat> Artd::Fstat(const File& file) const {
  struct stat st;
  if (fstat_(file.Fd(), &st) != 0) {
    return Errorf("Unable to fstat file '{}'", file.GetPath());
  }
  return st;
}

Result<void> Artd::BindMountNewDir(const std::string& source, const std::string& target) const {
  OR_RETURN(CreateDir(source));
  OR_RETURN(BindMount(source, target));
  OR_RETURN(restorecon_(target, /*se_context=*/std::nullopt, /*recurse=*/false));
  return {};
}

Result<void> Artd::BindMount(const std::string& source, const std::string& target) const {
  if (mount_(source.c_str(),
             target.c_str(),
             /*fs_type=*/nullptr,
             MS_BIND | MS_PRIVATE,
             /*data=*/nullptr) != 0) {
    return ErrnoErrorf("Failed to bind-mount '{}' at '{}'", source, target);
  }
  return {};
}

ScopedAStatus Artd::preRebootInit(
    const std::shared_ptr<IArtdCancellationSignal>& in_cancellationSignal, bool* _aidl_return) {
  RETURN_FATAL_IF_NOT_PRE_REBOOT(options_);

  std::string tmp_dir = pre_reboot_tmp_dir_.value_or(kDefaultPreRebootTmpDir);
  std::string preparation_done_file = tmp_dir + "/preparation_done";
  std::string classpath_file = tmp_dir + "/classpath.txt";
  std::string art_apex_data_dir = tmp_dir + "/art_apex_data";
  std::string odrefresh_dir = tmp_dir + "/odrefresh";

  bool preparation_done = OS::FileExists(preparation_done_file.c_str());

  if (!preparation_done) {
    std::error_code ec;
    bool is_empty = std::filesystem::is_empty(tmp_dir, ec);
    if (ec) {
      return NonFatal(ART_FORMAT("Failed to check dir '{}': {}", tmp_dir, ec.message()));
    }
    if (!is_empty) {
      return Fatal(
          "preRebootInit must not be concurrently called or retried after cancellation or failure");
    }
  }

  OR_RETURN_NON_FATAL(PreRebootInitClearEnvs());
  OR_RETURN_NON_FATAL(
      PreRebootInitSetEnvFromFile(init_environ_rc_path_.value_or("/init.environ.rc")));
  if (!preparation_done) {
    OR_RETURN_NON_FATAL(PreRebootInitDeriveClasspath(classpath_file));
  }
  OR_RETURN_NON_FATAL(PreRebootInitSetEnvFromFile(classpath_file));
  if (!preparation_done) {
    OR_RETURN_NON_FATAL(BindMountNewDir(art_apex_data_dir, GetArtApexData()));
    OR_RETURN_NON_FATAL(BindMountNewDir(odrefresh_dir, "/data/misc/odrefresh"));
    ArtdCancellationSignal* cancellation_signal =
        OR_RETURN_FATAL(ToArtdCancellationSignal(in_cancellationSignal.get()));
    if (!OR_RETURN_NON_FATAL(PreRebootInitBootImages(cancellation_signal))) {
      *_aidl_return = false;
      return ScopedAStatus::ok();
    }
  }

  if (!preparation_done) {
    if (!WriteStringToFile(/*content=*/"", preparation_done_file)) {
      return NonFatal(
          ART_FORMAT("Failed to write '{}': {}", preparation_done_file, strerror(errno)));
    }
  }

  *_aidl_return = true;
  return ScopedAStatus::ok();
}

Result<void> Artd::PreRebootInitClearEnvs() {
  if (clearenv() != 0) {
    return ErrnoErrorf("Failed to clear environment variables");
  }
  return {};
}

Result<void> Artd::PreRebootInitSetEnvFromFile(const std::string& path) {
  std::regex export_line_pattern("\\s*export\\s+(.+?)\\s+(.+)");

  std::string content;
  if (!ReadFileToString(path, &content)) {
    return ErrnoErrorf("Failed to read '{}'", path);
  }
  bool found = false;
  for (const std::string& line : Split(content, "\n")) {
    if (line.find_first_of("\\\"") != std::string::npos) {
      return Errorf("Backslashes and quotes in env var file are not supported for now, got '{}'",
                    line);
    }
    std::smatch match;
    if (!std::regex_match(line, match, export_line_pattern)) {
      continue;
    }
    const std::string& key = match[1].str();
    const std::string& value = match[2].str();
    LOG(INFO) << ART_FORMAT("Setting environment variable '{}' to '{}'", key, value);
    if (setenv(key.c_str(), value.c_str(), /*replace=*/1) != 0) {
      return ErrnoErrorf("Failed to set environment variable '{}' to '{}'", key, value);
    }
    found = true;
  }
  if (!found) {
    return Errorf("Malformed env var file '{}': {}", path, content);
  }
  return {};
}

Result<void> Artd::PreRebootInitDeriveClasspath(const std::string& path) {
  std::unique_ptr<File> output(OS::CreateEmptyFile(path.c_str()));
  if (output == nullptr) {
    return ErrnoErrorf("Failed to create '{}'", path);
  }

  if (pre_reboot_build_props_ == nullptr) {
    pre_reboot_build_props_ = std::make_unique<BuildSystemProperties>(
        OR_RETURN(BuildSystemProperties::Create("/system/build.prop")));
  }
  std::string sdk_version = pre_reboot_build_props_->GetOrEmpty("ro.build.version.sdk");
  std::string codename = pre_reboot_build_props_->GetOrEmpty("ro.build.version.codename");
  std::string known_codenames =
      pre_reboot_build_props_->GetOrEmpty("ro.build.version.known_codenames");
  if (sdk_version.empty() || codename.empty() || known_codenames.empty()) {
    return Errorf("Failed to read system properties");
  }

  CmdlineBuilder args = OR_RETURN(GetArtExecCmdlineBuilder());
  args.Add("--keep-fds=%d", output->Fd())
      .Add("--")
      .Add("/apex/com.android.sdkext/bin/derive_classpath")
      .Add("--override-device-sdk-version=%s", sdk_version)
      .Add("--override-device-codename=%s", codename)
      .Add("--override-device-known-codenames=%s", known_codenames)
      .Add("/proc/self/fd/%d", output->Fd());

  LOG(INFO) << "Running derive_classpath: " << Join(args.Get(), /*separator=*/" ");

  Result<int> result = ExecAndReturnCode(args.Get(), kShortTimeoutSec);
  if (!result.ok()) {
    return Errorf("Failed to run derive_classpath: {}", result.error().message());
  }

  LOG(INFO) << ART_FORMAT("derive_classpath returned code {}", result.value());

  if (result.value() != 0) {
    return Errorf("derive_classpath returned an unexpected code: {}", result.value());
  }

  if (output->FlushClose() != 0) {
    return ErrnoErrorf("Failed to flush and close '{}'", path);
  }

  return {};
}

Result<bool> Artd::PreRebootInitBootImages(ArtdCancellationSignal* cancellation_signal) {
  CmdlineBuilder args = OR_RETURN(GetArtExecCmdlineBuilder());
  args.Add("--")
      .Add(OR_RETURN(BuildArtBinPath("odrefresh")))
      .Add("--only-boot-images")
      .Add("--compile");

  LOG(INFO) << "Running odrefresh: " << Join(args.Get(), /*separator=*/" ");

  Result<int> result =
      ExecAndReturnCode(args.Get(), kLongTimeoutSec, cancellation_signal->CreateExecCallbacks());
  if (!result.ok()) {
    if (cancellation_signal->IsCancelled()) {
      return false;
    }
    return Errorf("Failed to run odrefresh: {}", result.error().message());
  }

  LOG(INFO) << ART_FORMAT("odrefresh returned code {}", result.value());

  if (result.value() != odrefresh::ExitCode::kCompilationSuccess &&
      result.value() != odrefresh::ExitCode::kOkay) {
    return Errorf("odrefresh returned an unexpected code: {}", result.value());
  }

  return true;
}

ScopedAStatus Artd::validateDexPath(const std::string& in_dexFile,
                                    std::optional<std::string>* _aidl_return) {
  RETURN_FATAL_IF_NOT_PRE_REBOOT(options_);
  if (Result<void> result = ValidateDexPath(in_dexFile); !result.ok()) {
    *_aidl_return = result.error().message();
  } else {
    *_aidl_return = std::nullopt;
  }
  return ScopedAStatus::ok();
}

ScopedAStatus Artd::validateClassLoaderContext(const std::string& in_dexFile,
                                               const std::string& in_classLoaderContext,
                                               std::optional<std::string>* _aidl_return) {
  RETURN_FATAL_IF_NOT_PRE_REBOOT(options_);
  if (Result<void> result = ValidateClassLoaderContext(in_dexFile, in_classLoaderContext);
      !result.ok()) {
    *_aidl_return = result.error().message();
  } else {
    *_aidl_return = std::nullopt;
  }
  return ScopedAStatus::ok();
}

Result<BuildSystemProperties> BuildSystemProperties::Create(const std::string& filename) {
  std::string content;
  if (!ReadFileToString(filename, &content)) {
    return ErrnoErrorf("Failed to read '{}'", filename);
  }
  std::regex import_pattern(R"re(import\s.*)re");
  std::unordered_map<std::string, std::string> system_properties;
  for (const std::string& raw_line : Split(content, "\n")) {
    std::string line = Trim(raw_line);
    if (line.empty() || line.starts_with('#') || std::regex_match(line, import_pattern)) {
      continue;
    }
    size_t pos = line.find('=');
    if (pos == std::string::npos || pos == 0 || (pos == 1 && line[1] == '?')) {
      return Errorf("Malformed system property line '{}' in file '{}'", line, filename);
    }
    if (line[pos - 1] == '?') {
      std::string key = line.substr(/*pos=*/0, /*n=*/pos - 1);
      if (system_properties.find(key) == system_properties.end()) {
        system_properties[key] = line.substr(pos + 1);
      }
    } else {
      system_properties[line.substr(/*pos=*/0, /*n=*/pos)] = line.substr(pos + 1);
    }
  }
  return BuildSystemProperties(std::move(system_properties));
}

std::string BuildSystemProperties::GetProperty(const std::string& key) const {
  auto it = system_properties_.find(key);
  return it != system_properties_.end() ? it->second : "";
}

}  // namespace artd
}  // namespace art
