/*
 * Copyright (C) 2016 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 <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/file.h>
#include <sys/param.h>
#include <unistd.h>

#include <cstdint>
#include <fstream>
#include <iostream>
#include <optional>
#include <ostream>
#include <set>
#include <string>
#include <string_view>
#include <tuple>
#include <unordered_set>
#include <vector>

#include "android-base/parsebool.h"
#include "android-base/stringprintf.h"
#include "android-base/strings.h"
#include "base/array_ref.h"
#include "base/dumpable.h"
#include "base/logging.h"  // For InitLogging.
#include "base/mem_map.h"
#include "base/scoped_flock.h"
#include "base/stl_util.h"
#include "base/string_view_cpp20.h"
#include "base/time_utils.h"
#include "base/unix_file/fd_file.h"
#include "base/utils.h"
#include "base/zip_archive.h"
#include "boot_image_profile.h"
#include "dex/art_dex_file_loader.h"
#include "dex/bytecode_utils.h"
#include "dex/class_accessor-inl.h"
#include "dex/class_reference.h"
#include "dex/code_item_accessors-inl.h"
#include "dex/descriptors_names.h"
#include "dex/dex_file.h"
#include "dex/dex_file_loader.h"
#include "dex/dex_file_structs.h"
#include "dex/dex_file_types.h"
#include "dex/method_reference.h"
#include "dex/type_reference.h"
#include "profile/profile_boot_info.h"
#include "profile/profile_compilation_info.h"
#include "profile_assistant.h"
#include "profman/profman_result.h"

namespace art {

using ProfileSampleAnnotation = ProfileCompilationInfo::ProfileSampleAnnotation;

static int original_argc;
static char** original_argv;

static std::string CommandLine() {
  std::vector<std::string> command;
  command.reserve(original_argc);
  for (int i = 0; i < original_argc; ++i) {
    command.push_back(original_argv[i]);
  }
  return android::base::Join(command, ' ');
}

static bool FdIsValid(int fd) {
  return fd != File::kInvalidFd;
}

static void UsageErrorV(const char* fmt, va_list ap) {
  std::string error;
  android::base::StringAppendV(&error, fmt, ap);
  LOG(ERROR) << error;
}

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

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

  UsageError("Command: %s", CommandLine().c_str());
  UsageError("Usage: profman [options]...");
  UsageError("");
  UsageError("  --dump-only: dumps the content of the specified profile files");
  UsageError("      to standard output (default) in a human readable form.");
  UsageError("");
  UsageError("  --dump-output-to-fd=<number>: redirects --dump-only output to a file descriptor.");
  UsageError("");
  UsageError("  --dump-classes-and-methods: dumps a sorted list of classes and methods that are");
  UsageError("      in the specified profile file to standard output (default) in a human");
  UsageError("      readable form. The output is valid input for --create-profile-from");
  UsageError("");
  UsageError("  --profile-file=<filename>: specify profiler output file to use for compilation.");
  UsageError("      Can be specified multiple time, in which case the data from the different");
  UsageError("      profiles will be aggregated. Can also be specified zero times, in which case");
  UsageError("      profman will still analyze the reference profile against the given --apk and");
  UsageError("      return exit code based on whether the reference profile is empty and whether");
  UsageError("      an error occurs, but no merge will happen.");
  UsageError("");
  UsageError("  --profile-file-fd=<number>: same as --profile-file but accepts a file descriptor.");
  UsageError("      Cannot be used together with --profile-file.");
  UsageError("");
  UsageError("  --reference-profile-file=<filename>: specify a reference profile.");
  UsageError("      The data in this file will be compared with the data obtained by merging");
  UsageError("      all the files specified with --profile-file or --profile-file-fd.");
  UsageError("      If the exit code is ProfmanResult::kCompile then all --profile-file will be");
  UsageError("      merged into --reference-profile-file. ");
  UsageError("");
  UsageError("  --reference-profile-file-fd=<number>: same as --reference-profile-file but");
  UsageError("      accepts a file descriptor. Cannot be used together with");
  UsageError("      --reference-profile-file.");
  UsageError("");
  UsageError("  --generate-test-profile=<filename>: generates a random profile file for testing.");
  UsageError("  --generate-test-profile-num-dex=<number>: number of dex files that should be");
  UsageError("      included in the generated profile. Defaults to 20.");
  UsageError("  --generate-test-profile-method-percentage=<number>: the percentage from the maximum");
  UsageError("      number of methods that should be generated. Defaults to 5.");
  UsageError("  --generate-test-profile-class-percentage=<number>: the percentage from the maximum");
  UsageError("      number of classes that should be generated. Defaults to 5.");
  UsageError("  --generate-test-profile-seed=<number>: seed for random number generator used when");
  UsageError("      generating random test profiles. Defaults to using NanoTime.");
  UsageError("");
  UsageError("  --create-profile-from=<filename>: creates a profile from a list of classes,");
  UsageError("      methods and inline caches.");
  UsageError("  --output-profile-type=(app|boot|bprof): Select output profile format for");
  UsageError("      the --create-profile-from option. Default: app.");
  UsageError("");
  UsageError("  --dex-location=<string>: location string to use with corresponding");
  UsageError("      apk-fd to find dex files");
  UsageError("");
  UsageError("  --apk-fd=<number>: file descriptor containing an open APK to");
  UsageError("      search for dex files");
  UsageError("  --apk=<filename>: an APK to search for dex files");
  UsageError("  --skip-apk-verification: do not attempt to verify APKs");
  UsageError("");
  UsageError("  --generate-boot-image-profile: Generate a boot image profile based on input");
  UsageError("      profiles. Requires passing in dex files to inspect properties of classes.");
  UsageError("  --method-threshold=percentage between 0 and 100");
  UsageError("      what threshold to apply to the methods when deciding whether or not to");
  UsageError("      include it in the final profile.");
  UsageError("  --class-threshold=percentage between 0 and 100");
  UsageError("      what threshold to apply to the classes when deciding whether or not to");
  UsageError("      include it in the final profile.");
  UsageError("  --clean-class-threshold=percentage between 0 and 100");
  UsageError("      what threshold to apply to the clean classes when deciding whether or not to");
  UsageError("      include it in the final profile.");
  UsageError("  --preloaded-class-threshold=percentage between 0 and 100");
  UsageError("      what threshold to apply to the classes when deciding whether or not to");
  UsageError("      include it in the final preloaded classes.");
  UsageError("  --preloaded-classes-denylist=file");
  UsageError("      a file listing the classes that should not be preloaded in Zygote");
  UsageError("  --upgrade-startup-to-hot=true|false:");
  UsageError("      whether or not to upgrade startup methods to hot");
  UsageError("  --special-package=pkg_name:percentage between 0 and 100");
  UsageError("      what threshold to apply to the methods/classes that are used by the given");
  UsageError("      package when deciding whether or not to include it in the final profile.");
  UsageError("  --debug-append-uses=bool: whether or not to append package use as debug info.");
  UsageError("  --out-profile-path=path: boot image profile output path");
  UsageError("  --out-preloaded-classes-path=path: preloaded classes output path");
  UsageError("  --copy-and-update-profile-key: if present, profman will copy the profile from");
  UsageError("      the file passed with --profile-fd(file) to the profile passed with");
  UsageError("      --reference-profile-fd(file) and update at the same time the profile-key");
  UsageError("      of entries corresponding to the apks passed with --apk(-fd).");
  UsageError("  --boot-image-merge: indicates that this merge is for a boot image profile.");
  UsageError("      In this case, the reference profile must have a boot profile version.");
  UsageError("  --force-merge: performs a forced merge, without analyzing if there is a");
  UsageError("      significant difference between the current profile and the reference profile.");
  UsageError("  --min-new-methods-percent-change=percentage between 0 and 100 (default 20)");
  UsageError("      the min percent of new methods to trigger a compilation.");
  UsageError("  --min-new-classes-percent-change=percentage between 0 and 100 (default 20)");
  UsageError("      the min percent of new classes to trigger a compilation.");
  UsageError("");

  exit(ProfmanResult::kErrorUsage);
}

// Note: make sure you update the Usage if you change these values.
static constexpr uint16_t kDefaultTestProfileNumDex = 20;
static constexpr uint16_t kDefaultTestProfileMethodPercentage = 5;
static constexpr uint16_t kDefaultTestProfileClassPercentage = 5;

// Separators used when parsing human friendly representation of profiles.
static const std::string kMethodSep = "->";  // NOLINT [runtime/string] [4]
static const std::string kMissingTypesMarker = "missing_types";  // NOLINT [runtime/string] [4]
static const std::string kMegamorphicTypesMarker = "megamorphic_types";  // NOLINT [runtime/string] [4]
static const std::string kClassAllMethods = "*";  // NOLINT [runtime/string] [4]
static constexpr char kAnnotationStart = '{';
static constexpr char kAnnotationEnd = '}';
static constexpr char kProfileParsingInlineChacheSep = '+';
static constexpr char kProfileParsingInlineChacheTargetSep = ']';
static constexpr char kProfileParsingTypeSep = ',';
static constexpr char kProfileParsingFirstCharInSignature = '(';
static constexpr char kMethodFlagStringHot = 'H';
static constexpr char kMethodFlagStringStartup = 'S';
static constexpr char kMethodFlagStringPostStartup = 'P';

NO_RETURN static void Abort(const char* msg) {
  LOG(ERROR) << msg;
  exit(1);
}
template <typename T>
static void ParseUintValue(const std::string& option_name,
                           const std::string& value,
                           T* out,
                           T min = std::numeric_limits<T>::min(),
                           T max = std::numeric_limits<T>::max()) {
  int64_t parsed_integer_value = 0;
  if (!android::base::ParseInt(
      value,
      &parsed_integer_value,
      static_cast<int64_t>(min),
      static_cast<int64_t>(max))) {
    Usage("Failed to parse %s '%s' as an integer", option_name.c_str(), value.c_str());
  }
  if (parsed_integer_value < 0) {
    Usage("%s passed a negative value %" PRId64, option_name.c_str(), parsed_integer_value);
  }
  if (static_cast<uint64_t>(parsed_integer_value) >
      static_cast<std::make_unsigned_t<T>>(std::numeric_limits<T>::max())) {
    Usage("%s passed a value %" PRIu64 " above max (%" PRIu64 ")",
          option_name.c_str(),
          static_cast<uint64_t>(parsed_integer_value),
          static_cast<uint64_t>(std::numeric_limits<T>::max()));
  }
  *out = dchecked_integral_cast<T>(parsed_integer_value);
}

template <typename T>
static void ParseUintOption(const char* raw_option,
                            std::string_view option_prefix,
                            T* out,
                            T min = std::numeric_limits<T>::min(),
                            T max = std::numeric_limits<T>::max()) {
  DCHECK(EndsWith(option_prefix, "="));
  DCHECK(StartsWith(raw_option, option_prefix)) << raw_option << " " << option_prefix;
  std::string option_name(option_prefix.substr(option_prefix.size() - 1u));
  const char* value_string = raw_option + option_prefix.size();

  ParseUintValue(option_name, value_string, out, min, max);
}

static void ParseBoolOption(const char* raw_option,
                            std::string_view option_prefix,
                            bool* out) {
  DCHECK(EndsWith(option_prefix, "="));
  DCHECK(StartsWith(raw_option, option_prefix)) << raw_option << " " << option_prefix;
  const char* value_string = raw_option + option_prefix.size();
  android::base::ParseBoolResult result = android::base::ParseBool(value_string);
  if (result == android::base::ParseBoolResult::kError) {
    std::string option_name(option_prefix.substr(option_prefix.size() - 1u));
    Usage("Failed to parse %s '%s' as an integer", option_name.c_str(), value_string);
  }

  *out = result == android::base::ParseBoolResult::kTrue;
}

enum class OutputProfileType {
  kApp,
  kBoot,
  kBprof,
};

static void ParseOutputProfileType(const char* raw_option,
                                   std::string_view option_prefix,
                                   OutputProfileType* out) {
  DCHECK(EndsWith(option_prefix, "="));
  DCHECK(StartsWith(raw_option, option_prefix)) << raw_option << " " << option_prefix;
  const char* value_string = raw_option + option_prefix.size();
  if (strcmp(value_string, "app") == 0) {
    *out = OutputProfileType::kApp;
  } else if (strcmp(value_string, "boot") == 0) {
    *out = OutputProfileType::kBoot;
  } else if (strcmp(value_string, "bprof") == 0) {
    *out = OutputProfileType::kBprof;
  } else {
    std::string option_name(option_prefix.substr(option_prefix.size() - 1u));
    Usage("Failed to parse %s '%s' as (app|boot|bprof)", option_name.c_str(), value_string);
  }
}

// TODO(calin): This class has grown too much from its initial design. Split the functionality
// into smaller, more contained pieces.
class ProfMan final {
 public:
  ProfMan() :
      reference_profile_file_fd_(File::kInvalidFd),
      dump_only_(false),
      dump_classes_and_methods_(false),
      generate_boot_image_profile_(false),
      output_profile_type_(OutputProfileType::kApp),
      dump_output_to_fd_(File::kInvalidFd),
      test_profile_num_dex_(kDefaultTestProfileNumDex),
      test_profile_method_percerntage_(kDefaultTestProfileMethodPercentage),
      test_profile_class_percentage_(kDefaultTestProfileClassPercentage),
      test_profile_seed_(NanoTime()),
      start_ns_(NanoTime()),
      copy_and_update_profile_key_(false),
      profile_assistant_options_(ProfileAssistant::Options()) {}

  ~ProfMan() {
    LogCompletionTime();
  }

  void ParseArgs(int argc, char **argv) {
    original_argc = argc;
    original_argv = argv;

    MemMap::Init();
    InitLogging(argv, Abort);

    // Skip over the command name.
    argv++;
    argc--;

    if (argc == 0) {
      Usage("No arguments specified");
    }

    for (int i = 0; i < argc; ++i) {
      const char* raw_option = argv[i];
      const std::string_view option(raw_option);
      const bool log_options = false;
      if (log_options) {
        LOG(INFO) << "profman: option[" << i << "]=" << argv[i];
      }
      if (option == "--dump-only") {
        dump_only_ = true;
      } else if (option == "--dump-classes-and-methods") {
        dump_classes_and_methods_ = true;
      } else if (StartsWith(option, "--create-profile-from=")) {
        create_profile_from_file_ = std::string(option.substr(strlen("--create-profile-from=")));
      } else if (StartsWith(option, "--output-profile-type=")) {
        ParseOutputProfileType(raw_option, "--output-profile-type=", &output_profile_type_);
      } else if (StartsWith(option, "--dump-output-to-fd=")) {
        ParseUintOption(raw_option, "--dump-output-to-fd=", &dump_output_to_fd_);
      } else if (option == "--generate-boot-image-profile") {
        generate_boot_image_profile_ = true;
      } else if (StartsWith(option, "--method-threshold=")) {
        ParseUintOption(raw_option,
                        "--method-threshold=",
                        &boot_image_options_.method_threshold,
                        0u,
                        100u);
      } else if (StartsWith(option, "--class-threshold=")) {
        ParseUintOption(raw_option,
                        "--class-threshold=",
                        &boot_image_options_.image_class_threshold,
                        0u,
                        100u);
      } else if (StartsWith(option, "--clean-class-threshold=")) {
        ParseUintOption(raw_option,
                        "--clean-class-threshold=",
                        &boot_image_options_.image_class_clean_threshold,
                        0u,
                        100u);
      } else if (StartsWith(option, "--preloaded-class-threshold=")) {
        ParseUintOption(raw_option,
                        "--preloaded-class-threshold=",
                        &boot_image_options_.preloaded_class_threshold,
                        0u,
                        100u);
      } else if (StartsWith(option, "--preloaded-classes-denylist=")) {
        std::string preloaded_classes_denylist =
            std::string(option.substr(strlen("--preloaded-classes-denylist=")));
        // Read the user-specified list of methods.
        std::unique_ptr<std::set<std::string>>
            denylist(ReadCommentedInputFromFile<std::set<std::string>>(
                preloaded_classes_denylist.c_str(), nullptr));  // No post-processing.
        boot_image_options_.preloaded_classes_denylist.insert(
            denylist->begin(), denylist->end());
      } else if (StartsWith(option, "--upgrade-startup-to-hot=")) {
        ParseBoolOption(raw_option,
                        "--upgrade-startup-to-hot=",
                        &boot_image_options_.upgrade_startup_to_hot);
      } else if (StartsWith(option, "--special-package=")) {
        std::vector<std::string> values;
        Split(std::string(option.substr(strlen("--special-package="))), ':', &values);
        if (values.size() != 2) {
          Usage("--special-package needs to be specified as pkg_name:threshold");
        }
        uint32_t threshold;
        ParseUintValue("special-package", values[1], &threshold, 0u, 100u);
        boot_image_options_.special_packages_thresholds.Overwrite(values[0], threshold);
      } else if (StartsWith(option, "--debug-append-uses=")) {
        ParseBoolOption(raw_option,
                        "--debug-append-uses=",
                        &boot_image_options_.append_package_use_list);
      } else if (StartsWith(option, "--out-profile-path=")) {
        boot_profile_out_path_ = std::string(option.substr(strlen("--out-profile-path=")));
      } else if (StartsWith(option, "--out-preloaded-classes-path=")) {
        preloaded_classes_out_path_ = std::string(
            option.substr(strlen("--out-preloaded-classes-path=")));
      } else if (StartsWith(option, "--profile-file=")) {
        profile_files_.push_back(std::string(option.substr(strlen("--profile-file="))));
      } else if (StartsWith(option, "--profile-file-fd=")) {
        ParseFdForCollection(raw_option, "--profile-file-fd=", &profile_files_fd_);
      } else if (StartsWith(option, "--reference-profile-file=")) {
        reference_profile_file_ = std::string(option.substr(strlen("--reference-profile-file=")));
      } else if (StartsWith(option, "--reference-profile-file-fd=")) {
        ParseUintOption(raw_option, "--reference-profile-file-fd=", &reference_profile_file_fd_);
      } else if (StartsWith(option, "--dex-location=")) {
        dex_locations_.push_back(std::string(option.substr(strlen("--dex-location="))));
      } else if (StartsWith(option, "--apk-fd=")) {
        ParseFdForCollection(raw_option, "--apk-fd=", &apks_fd_);
      } else if (StartsWith(option, "--apk=")) {
        apk_files_.push_back(std::string(option.substr(strlen("--apk="))));
      } else if (StartsWith(option, "--generate-test-profile=")) {
        test_profile_ = std::string(option.substr(strlen("--generate-test-profile=")));
      } else if (StartsWith(option, "--generate-test-profile-num-dex=")) {
        ParseUintOption(raw_option,
                        "--generate-test-profile-num-dex=",
                        &test_profile_num_dex_);
      } else if (StartsWith(option, "--generate-test-profile-method-percentage=")) {
        ParseUintOption(raw_option,
                        "--generate-test-profile-method-percentage=",
                        &test_profile_method_percerntage_);
      } else if (StartsWith(option, "--generate-test-profile-class-percentage=")) {
        ParseUintOption(raw_option,
                        "--generate-test-profile-class-percentage=",
                        &test_profile_class_percentage_);
      } else if (StartsWith(option, "--generate-test-profile-seed=")) {
        ParseUintOption(raw_option, "--generate-test-profile-seed=", &test_profile_seed_);
      } else if (StartsWith(option, "--min-new-methods-percent-change=")) {
        uint32_t min_new_methods_percent_change;
        ParseUintOption(raw_option,
                        "--min-new-methods-percent-change=",
                        &min_new_methods_percent_change,
                        0u,
                        100u);
        profile_assistant_options_.SetMinNewMethodsPercentChangeForCompilation(
            min_new_methods_percent_change);
      } else if (StartsWith(option, "--min-new-classes-percent-change=")) {
        uint32_t min_new_classes_percent_change;
        ParseUintOption(raw_option,
                        "--min-new-classes-percent-change=",
                        &min_new_classes_percent_change,
                        0u,
                        100u);
        profile_assistant_options_.SetMinNewClassesPercentChangeForCompilation(
            min_new_classes_percent_change);
      } else if (option == "--copy-and-update-profile-key") {
        copy_and_update_profile_key_ = true;
      } else if (option == "--boot-image-merge") {
        profile_assistant_options_.SetBootImageMerge(true);
      } else if (option == "--force-merge") {
        profile_assistant_options_.SetForceMerge(true);
      } else {
        Usage("Unknown argument '%s'", raw_option);
      }
    }

    // Validate global consistency between file/fd options.
    if (!profile_files_.empty() && !profile_files_fd_.empty()) {
      Usage("Profile files should not be specified with both --profile-file-fd and --profile-file");
    }
    if (!reference_profile_file_.empty() && FdIsValid(reference_profile_file_fd_)) {
      Usage("Reference profile should not be specified with both "
            "--reference-profile-file-fd and --reference-profile-file");
    }
    if (!apk_files_.empty() && !apks_fd_.empty()) {
      Usage("APK files should not be specified with both --apk-fd and --apk");
    }
  }

  struct ProfileFilterKey {
    ProfileFilterKey(const std::string& dex_location, uint32_t checksum)
        : dex_location_(dex_location), checksum_(checksum) {}
    const std::string dex_location_;
    uint32_t checksum_;

    bool operator==(const ProfileFilterKey& other) const {
      return checksum_ == other.checksum_ && dex_location_ == other.dex_location_;
    }
    bool operator<(const ProfileFilterKey& other) const {
      return checksum_ == other.checksum_
          ?  dex_location_ < other.dex_location_
          : checksum_ < other.checksum_;
    }
  };

  ProfmanResult::ProcessingResult ProcessProfiles() {
    // Validate that a reference profile was passed, at the very least. It's okay that profiles are
    // missing, in which case profman will still analyze the reference profile (to check whether
    // it's empty), but no merge will happen.
    if (reference_profile_file_.empty() && !FdIsValid(reference_profile_file_fd_)) {
      Usage("No reference profile file specified.");
    }
    if ((!profile_files_.empty() && FdIsValid(reference_profile_file_fd_)) ||
        (!profile_files_fd_.empty() && !FdIsValid(reference_profile_file_fd_))) {
      Usage("Options --profile-file-fd and --reference-profile-file-fd "
            "should only be used together");
    }

    // Check if we have any apks which we should use to filter the profile data.
    std::set<ProfileFilterKey> profile_filter_keys;
    if (!GetProfileFilterKeyFromApks(&profile_filter_keys)) {
      return ProfmanResult::kErrorIO;
    }

    // Build the profile filter function. If the set of keys is empty it means we
    // don't have any apks; as such we do not filter anything.
    const ProfileCompilationInfo::ProfileLoadFilterFn& filter_fn =
        [profile_filter_keys](const std::string& profile_key, uint32_t checksum) {
            if (profile_filter_keys.empty()) {
              // No --apk was specified. Accept all dex files.
              return true;
            } else {
              // Remove any annotations from the profile key before comparing with the keys we get from apks.
              std::string base_key = ProfileCompilationInfo::GetBaseKeyFromAugmentedKey(profile_key);
              return profile_filter_keys.find(ProfileFilterKey(base_key, checksum)) !=
                  profile_filter_keys.end();
            }
        };

    ProfmanResult::ProcessingResult result;

    if (reference_profile_file_.empty()) {
      // The file doesn't need to be flushed here (ProcessProfiles will do it)
      // so don't check the usage.
      File file(reference_profile_file_fd_, false);
      result = ProfileAssistant::ProcessProfiles(profile_files_fd_,
                                                 reference_profile_file_fd_,
                                                 filter_fn,
                                                 profile_assistant_options_);
      CloseAllFds(profile_files_fd_, "profile_files_fd_");
    } else {
      result = ProfileAssistant::ProcessProfiles(profile_files_,
                                                 reference_profile_file_,
                                                 filter_fn,
                                                 profile_assistant_options_);
    }
    return result;
  }

  bool GetProfileFilterKeyFromApks(std::set<ProfileFilterKey>* profile_filter_keys) {
    auto process_fn = [profile_filter_keys](std::unique_ptr<const DexFile>&& dex_file) {
      // Store the profile key of the location instead of the location itself.
      // This will make the matching in the profile filter method much easier.
      profile_filter_keys->emplace(ProfileCompilationInfo::GetProfileDexFileBaseKey(
          dex_file->GetLocation()), dex_file->GetLocationChecksum());
    };
    return OpenApkFilesFromLocations(process_fn);
  }

  bool OpenApkFilesFromLocations(std::vector<std::unique_ptr<const DexFile>>* dex_files) {
    auto process_fn = [dex_files](std::unique_ptr<const DexFile>&& dex_file) {
      dex_files->emplace_back(std::move(dex_file));
    };
    return OpenApkFilesFromLocations(process_fn);
  }

  bool OpenApkFilesFromLocations(
      const std::function<void(std::unique_ptr<const DexFile>&&)>& process_fn) {
    bool use_apk_fd_list = !apks_fd_.empty();
    if (use_apk_fd_list) {
      // Get the APKs from the collection of FDs.
      if (dex_locations_.empty()) {
        // Try to compute the dex locations from the file paths of the descriptions.
        // This will make it easier to invoke profman with --apk-fd and without
        // being force to pass --dex-location when the location would be the apk path.
        if (!ComputeDexLocationsFromApkFds()) {
          return false;
        }
      } else {
        if (dex_locations_.size() != apks_fd_.size()) {
            Usage("The number of apk-fds must match the number of dex-locations.");
        }
      }
    } else if (!apk_files_.empty()) {
      if (dex_locations_.empty()) {
        // If no dex locations are specified use the apk names as locations.
        dex_locations_ = apk_files_;
      } else if (dex_locations_.size() != apk_files_.size()) {
          Usage("The number of apk-fds must match the number of dex-locations.");
      }
    } else {
      // No APKs were specified.
      CHECK(dex_locations_.empty());
      return true;
    }
    static constexpr bool kVerifyChecksum = true;
    for (size_t i = 0; i < dex_locations_.size(); ++i) {
      std::string error_msg;
      const ArtDexFileLoader dex_file_loader;
      std::vector<std::unique_ptr<const DexFile>> dex_files_for_location;
      // We do not need to verify the apk for processing profiles.
      if (use_apk_fd_list) {
        if (dex_file_loader.OpenZip(apks_fd_[i],
                                    dex_locations_[i],
                                    /* verify= */ false,
                                    kVerifyChecksum,
                                    &error_msg,
                                    &dex_files_for_location)) {
        } else {
          LOG(ERROR) << "OpenZip failed for '" << dex_locations_[i] << "' " << error_msg;
          return false;
        }
      } else {
        if (dex_file_loader.Open(apk_files_[i].c_str(),
                                 dex_locations_[i],
                                 /* verify= */ false,
                                 kVerifyChecksum,
                                 &error_msg,
                                 &dex_files_for_location)) {
        } else {
          LOG(ERROR) << "Open failed for '" << dex_locations_[i] << "' " << error_msg;
          return false;
        }
      }
      for (std::unique_ptr<const DexFile>& dex_file : dex_files_for_location) {
        process_fn(std::move(dex_file));
      }
    }
    return true;
  }

  // Get the dex locations from the apk fds.
  // The methods reads the links from /proc/self/fd/ to find the original apk paths
  // and puts them in the dex_locations_ vector.
  bool ComputeDexLocationsFromApkFds() {
#ifdef _WIN32
    PLOG(ERROR) << "ComputeDexLocationsFromApkFds is unsupported on Windows.";
    return false;
#else
    // We can't use a char array of PATH_MAX size without exceeding the frame size.
    // So we use a vector as the buffer for the path.
    std::vector<char> buffer(PATH_MAX, 0);
    for (size_t i = 0; i < apks_fd_.size(); ++i) {
      std::string fd_path = "/proc/self/fd/" + std::to_string(apks_fd_[i]);
      ssize_t len = readlink(fd_path.c_str(), buffer.data(), buffer.size() - 1);
      if (len == -1) {
        PLOG(ERROR) << "Could not open path from fd";
        return false;
      }

      buffer[len] = '\0';
      dex_locations_.push_back(buffer.data());
    }
    return true;
#endif
  }

  std::unique_ptr<const ProfileCompilationInfo> LoadProfile(const std::string& filename,
                                                            int fd,
                                                            bool for_boot_image) {
    if (!filename.empty()) {
#ifdef _WIN32
      int flags = O_RDWR;
#else
      int flags = O_RDWR | O_CLOEXEC;
#endif
      fd = open(filename.c_str(), flags);
      if (fd < 0) {
        PLOG(ERROR) << "Cannot open " << filename;
        return nullptr;
      }
    }
    std::unique_ptr<ProfileCompilationInfo> info(new ProfileCompilationInfo(for_boot_image));
    if (!info->Load(fd)) {
      LOG(ERROR) << "Cannot load profile info from fd=" << fd << "\n";
      return nullptr;
    }
    return info;
  }

  int DumpOneProfile(const std::string& banner,
                     const std::string& filename,
                     int fd,
                     const std::vector<std::unique_ptr<const DexFile>>* dex_files,
                     std::string* dump) {
    // For dumping, try loading as app profile and if that fails try loading as boot profile.
    std::unique_ptr<const ProfileCompilationInfo> info =
        LoadProfile(filename, fd, /*for_boot_image=*/ false);
    if (info == nullptr) {
      info = LoadProfile(filename, fd, /*for_boot_image=*/ true);
    }
    if (info == nullptr) {
      LOG(ERROR) << "Cannot load profile info from filename=" << filename << " fd=" << fd;
      return -1;
    }
    *dump += banner + "\n" + info->DumpInfo(MakeNonOwningPointerVector(*dex_files)) + "\n";
    return 0;
  }

  int DumpProfileInfo() {
    // Validate that at least one profile file or reference was specified.
    if (profile_files_.empty() && profile_files_fd_.empty() &&
        reference_profile_file_.empty() && !FdIsValid(reference_profile_file_fd_)) {
      Usage("No profile files or reference profile specified.");
    }
    static const char* kEmptyString = "";
    static const char* kOrdinaryProfile = "=== profile ===";
    static const char* kReferenceProfile = "=== reference profile ===";
    static const char* kDexFiles = "=== Dex files  ===";

    std::vector<std::unique_ptr<const DexFile>> dex_files;
    OpenApkFilesFromLocations(&dex_files);

    std::string dump;

    // Dump checkfiles and corresponding checksums.
    dump += kDexFiles;
    dump += "\n";
    for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
      std::ostringstream oss;
      oss << dex_file->GetLocation()
          << " [checksum=" << std::hex << dex_file->GetLocationChecksum() << "]\n";
      dump += oss.str();
    }

    // Dump individual profile files.
    if (!profile_files_fd_.empty()) {
      for (int profile_file_fd : profile_files_fd_) {
        int ret = DumpOneProfile(kOrdinaryProfile,
                                 kEmptyString,
                                 profile_file_fd,
                                 &dex_files,
                                 &dump);
        if (ret != 0) {
          return ret;
        }
      }
    }
    for (const std::string& profile_file : profile_files_) {
      int ret = DumpOneProfile(kOrdinaryProfile, profile_file, File::kInvalidFd, &dex_files, &dump);
      if (ret != 0) {
        return ret;
      }
    }
    // Dump reference profile file.
    if (FdIsValid(reference_profile_file_fd_)) {
      int ret = DumpOneProfile(kReferenceProfile,
                               kEmptyString,
                               reference_profile_file_fd_,
                               &dex_files,
                               &dump);
      if (ret != 0) {
        return ret;
      }
    }
    if (!reference_profile_file_.empty()) {
      int ret = DumpOneProfile(kReferenceProfile,
                               reference_profile_file_,
                               File::kInvalidFd,
                               &dex_files,
                               &dump);
      if (ret != 0) {
        return ret;
      }
    }
    if (!FdIsValid(dump_output_to_fd_)) {
      std::cout << dump;
    } else {
      unix_file::FdFile out_fd(dump_output_to_fd_, /*check_usage=*/ false);
      if (!out_fd.WriteFully(dump.c_str(), dump.length())) {
        return -1;
      }
    }
    return 0;
  }

  bool ShouldOnlyDumpProfile() {
    return dump_only_;
  }

  // Creates the inline-cache portion of a text-profile line. If there is no
  // inline-caches this will be and empty string. Otherwise it will be '@'
  // followed by an IC description matching the format described by ProcessLine
  // below. Note that this will collapse all ICs with the same receiver type.
  std::string GetInlineCacheLine(const ProfileCompilationInfo& profile_info,
                                 const dex::MethodId& id,
                                 const DexFile* dex_file,
                                 uint16_t dex_method_idx) {
    ProfileCompilationInfo::MethodHotness hotness =
        profile_info.GetMethodHotness(MethodReference(dex_file, dex_method_idx));
    DCHECK(!hotness.IsHot() || hotness.GetInlineCacheMap() != nullptr);
    if (!hotness.IsHot() || hotness.GetInlineCacheMap()->empty()) {
      return "";
    }
    const ProfileCompilationInfo::InlineCacheMap* inline_caches = hotness.GetInlineCacheMap();
    struct IcLineInfo {
      bool is_megamorphic_ = false;
      bool is_missing_types_ = false;
      std::set<dex::TypeIndex> classes_;
    };
    std::unordered_map<dex::TypeIndex, IcLineInfo> ics;
    CodeItemInstructionAccessor accessor(
        *dex_file,
        dex_file->GetCodeItem(dex_file->FindCodeItemOffset(*dex_file->FindClassDef(id.class_idx_),
                                                            dex_method_idx)));
    for (const auto& [pc, ic_data] : *inline_caches) {
      const Instruction& inst = accessor.InstructionAt(pc);
      const dex::MethodId& target = dex_file->GetMethodId(inst.VRegB());
      if (ic_data.classes.empty() && !ic_data.is_megamorphic && !ic_data.is_missing_types) {
        continue;
      }
      auto val = ics.find(target.class_idx_);
      if (val == ics.end()) {
        val = ics.insert({ target.class_idx_, {} }).first;
      }
      if (ic_data.is_megamorphic) {
        val->second.is_megamorphic_ = true;
      }
      if (ic_data.is_missing_types) {
        val->second.is_missing_types_ = true;
      }
      for (dex::TypeIndex type_index : ic_data.classes) {
        val->second.classes_.insert(type_index);
      }
    }
    if (ics.empty()) {
      return "";
    }
    std::ostringstream dump_ic;
    dump_ic << kProfileParsingInlineChacheSep;
    for (const auto& [target, dex_data] : ics) {
      dump_ic << kProfileParsingInlineChacheTargetSep;
      dump_ic << dex_file->GetTypeDescriptor(dex_file->GetTypeId(target));
      if (dex_data.is_missing_types_) {
        dump_ic << kMissingTypesMarker;
      } else if (dex_data.is_megamorphic_) {
        dump_ic << kMegamorphicTypesMarker;
      } else {
        bool first = true;
        for (dex::TypeIndex type_index : dex_data.classes_) {
          if (!first) {
            dump_ic << kProfileParsingTypeSep;
          }
          first = false;
          dump_ic << profile_info.GetTypeDescriptor(dex_file, type_index);
        }
      }
    }
    return dump_ic.str();
  }

  bool GetClassNamesAndMethods(const ProfileCompilationInfo& profile_info,
                               std::vector<std::unique_ptr<const DexFile>>* dex_files,
                               std::set<std::string>* out_lines) {
    for (const std::unique_ptr<const DexFile>& dex_file : *dex_files) {
      std::set<dex::TypeIndex> class_types;
      std::set<uint16_t> hot_methods;
      std::set<uint16_t> startup_methods;
      std::set<uint16_t> post_startup_methods;
      std::set<uint16_t> combined_methods;
      if (profile_info.GetClassesAndMethods(*dex_file.get(),
                                            &class_types,
                                            &hot_methods,
                                            &startup_methods,
                                            &post_startup_methods)) {
        for (const dex::TypeIndex& type_index : class_types) {
          out_lines->insert(profile_info.GetTypeDescriptor(dex_file.get(), type_index));
        }
        combined_methods = hot_methods;
        combined_methods.insert(startup_methods.begin(), startup_methods.end());
        combined_methods.insert(post_startup_methods.begin(), post_startup_methods.end());
        for (uint16_t dex_method_idx : combined_methods) {
          const dex::MethodId& id = dex_file->GetMethodId(dex_method_idx);
          std::string signature_string(dex_file->GetMethodSignature(id).ToString());
          std::string type_string(dex_file->GetTypeDescriptor(dex_file->GetTypeId(id.class_idx_)));
          std::string method_name(dex_file->GetMethodName(id));
          std::string flags_string;
          if (hot_methods.find(dex_method_idx) != hot_methods.end()) {
            flags_string += kMethodFlagStringHot;
          }
          if (startup_methods.find(dex_method_idx) != startup_methods.end()) {
            flags_string += kMethodFlagStringStartup;
          }
          if (post_startup_methods.find(dex_method_idx) != post_startup_methods.end()) {
            flags_string += kMethodFlagStringPostStartup;
          }
          std::string inline_cache_string =
              GetInlineCacheLine(profile_info, id, dex_file.get(), dex_method_idx);
          out_lines->insert(flags_string + type_string + kMethodSep + method_name +
                            signature_string + inline_cache_string);
        }
      }
    }
    return true;
  }

  bool GetClassNamesAndMethods(int fd,
                               std::vector<std::unique_ptr<const DexFile>>* dex_files,
                               std::set<std::string>* out_lines) {
    // For dumping, try loading as app profile and if that fails try loading as boot profile.
    for (bool for_boot_image : {false, true}) {
      ProfileCompilationInfo profile_info(for_boot_image);
      if (profile_info.Load(fd)) {
        return GetClassNamesAndMethods(profile_info, dex_files, out_lines);
      }
    }
    LOG(ERROR) << "Cannot load profile info";
    return false;
  }

  bool GetClassNamesAndMethods(const std::string& profile_file,
                               std::vector<std::unique_ptr<const DexFile>>* dex_files,
                               std::set<std::string>* out_lines) {
#ifdef _WIN32
    int flags = O_RDONLY;
#else
    int flags = O_RDONLY | O_CLOEXEC;
#endif
    int fd = open(profile_file.c_str(), flags);
    if (!FdIsValid(fd)) {
      PLOG(ERROR) << "Cannot open " << profile_file;
      return false;
    }
    if (!GetClassNamesAndMethods(fd, dex_files, out_lines)) {
      return false;
    }
    if (close(fd) < 0) {
      PLOG(WARNING) << "Failed to close descriptor";
    }
    return true;
  }

  int DumpClassesAndMethods() {
    // Validate that at least one profile file or reference was specified.
    if (profile_files_.empty() && profile_files_fd_.empty() &&
        reference_profile_file_.empty() && !FdIsValid(reference_profile_file_fd_)) {
      Usage("No profile files or reference profile specified.");
    }

    // Open the dex files to get the names for classes.
    std::vector<std::unique_ptr<const DexFile>> dex_files;
    OpenApkFilesFromLocations(&dex_files);
    // Build a vector of class names from individual profile files.
    std::set<std::string> class_names;
    if (!profile_files_fd_.empty()) {
      for (int profile_file_fd : profile_files_fd_) {
        if (!GetClassNamesAndMethods(profile_file_fd, &dex_files, &class_names)) {
          return -1;
        }
      }
    }
    if (!profile_files_.empty()) {
      for (const std::string& profile_file : profile_files_) {
        if (!GetClassNamesAndMethods(profile_file, &dex_files, &class_names)) {
          return -1;
        }
      }
    }
    // Concatenate class names from reference profile file.
    if (FdIsValid(reference_profile_file_fd_)) {
      if (!GetClassNamesAndMethods(reference_profile_file_fd_, &dex_files, &class_names)) {
        return -1;
      }
    }
    if (!reference_profile_file_.empty()) {
      if (!GetClassNamesAndMethods(reference_profile_file_, &dex_files, &class_names)) {
        return -1;
      }
    }
    // Dump the class names.
    std::string dump;
    for (const std::string& class_name : class_names) {
      dump += class_name + std::string("\n");
    }
    if (!FdIsValid(dump_output_to_fd_)) {
      std::cout << dump;
    } else {
      unix_file::FdFile out_fd(dump_output_to_fd_, /*check_usage=*/ false);
      if (!out_fd.WriteFully(dump.c_str(), dump.length())) {
        return -1;
      }
    }
    return 0;
  }

  bool ShouldOnlyDumpClassesAndMethods() {
    return dump_classes_and_methods_;
  }

  // Read lines from the given file, dropping comments and empty lines. Post-process each line with
  // the given function.
  template <typename T>
  static T* ReadCommentedInputFromFile(
      const char* input_filename, std::function<std::string(const char*)>* process) {
    std::unique_ptr<std::ifstream> input_file(new std::ifstream(input_filename, std::ifstream::in));
    if (input_file.get() == nullptr) {
      LOG(ERROR) << "Failed to open input file " << input_filename;
      return nullptr;
    }
    std::unique_ptr<T> result(
        ReadCommentedInputStream<T>(*input_file, process));
    input_file->close();
    return result.release();
  }

  // Read lines from the given stream, dropping comments and empty lines. Post-process each line
  // with the given function.
  template <typename T>
  static T* ReadCommentedInputStream(
      std::istream& in_stream,
      std::function<std::string(const char*)>* process) {
    std::unique_ptr<T> output(new T());
    while (in_stream.good()) {
      std::string dot;
      std::getline(in_stream, dot);
      if (android::base::StartsWith(dot, "#") || dot.empty()) {
        continue;
      }
      if (process != nullptr) {
        std::string descriptor((*process)(dot.c_str()));
        output->insert(output->end(), descriptor);
      } else {
        output->insert(output->end(), dot);
      }
    }
    return output.release();
  }

  // Find class definition for a descriptor.
  const dex::ClassDef* FindClassDef(const std::vector<std::unique_ptr<const DexFile>>& dex_files,
                                    std::string_view klass_descriptor,
                                    /*out*/ TypeReference* class_ref) {
    for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
      const dex::TypeId* type_id = dex_file->FindTypeId(klass_descriptor);
      if (type_id != nullptr) {
        dex::TypeIndex type_index = dex_file->GetIndexForTypeId(*type_id);
        const dex::ClassDef* class_def = dex_file->FindClassDef(type_index);
        if (class_def != nullptr) {
          *class_ref = TypeReference(dex_file.get(), type_index);
          return class_def;
        }
      }
    }
    return nullptr;
  }

  // Find class klass_descriptor in the given dex_files and store its reference
  // in the out parameter class_ref.
  // Return true if a reference of the class was found in any of the dex_files.
  bool FindClass(const std::vector<std::unique_ptr<const DexFile>>& dex_files,
                 std::string_view klass_descriptor,
                 /*out*/ TypeReference* class_ref) {
    for (const std::unique_ptr<const DexFile>& dex_file_ptr : dex_files) {
      const DexFile* dex_file = dex_file_ptr.get();
      const dex::TypeId* type_id = dex_file->FindTypeId(klass_descriptor);
      if (type_id != nullptr) {
        *class_ref = TypeReference(dex_file, dex_file->GetIndexForTypeId(*type_id));
        return true;
      }
    }
    return false;
  }

  // Find the method specified by method_spec in the class class_ref.
  uint32_t FindMethodIndex(const TypeReference& class_ref,
                           std::string_view method_spec) {
    const DexFile* dex_file = class_ref.dex_file;

    size_t signature_start = method_spec.find(kProfileParsingFirstCharInSignature);
    if (signature_start == std::string_view::npos) {
      LOG(ERROR) << "Invalid method name and signature: " << method_spec;
      return dex::kDexNoIndex;
    }

    const std::string_view name = method_spec.substr(0u, signature_start);
    const std::string_view signature = method_spec.substr(signature_start);

    const dex::StringId* name_id = dex_file->FindStringId(std::string(name).c_str());
    if (name_id == nullptr) {
      LOG(WARNING) << "Could not find name: "  << name;
      return dex::kDexNoIndex;
    }
    dex::TypeIndex return_type_idx;
    std::vector<dex::TypeIndex> param_type_idxs;
    if (!dex_file->CreateTypeList(signature, &return_type_idx, &param_type_idxs)) {
      LOG(WARNING) << "Could not create type list: " << signature;
      return dex::kDexNoIndex;
    }
    const dex::ProtoId* proto_id = dex_file->FindProtoId(return_type_idx, param_type_idxs);
    if (proto_id == nullptr) {
      LOG(WARNING) << "Could not find proto_id: " << name;
      return dex::kDexNoIndex;
    }
    const dex::MethodId* method_id = dex_file->FindMethodId(
        dex_file->GetTypeId(class_ref.TypeIndex()), *name_id, *proto_id);
    if (method_id == nullptr) {
      LOG(WARNING) << "Could not find method_id: " << name;
      return dex::kDexNoIndex;
    }

    return dex_file->GetIndexForMethodId(*method_id);
  }

  template <typename Visitor>
  void VisitAllInstructions(const TypeReference& class_ref, uint16_t method_idx, Visitor visitor) {
    const DexFile* dex_file = class_ref.dex_file;
    const dex::ClassDef* def = dex_file->FindClassDef(class_ref.TypeIndex());
    if (def == nullptr) {
      return;
    }
    std::optional<uint32_t> offset = dex_file->GetCodeItemOffset(*def, method_idx);
    if (offset.has_value()) {
      for (const DexInstructionPcPair& inst :
          CodeItemInstructionAccessor(*dex_file, dex_file->GetCodeItem(*offset))) {
        if (!visitor(inst)) {
          break;
        }
      }
    } else {
      LOG(WARNING) << "Could not find method " << method_idx;
    }
  }

  // Get dex-pcs of any virtual + interface invokes referencing a method of the
  // 'target' type in the given method.
  void GetAllInvokes(const TypeReference& class_ref,
                     uint16_t method_idx,
                     dex::TypeIndex target,
                     /*out*/ std::vector<uint32_t>* dex_pcs) {
    const DexFile* dex_file = class_ref.dex_file;
    VisitAllInstructions(class_ref, method_idx, [&](const DexInstructionPcPair& inst) -> bool {
      switch (inst->Opcode()) {
        case Instruction::INVOKE_INTERFACE:
        case Instruction::INVOKE_INTERFACE_RANGE:
        case Instruction::INVOKE_VIRTUAL:
        case Instruction::INVOKE_VIRTUAL_RANGE: {
          const dex::MethodId& meth = dex_file->GetMethodId(inst->VRegB());
          if (meth.class_idx_ == target) {
            dex_pcs->push_back(inst.DexPc());
          }
          break;
        }
        default:
          break;
      }
      return true;
    });
  }

  // Given a method, return true if the method has a single INVOKE_VIRTUAL in its byte code.
  // Upon success it returns true and stores the method index and the invoke dex pc
  // in the output parameters.
  // The format of the method spec is "inlinePolymorphic(LSuper;)I+LSubA;,LSubB;,LSubC;".
  bool HasSingleInvoke(const TypeReference& class_ref,
                       uint16_t method_index,
                       /*out*/ uint32_t* dex_pc) {
    bool found_invoke = false;
    bool found_multiple_invokes = false;
    VisitAllInstructions(class_ref, method_index, [&](const DexInstructionPcPair& inst) -> bool {
      if (inst->Opcode() == Instruction::INVOKE_VIRTUAL ||
          inst->Opcode() == Instruction::INVOKE_VIRTUAL_RANGE ||
          inst->Opcode() == Instruction::INVOKE_INTERFACE ||
          inst->Opcode() == Instruction::INVOKE_INTERFACE_RANGE) {
        if (found_invoke) {
          LOG(ERROR) << "Multiple invoke INVOKE_VIRTUAL found: "
                     << class_ref.dex_file->PrettyMethod(method_index);
          return false;
        }
        found_invoke = true;
        *dex_pc = inst.DexPc();
      }
      return true;
    });
    if (!found_invoke) {
      LOG(ERROR) << "Could not find any INVOKE_VIRTUAL/INTERFACE: "
                 << class_ref.dex_file->PrettyMethod(method_index);
    }
    return found_invoke && !found_multiple_invokes;
  }

  struct InlineCacheSegment {
   public:
    using IcArray =
        std::array<std::string_view, ProfileCompilationInfo::kIndividualInlineCacheSize + 1>;
    static void SplitInlineCacheSegment(std::string_view ic_line,
                                        /*out*/ std::vector<InlineCacheSegment>* res) {
      if (ic_line[0] != kProfileParsingInlineChacheTargetSep) {
        // single target
        InlineCacheSegment out;
        Split(ic_line, kProfileParsingTypeSep, &out.inline_caches_);
        res->push_back(out);
        return;
      }
      std::vector<std::string_view> targets_and_resolutions;
      // Avoid a zero-length entry.
      for (std::string_view t :
           SplitString(ic_line.substr(1), kProfileParsingInlineChacheTargetSep)) {
        InlineCacheSegment out;
        DCHECK_EQ(t[0], 'L') << "Target is not a class? " << t;
        size_t recv_end = t.find_first_of(';');
        out.receiver_ = t.substr(0, recv_end + 1);
        Split(t.substr(recv_end + 1), kProfileParsingTypeSep, &out.inline_caches_);
        res->push_back(out);
      }
    }

    bool IsSingleReceiver() const {
      return !receiver_.has_value();
    }

    const std::string_view& GetReceiverType() const {
      DCHECK(!IsSingleReceiver());
      return *receiver_;
    }

    const IcArray& GetIcTargets() const {
      return inline_caches_;
    }

    size_t NumIcTargets() const {
      return std::count_if(
          inline_caches_.begin(), inline_caches_.end(), [](const auto& x) { return !x.empty(); });
    }

    std::ostream& Dump(std::ostream& os) const {
      if (!IsSingleReceiver()) {
        os << "[" << GetReceiverType();
      }
      bool first = true;
      for (std::string_view target : inline_caches_) {
        if (target.empty()) {
          break;
        } else if (!first) {
          os << ",";
        }
        first = false;
        os << target;
      }
      return os;
    }

   private:
    std::optional<std::string_view> receiver_;
    // Max number of ics in the profile file. Don't need to store more than this
    // (although internally we can have as many as we want). If we fill this up
    // we are megamorphic.
    IcArray inline_caches_;

    friend std::ostream& operator<<(std::ostream& os, const InlineCacheSegment& ics);
  };

  struct ClassMethodReference {
    TypeReference type_;
    uint32_t method_index_;

    bool operator==(const ClassMethodReference& ref) {
      return ref.type_ == type_ && ref.method_index_ == method_index_;
    }
    bool operator!=(const ClassMethodReference& ref) {
      return !(*this == ref);
    }
  };

  // Try to perform simple method resolution to produce a more useful profile.
  // This will resolve to the nearest class+method-index which is within the
  // same dexfile and in a declared supertype of the starting class. It will
  // return nullopt if it cannot find an appropriate method or the nearest
  // possibility is private.
  // TODO: This should ideally support looking in other dex files. That's getting
  // to the point of needing to have a whole class-linker so it's probably not
  // worth it.
  std::optional<ClassMethodReference> ResolveMethod(TypeReference class_ref,
                                                    uint32_t method_index) {
    const DexFile* dex = class_ref.dex_file;
    const dex::ClassDef* def = dex->FindClassDef(class_ref.TypeIndex());
    if (def == nullptr || method_index >= dex->NumMethodIds()) {
      // Class not in dex-file.
      return std::nullopt;
    }
    if (LIKELY(dex->GetCodeItemOffset(*def, method_index).has_value())) {
      return ClassMethodReference{class_ref, method_index};
    }
    // What to look for.
    const dex::MethodId& method_id = dex->GetMethodId(method_index);
    // No going between different dexs so use name and proto directly
    const dex::ProtoIndex& method_proto = method_id.proto_idx_;
    const dex::StringIndex& method_name = method_id.name_idx_;
    // Floyd's algo to prevent infinite loops.
    // Slow-iterator position for Floyd's
    dex::TypeIndex slow_class_type = def->class_idx_;
    // Whether to take a step with the slow iterator.
    bool update_slow = false;
    for (dex::TypeIndex cur_candidate = def->superclass_idx_;
         cur_candidate != dex::TypeIndex::Invalid() && cur_candidate != slow_class_type;) {
      const dex::ClassDef* cur_class_def = dex->FindClassDef(cur_candidate);
      if (cur_class_def == nullptr) {
        // We left the dex file.
        return std::nullopt;
      }
      const dex::MethodId* cur_id =
          dex->FindMethodIdByIndex(cur_candidate, method_name, method_proto);
      if (cur_id != nullptr) {
        if (dex->GetCodeItemOffset(*cur_class_def, dex->GetIndexForMethodId(*cur_id)).has_value()) {
          return ClassMethodReference{TypeReference(dex, cur_candidate),
                                      dex->GetIndexForMethodId(*cur_id)};
        }
      }
      // Floyd's algo step.
      cur_candidate = cur_class_def->superclass_idx_;
      slow_class_type =
          update_slow ? dex->FindClassDef(slow_class_type)->superclass_idx_ : slow_class_type;
      update_slow = !update_slow;
    }
    return std::nullopt;
  }

  // Process a line defining a class or a method and its inline caches.
  // Upon success return true and add the class or the method info to profile.
  // Inline caches are identified by the type of the declared receiver type.
  // The possible line formats are:
  // "LJustTheClass;".
  // "LTestInline;->inlinePolymorphic(LSuper;)I+LSubA;,LSubB;,LSubC;".
  // "LTestInline;->inlineMissingTypes(LSuper;)I+missing_types".
  // // Note no ',' after [LTarget;
  // "LTestInline;->multiInlinePolymorphic(LSuper;)I+]LTarget1;LResA;,LResB;]LTarget2;LResC;,LResD;".
  // "LTestInline;->multiInlinePolymorphic(LSuper;)I+]LTarget1;missing_types]LTarget2;LResC;,LResD;".
  // "{annotation}LTestInline;->inlineNoInlineCaches(LSuper;)I".
  // "LTestInline;->*".
  // The method and classes are searched only in the given dex files.
  bool ProcessLine(const std::vector<std::unique_ptr<const DexFile>>& dex_files,
                   std::string_view maybe_annotated_line,
                   /*out*/ProfileCompilationInfo* profile) {
    // First, process the annotation.
    if (maybe_annotated_line.empty()) {
      return true;
    }
    // Working line variable which will contain the user input without the annotations.
    std::string_view line = maybe_annotated_line;

    std::string_view annotation_string;
    if (maybe_annotated_line[0] == kAnnotationStart) {
      size_t end_pos = maybe_annotated_line.find(kAnnotationEnd, 0);
      if (end_pos == std::string::npos || end_pos == 0) {
        LOG(ERROR) << "Invalid line: " << maybe_annotated_line;
        return false;
      }
      annotation_string = maybe_annotated_line.substr(1, end_pos - 1);
      // Update the working line.
      line = maybe_annotated_line.substr(end_pos + 1);
    }

    ProfileSampleAnnotation annotation = annotation_string.empty()
        ? ProfileSampleAnnotation::kNone
        : ProfileSampleAnnotation(std::string(annotation_string));

    // Now process the rest of the line.
    std::string_view klass;
    std::string_view method_str;
    bool is_hot = false;
    bool is_startup = false;
    bool is_post_startup = false;
    const size_t method_sep_index = line.find(kMethodSep, 0);
    if (method_sep_index == std::string::npos) {
      klass = line;
    } else {
      // The method prefix flags are only valid for method strings.
      size_t start_index = 0;
      while (start_index < line.size() && line[start_index] != 'L') {
        const char c = line[start_index];
        if (c == kMethodFlagStringHot) {
          is_hot = true;
        } else if (c == kMethodFlagStringStartup) {
          is_startup = true;
        } else if (c == kMethodFlagStringPostStartup) {
          is_post_startup = true;
        } else {
          LOG(WARNING) << "Invalid flag " << c;
          return false;
        }
        ++start_index;
      }
      klass = line.substr(start_index, method_sep_index - start_index);
      method_str = line.substr(method_sep_index + kMethodSep.size());
    }

    if (!IsValidDescriptor(std::string(klass).c_str())) {
      LOG(ERROR) << "Invalid descriptor: " << klass;
      return false;
    }

    if (method_str.empty()) {
      auto array_it = std::find_if(klass.begin(), klass.end(), [](char c) { return c != '['; });
      size_t array_dim = std::distance(klass.begin(), array_it);
      if (klass.size() == array_dim + 1u) {
        // Attribute primitive types and their arrays to the first dex file.
        profile->AddClass(*dex_files[0], klass, annotation);
        return true;
      }
      // Attribute non-primitive classes and their arrays to the dex file with the definition.
      TypeReference class_ref(/* dex_file= */ nullptr, dex::TypeIndex());
      if (FindClassDef(dex_files, klass.substr(array_dim), &class_ref) == nullptr) {
        LOG(WARNING) << "Could not find class definition: " << klass.substr(array_dim);
        return false;
      }
      if (array_dim != 0) {
        // Let the ProfileCompilationInfo find the type index or add an extra descriptor.
        return profile->AddClass(*class_ref.dex_file, klass, annotation);
      } else {
        return profile->AddClass(*class_ref.dex_file, class_ref.TypeIndex(), annotation);
      }
    }

    DCHECK_NE(klass[0], '[');
    TypeReference class_ref(/* dex_file= */ nullptr, dex::TypeIndex());
    const dex::ClassDef* class_def = FindClassDef(dex_files, klass, &class_ref);
    if (class_def == nullptr) {
      LOG(WARNING) << "Could not find class definition: " << klass;
      return false;
    }

    uint32_t flags = 0;
    if (is_hot) {
      flags |= ProfileCompilationInfo::MethodHotness::kFlagHot;
    }
    if (is_startup) {
      flags |= ProfileCompilationInfo::MethodHotness::kFlagStartup;
    }
    if (is_post_startup) {
      flags |= ProfileCompilationInfo::MethodHotness::kFlagPostStartup;
    }

    if (method_str == kClassAllMethods) {
      // Start by adding the class.
      profile->AddClass(*class_ref.dex_file, class_ref.TypeIndex(), annotation);
      uint16_t class_def_index = class_ref.dex_file->GetIndexForClassDef(*class_def);
      ClassAccessor accessor(*class_ref.dex_file, class_def_index);
      std::vector<ProfileMethodInfo> methods;
      for (const ClassAccessor::Method& method : accessor.GetMethods()) {
        if (method.GetCodeItemOffset() != 0) {
          // Add all of the methods that have code to the profile.
          methods.push_back(ProfileMethodInfo(method.GetReference()));
        }
      }
      // TODO: Check return value?
      profile->AddMethods(
          methods, static_cast<ProfileCompilationInfo::MethodHotness::Flag>(flags), annotation);
      return true;
    }

    // Process the method.
    std::string method_spec;

    // If none of the flags are set, default to hot.
    // TODO: Why is this done after we have already calculated `flags`?
    is_hot = is_hot || (!is_hot && !is_startup && !is_post_startup);

    // Lifetime of segments is same as method_elems since it contains pointers into the string-data
    std::vector<InlineCacheSegment> segments;
    std::vector<std::string_view> method_elems;
    Split(method_str, kProfileParsingInlineChacheSep, &method_elems);
    if (method_elems.size() == 2) {
      method_spec = method_elems[0];
      InlineCacheSegment::SplitInlineCacheSegment(method_elems[1], &segments);
    } else if (method_elems.size() == 1) {
      method_spec = method_elems[0];
    } else {
      LOG(ERROR) << "Invalid method line: " << line;
      return false;
    }

    const uint32_t method_index = FindMethodIndex(class_ref, method_spec);
    if (method_index == dex::kDexNoIndex) {
      LOG(WARNING) << "Could not find method " << klass << "->" << method_spec;
      return false;
    }

    std::optional<ClassMethodReference>
        resolved_class_method_ref = ResolveMethod(class_ref, method_index);

    std::vector<ProfileMethodInfo::ProfileInlineCache> inline_caches;
    // We can only create inline-caches when we actually have code we can
    // examine. If we couldn't resolve the method don't bother trying to create
    // inline-caches.
    if (resolved_class_method_ref) {
      for (const InlineCacheSegment& segment : segments) {
        std::vector<uint32_t> dex_pcs;
        if (segment.IsSingleReceiver()) {
          DCHECK_EQ(segments.size(), 1u);
          dex_pcs.resize(1, -1);
          // TODO This single invoke format should really be phased out and
          // removed.
          if (!HasSingleInvoke(class_ref, method_index, &dex_pcs[0])) {
            return false;
          }
        } else {
          // Get the type-ref the method code will use.
          std::string receiver_str(segment.GetReceiverType());
          const dex::TypeId *type_id =
              class_ref.dex_file->FindTypeId(receiver_str.c_str());
          if (type_id == nullptr) {
            LOG(WARNING) << "Could not find class: "
                         << segment.GetReceiverType() << " in dex-file "
                         << class_ref.dex_file << ". Ignoring IC group: '"
                         << segment << "'";
            continue;
          }
          dex::TypeIndex target_index =
              class_ref.dex_file->GetIndexForTypeId(*type_id);

          GetAllInvokes(resolved_class_method_ref->type_,
                        resolved_class_method_ref->method_index_,
                        target_index,
                        &dex_pcs);
        }
        bool missing_types = segment.GetIcTargets()[0] == kMissingTypesMarker;
        bool megamorphic_types =
            segment.GetIcTargets()[0] == kMegamorphicTypesMarker;
        std::vector<TypeReference> classes;
        if (!missing_types && !megamorphic_types) {
          classes.reserve(segment.NumIcTargets());
          for (const std::string_view& ic_class : segment.GetIcTargets()) {
            if (ic_class.empty()) {
              break;
            }
            if (!IsValidDescriptor(std::string(ic_class).c_str())) {
              LOG(ERROR) << "Invalid descriptor for inline cache: " << ic_class;
              return false;
            }
            // TODO: Allow referencing classes without a `dex::TypeId` in any of the dex files.
            TypeReference ic_class_ref(/* dex_file= */ nullptr, dex::TypeIndex());
            if (!FindClass(dex_files, ic_class, &ic_class_ref)) {
              LOG(segment.IsSingleReceiver() ? ERROR : WARNING)
                  << "Could not find class: " << ic_class << " in " << segment;
              if (segment.IsSingleReceiver()) {
                return false;
              } else {
                // Be a bit more forgiving with profiles from servers.
                missing_types = true;
                classes.clear();
                break;
              }
            }
            classes.push_back(ic_class_ref);
          }
        }
        for (size_t dex_pc : dex_pcs) {
          inline_caches.emplace_back(dex_pc, missing_types, classes, megamorphic_types);
        }
      }
    }
    MethodReference ref(class_ref.dex_file, method_index);
    if (is_hot) {
      ClassMethodReference orig_cmr { class_ref, method_index };
      if (!inline_caches.empty() &&
          resolved_class_method_ref &&
          orig_cmr != *resolved_class_method_ref) {
        // We have inline-caches on a method that doesn't actually exist. We
        // want to put the inline caches on the resolved version of the method
        // (if we could find one) and just mark the actual method as present.
        const DexFile *dex = resolved_class_method_ref->type_.dex_file;
        LOG(VERBOSE) << "Adding "
                     << dex->PrettyMethod(
                            resolved_class_method_ref->method_index_)
                     << " as alias for " << dex->PrettyMethod(method_index);
        // The inline-cache refers to a supertype of the actual profile line.
        // Include this supertype method in the profile as well.
        MethodReference resolved_ref(class_ref.dex_file,
                                     resolved_class_method_ref->method_index_);
        profile->AddMethod(
            ProfileMethodInfo(resolved_ref, inline_caches),
            static_cast<ProfileCompilationInfo::MethodHotness::Flag>(flags),
            annotation);
        profile->AddMethod(
            ProfileMethodInfo(ref),
            static_cast<ProfileCompilationInfo::MethodHotness::Flag>(flags),
            annotation);
      } else {
        profile->AddMethod(
            ProfileMethodInfo(ref, inline_caches),
            static_cast<ProfileCompilationInfo::MethodHotness::Flag>(flags),
            annotation);
      }
    }
    if (flags != 0) {
      if (!profile->AddMethod(ProfileMethodInfo(ref),
                              static_cast<ProfileCompilationInfo::MethodHotness::Flag>(flags),
                              annotation)) {
        return false;
      }
      DCHECK(profile->GetMethodHotness(ref, annotation).IsInProfile()) << method_spec;
    }
    return true;
  }

  bool ProcessBootLine(const std::vector<std::unique_ptr<const DexFile>>& dex_files,
                       std::string_view line,
                       ProfileBootInfo* boot_profiling_info) {
    const size_t method_sep_index = line.find(kMethodSep, 0);
    if (method_sep_index == std::string_view::npos) {
      LOG(ERROR) << "Invalid boot line: " << line;
      return false;
    }
    std::string_view klass_str = line.substr(0, method_sep_index);
    std::string_view method_str = line.substr(method_sep_index + kMethodSep.size());

    TypeReference class_ref(/* dex_file= */ nullptr, dex::TypeIndex());
    if (FindClassDef(dex_files, klass_str, &class_ref) == nullptr) {
      LOG(WARNING) << "Could not find class definition: " << klass_str;
      return false;
    }

    const uint32_t method_index = FindMethodIndex(class_ref, method_str);
    if (method_index == dex::kDexNoIndex) {
      LOG(WARNING) << "Could not find method: " << line;
      return false;
    }
    boot_profiling_info->Add(class_ref.dex_file, method_index);
    return true;
  }

  int OpenReferenceProfile() const {
    int fd = reference_profile_file_fd_;
    if (!FdIsValid(fd)) {
      CHECK(!reference_profile_file_.empty());
#ifdef _WIN32
      int flags = O_CREAT | O_TRUNC | O_WRONLY;
#else
      int flags = O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC;
#endif
      fd = open(reference_profile_file_.c_str(), flags, 0644);
      if (fd < 0) {
        PLOG(ERROR) << "Cannot open " << reference_profile_file_;
        return File::kInvalidFd;
      }
    }
    return fd;
  }

  // Create and store a ProfileBootInfo.
  int CreateBootProfile() {
    // Validate parameters for this command.
    if (apk_files_.empty() && apks_fd_.empty()) {
      Usage("APK files must be specified");
    }
    if (dex_locations_.empty()) {
      Usage("DEX locations must be specified");
    }
    if (reference_profile_file_.empty() && !FdIsValid(reference_profile_file_fd_)) {
      Usage("Reference profile must be specified with --reference-profile-file or "
            "--reference-profile-file-fd");
    }
    if (!profile_files_.empty() || !profile_files_fd_.empty()) {
      Usage("Profile must be specified with --reference-profile-file or "
            "--reference-profile-file-fd");
    }
    // Open the profile output file if needed.
    int fd = OpenReferenceProfile();
    if (!FdIsValid(fd)) {
        return -1;
    }
    // Read the user-specified list of methods.
    std::unique_ptr<std::vector<std::string>>
        user_lines(ReadCommentedInputFromFile<std::vector<std::string>>(
            create_profile_from_file_.c_str(), nullptr));  // No post-processing.

    // Open the dex files to look up classes and methods.
    std::vector<std::unique_ptr<const DexFile>> dex_files;
    OpenApkFilesFromLocations(&dex_files);

    // Process the lines one by one and add the successful ones to the profile.
    ProfileBootInfo info;

    for (const auto& line : *user_lines) {
      ProcessBootLine(dex_files, line, &info);
    }

    // Write the profile file.
    CHECK(info.Save(fd));

    if (close(fd) < 0) {
      PLOG(WARNING) << "Failed to close descriptor";
    }

    return 0;
  }

  // Creates a profile from a human friendly textual representation.
  // The expected input format is:
  //   # Classes
  //   Ljava/lang/Comparable;
  //   Ljava/lang/Math;
  //   # Methods with inline caches
  //   LTestInline;->inlinePolymorphic(LSuper;)I+LSubA;,LSubB;,LSubC;
  //   LTestInline;->noInlineCache(LSuper;)I
  int CreateProfile() {
    // Validate parameters for this command.
    if (apk_files_.empty() && apks_fd_.empty()) {
      Usage("APK files must be specified");
    }
    if (dex_locations_.empty()) {
      Usage("DEX locations must be specified");
    }
    if (reference_profile_file_.empty() && !FdIsValid(reference_profile_file_fd_)) {
      Usage("Reference profile must be specified with --reference-profile-file or "
            "--reference-profile-file-fd");
    }
    if (!profile_files_.empty() || !profile_files_fd_.empty()) {
      Usage("Profile must be specified with --reference-profile-file or "
            "--reference-profile-file-fd");
    }
    // Open the profile output file if needed.
    int fd = OpenReferenceProfile();
    if (!FdIsValid(fd)) {
        return -1;
    }
    // Read the user-specified list of classes and methods.
    std::unique_ptr<std::unordered_set<std::string>>
        user_lines(ReadCommentedInputFromFile<std::unordered_set<std::string>>(
            create_profile_from_file_.c_str(), nullptr));  // No post-processing.

    // Open the dex files to look up classes and methods.
    std::vector<std::unique_ptr<const DexFile>> dex_files;
    OpenApkFilesFromLocations(&dex_files);

    // Process the lines one by one and add the successful ones to the profile.
    bool for_boot_image = GetOutputProfileType() == OutputProfileType::kBoot;
    ProfileCompilationInfo info(for_boot_image);

    if (for_boot_image) {
      // Add all dex files to the profile. This is needed for jitzygote to indicate
      // which dex files are part of the boot image extension to compile in memory.
      for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
        if (info.FindOrAddDexFile(*dex_file) == info.MaxProfileIndex()) {
          LOG(ERROR) << "Failed to add dex file to boot image profile: " << dex_file->GetLocation();
          return -1;
        }
      }
    }

    for (const auto& line : *user_lines) {
      ProcessLine(dex_files, line, &info);
    }

    // Write the profile file.
    CHECK(info.Save(fd));
    if (close(fd) < 0) {
      PLOG(WARNING) << "Failed to close descriptor";
    }
    return 0;
  }

  bool ShouldCreateBootImageProfile() const {
    return generate_boot_image_profile_;
  }

  OutputProfileType GetOutputProfileType() const {
    return output_profile_type_;
  }

  // Create and store a ProfileCompilationInfo for the boot image.
  int CreateBootImageProfile() {
    // Open the input profile file.
    if (profile_files_.size() < 1) {
      LOG(ERROR) << "At least one --profile-file must be specified.";
      return -1;
    }
    // Open the dex files.
    std::vector<std::unique_ptr<const DexFile>> dex_files;
    OpenApkFilesFromLocations(&dex_files);
    if (dex_files.empty()) {
      PLOG(ERROR) << "Expected dex files for creating boot profile";
      return -2;
    }

    if (!GenerateBootImageProfile(dex_files,
                                  profile_files_,
                                  boot_image_options_,
                                  boot_profile_out_path_,
                                  preloaded_classes_out_path_)) {
      LOG(ERROR) << "There was an error when generating the boot image profiles";
      return -4;
    }
    return 0;
  }

  bool ShouldCreateProfile() {
    return !create_profile_from_file_.empty();
  }

  int GenerateTestProfile() {
    // Validate parameters for this command.
    if (test_profile_method_percerntage_ > 100) {
      Usage("Invalid percentage for --generate-test-profile-method-percentage");
    }
    if (test_profile_class_percentage_ > 100) {
      Usage("Invalid percentage for --generate-test-profile-class-percentage");
    }
    // If given APK files or DEX locations, check that they're ok.
    if (!apk_files_.empty() || !apks_fd_.empty() || !dex_locations_.empty()) {
      if (apk_files_.empty() && apks_fd_.empty()) {
        Usage("APK files must be specified when passing DEX locations to --generate-test-profile");
      }
      if (dex_locations_.empty()) {
        Usage("DEX locations must be specified when passing APK files to --generate-test-profile");
      }
    }
    // ShouldGenerateTestProfile confirms !test_profile_.empty().
#ifdef _WIN32
    int flags = O_CREAT | O_TRUNC | O_WRONLY;
#else
    int flags = O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC;
#endif
    int profile_test_fd = open(test_profile_.c_str(), flags, 0644);
    if (profile_test_fd < 0) {
      PLOG(ERROR) << "Cannot open " << test_profile_;
      return -1;
    }
    bool result;
    if (apk_files_.empty() && apks_fd_.empty() && dex_locations_.empty()) {
      result = ProfileCompilationInfo::GenerateTestProfile(profile_test_fd,
                                                           test_profile_num_dex_,
                                                           test_profile_method_percerntage_,
                                                           test_profile_class_percentage_,
                                                           test_profile_seed_);
    } else {
      // Open the dex files to look up classes and methods.
      std::vector<std::unique_ptr<const DexFile>> dex_files;
      OpenApkFilesFromLocations(&dex_files);
      // Create a random profile file based on the set of dex files.
      result = ProfileCompilationInfo::GenerateTestProfile(profile_test_fd,
                                                           dex_files,
                                                           test_profile_method_percerntage_,
                                                           test_profile_class_percentage_,
                                                           test_profile_seed_);
    }
    close(profile_test_fd);  // ignore close result.
    return result ? 0 : -1;
  }

  bool ShouldGenerateTestProfile() {
    return !test_profile_.empty();
  }

  bool ShouldCopyAndUpdateProfileKey() const {
    return copy_and_update_profile_key_;
  }

  ProfmanResult::CopyAndUpdateResult CopyAndUpdateProfileKey() {
    // Validate that at least one profile file was passed, as well as a reference profile.
    if (!(profile_files_.size() == 1 ^ profile_files_fd_.size() == 1)) {
      Usage("Only one profile file should be specified.");
    }
    if (reference_profile_file_.empty() && !FdIsValid(reference_profile_file_fd_)) {
      Usage("No reference profile file specified.");
    }

    if (apk_files_.empty() && apks_fd_.empty()) {
      Usage("No apk files specified");
    }

    bool use_fds = profile_files_fd_.size() == 1;

    ProfileCompilationInfo profile;
    // Do not clear if invalid. The input might be an archive.
    bool load_ok = use_fds
        ? profile.Load(profile_files_fd_[0])
        : profile.Load(profile_files_[0], /*clear_if_invalid=*/ false);
    if (load_ok) {
      // Open the dex files to look up classes and methods.
      std::vector<std::unique_ptr<const DexFile>> dex_files;
      OpenApkFilesFromLocations(&dex_files);
      bool updated = false;
      if (!profile.UpdateProfileKeys(dex_files, &updated)) {
        return ProfmanResult::kCopyAndUpdateErrorFailedToUpdateProfile;
      }
      bool result = use_fds
          ? profile.Save(reference_profile_file_fd_)
          : profile.Save(reference_profile_file_, /*bytes_written=*/ nullptr);
      if (!result) {
        return ProfmanResult::kCopyAndUpdateErrorFailedToSaveProfile;
      }
      return updated ? ProfmanResult::kCopyAndUpdateSuccess : ProfmanResult::kCopyAndUpdateNoUpdate;
    } else {
      return ProfmanResult::kCopyAndUpdateErrorFailedToLoadProfile;
    }
  }

 private:
  static void ParseFdForCollection(const char* raw_option,
                                   std::string_view option_prefix,
                                   std::vector<int>* fds) {
    int fd;
    ParseUintOption(raw_option, option_prefix, &fd);
    fds->push_back(fd);
  }

  static void CloseAllFds(const std::vector<int>& fds, const char* descriptor) {
    for (size_t i = 0; i < fds.size(); i++) {
      if (close(fds[i]) < 0) {
        PLOG(WARNING) << "Failed to close descriptor for "
            << descriptor << " at index " << i << ": " << fds[i];
      }
    }
  }

  void LogCompletionTime() {
    static constexpr uint64_t kLogThresholdTime = MsToNs(100);  // 100ms
    uint64_t time_taken = NanoTime() - start_ns_;
    if (time_taken > kLogThresholdTime) {
      LOG(WARNING) << "profman took " << PrettyDuration(time_taken);
    }
  }

  std::vector<std::string> profile_files_;
  std::vector<int> profile_files_fd_;
  std::vector<std::string> dex_locations_;
  std::vector<std::string> apk_files_;
  std::vector<int> apks_fd_;
  std::string reference_profile_file_;
  int reference_profile_file_fd_;
  bool dump_only_;
  bool dump_classes_and_methods_;
  bool generate_boot_image_profile_;
  OutputProfileType output_profile_type_;
  int dump_output_to_fd_;
  BootImageOptions boot_image_options_;
  std::string test_profile_;
  std::string create_profile_from_file_;
  uint16_t test_profile_num_dex_;
  uint16_t test_profile_method_percerntage_;
  uint16_t test_profile_class_percentage_;
  uint32_t test_profile_seed_;
  uint64_t start_ns_;
  bool copy_and_update_profile_key_;
  ProfileAssistant::Options profile_assistant_options_;
  std::string boot_profile_out_path_;
  std::string preloaded_classes_out_path_;
};

std::ostream& operator<<(std::ostream& os, const ProfMan::InlineCacheSegment& ics) {
  return ics.Dump(os);
}

// See ProfmanResult for return codes.
static int profman(int argc, char** argv) {
  ProfMan profman;

  // Parse arguments. Argument mistakes will lead to exit(EXIT_FAILURE) in UsageError.
  profman.ParseArgs(argc, argv);

  // Initialize MemMap for ZipArchive::OpenFromFd.
  MemMap::Init();

  if (profman.ShouldGenerateTestProfile()) {
    return profman.GenerateTestProfile();
  }
  if (profman.ShouldOnlyDumpProfile()) {
    return profman.DumpProfileInfo();
  }
  if (profman.ShouldOnlyDumpClassesAndMethods()) {
    return profman.DumpClassesAndMethods();
  }
  if (profman.ShouldCreateProfile()) {
    if (profman.GetOutputProfileType() == OutputProfileType::kBprof) {
      return profman.CreateBootProfile();
    } else {
      return profman.CreateProfile();
    }
  }

  if (profman.ShouldCreateBootImageProfile()) {
    return profman.CreateBootImageProfile();
  }

  if (profman.ShouldCopyAndUpdateProfileKey()) {
    return profman.CopyAndUpdateProfileKey();
  }

  // Process profile information and assess if we need to do a profile guided compilation.
  // This operation involves I/O.
  return profman.ProcessProfiles();
}

}  // namespace art

int main(int argc, char **argv) {
  return art::profman(argc, argv);
}
