/*
 * 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 before and after the merge.");
  UsageError("      Deprecated. Use --force-merge-and-analyze instead.");
  UsageError("  --force-merge-and-analyze: performs a forced merge and analyzes if there is any");
  UsageError("      difference between before and after the merge.");
  UsageError("  --min-new-methods-percent-change=percentage between 0 and 100 (default 2)");
  UsageError("      the min percent of new methods to trigger a compilation.");
  UsageError("  --min-new-classes-percent-change=percentage between 0 and 100 (default 2)");
  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") {
        // For backward compatibility only.
        // TODO(jiakaiz): Remove this when S and T are no longer supported.
        profile_assistant_options_.SetForceMerge(true);
      } else if (option == "--force-merge-and-analyze") {
        profile_assistant_options_.SetForceMergeAndAnalyze(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;
      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) {
          ArtDexFileLoader dex_file_loader(apks_fd_[i], dex_locations_[i]);
          if (dex_file_loader.Open(/*verify=*/false,
                                   kVerifyChecksum,
                                   /*allow_no_dex_files=*/true,
                                   &error_msg,
                                   &dex_files_for_location)) {
          } else {
            LOG(ERROR) << "OpenZip failed for '" << dex_locations_[i] << "' " << error_msg;
            return false;
          }
      } else {
        File file(apk_files_[i], O_RDONLY, /*check_usage=*/false);
        if (file.Fd() < 0) {
          PLOG(ERROR) << "Unable to open '" << apk_files_[i] << "'";
          return false;
        }
        ArtDexFileLoader dex_file_loader(file.Release(), dex_locations_[i]);
        if (dex_file_loader.Open(/*verify=*/false,
                                 kVerifyChecksum,
                                 /*allow_no_dex_files=*/true,
                                 &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;
        // The target may be an array for methods defined in `j.l.Object`, such as `clone()`.
        size_t recv_end;
        if (UNLIKELY(t[0] == '[')) {
          recv_end = t.find_first_not_of('[', 1u);
          DCHECK_NE(recv_end, std::string_view::npos);
          if (t[recv_end] == 'L') {
            recv_end = t.find_first_of(';', recv_end + 1u);
            DCHECK_NE(recv_end, std::string_view::npos);
          } else {
            // Primitive array.
            DCHECK_NE(Primitive::GetType(t[recv_end]), Primitive::kPrimNot);
          }
        } else {
          DCHECK_EQ(t[0], 'L') << "Target is not a class? " << t;
          recv_end = t.find_first_of(';', 1u);
          DCHECK_NE(recv_end, std::string_view::npos);
        }
        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 matched = false;
      if (!profile.UpdateProfileKeys(dex_files, &matched)) {
        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 matched ? ProfmanResult::kCopyAndUpdateSuccess : ProfmanResult::kCopyAndUpdateNoMatch;
    } 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);
}
