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

#include <algorithm>
#include <optional>

#include "android-base/file.h"
#include "android-base/parseint.h"
#include "android-base/strings.h"
#include "art_field-inl.h"
#include "base/casts.h"
#include "base/dchecked_vector.h"
#include "base/file_utils.h"
#include "base/stl_util.h"
#include "base/systrace.h"
#include "class_linker.h"
#include "class_loader_utils.h"
#include "class_root-inl.h"
#include "dex/art_dex_file_loader.h"
#include "dex/dex_file.h"
#include "dex/dex_file_loader.h"
#include "handle_scope-inl.h"
#include "jni/jni_internal.h"
#include "mirror/class_loader-inl.h"
#include "mirror/object.h"
#include "mirror/object_array-alloc-inl.h"
#include "nativehelper/scoped_local_ref.h"
#include "oat/oat_file_assistant.h"
#include "obj_ptr-inl.h"
#include "runtime.h"
#include "scoped_thread_state_change-inl.h"
#include "thread.h"
#include "well_known_classes-inl.h"

namespace art HIDDEN {

static constexpr char kPathClassLoaderString[] = "PCL";
static constexpr char kDelegateLastClassLoaderString[] = "DLC";
static constexpr char kInMemoryDexClassLoaderString[] = "IMC";
static constexpr char kClassLoaderOpeningMark = '[';
static constexpr char kClassLoaderClosingMark = ']';
static constexpr char kClassLoaderSharedLibraryOpeningMark = '{';
static constexpr char kClassLoaderSharedLibraryClosingMark = '}';
static constexpr char kClassLoaderSharedLibrarySeparator = '#';
static constexpr char kClassLoaderSharedLibraryAfterSeparator = '~';
static constexpr char kClassLoaderSeparator = ';';
static constexpr char kClasspathSeparator = ':';
static constexpr char kDexFileChecksumSeparator = '*';
static constexpr char kInMemoryDexClassLoaderDexLocationMagic[] = "<unknown>";

ClassLoaderContext::ClassLoaderContext()
    : dex_files_state_(ContextDexFilesState::kDexFilesNotOpened), owns_the_dex_files_(true) {}

ClassLoaderContext::ClassLoaderContext(bool owns_the_dex_files)
    : dex_files_state_(ContextDexFilesState::kDexFilesOpened),
      owns_the_dex_files_(owns_the_dex_files) {}

// Utility method to add parent and shared libraries of `info` into
// the `work_list`.
static void AddToWorkList(ClassLoaderContext::ClassLoaderInfo* info,
                          std::vector<ClassLoaderContext::ClassLoaderInfo*>& work_list) {
  if (info->parent != nullptr) {
    work_list.push_back(info->parent.get());
  }
  for (size_t i = 0; i < info->shared_libraries.size(); ++i) {
    work_list.push_back(info->shared_libraries[i].get());
  }
  for (size_t i = 0; i < info->shared_libraries_after.size(); ++i) {
    work_list.push_back(info->shared_libraries_after[i].get());
  }
}

ClassLoaderContext::~ClassLoaderContext() {
  if (!owns_the_dex_files_ && class_loader_chain_ != nullptr) {
    // If the context does not own the dex/oat files release the unique pointers to
    // make sure we do not de-allocate them.
    std::vector<ClassLoaderInfo*> work_list;
    work_list.push_back(class_loader_chain_.get());
    while (!work_list.empty()) {
      ClassLoaderInfo* info = work_list.back();
      work_list.pop_back();
      for (std::unique_ptr<OatFile>& oat_file : info->opened_oat_files) {
        oat_file.release();  // NOLINT b/117926937
      }
      for (std::unique_ptr<const DexFile>& dex_file : info->opened_dex_files) {
        dex_file.release();  // NOLINT b/117926937
      }
      AddToWorkList(info, work_list);
    }
  }
}

std::unique_ptr<ClassLoaderContext> ClassLoaderContext::Default() { return Create(""); }

std::unique_ptr<ClassLoaderContext> ClassLoaderContext::Create(const std::string& spec) {
  std::unique_ptr<ClassLoaderContext> result(new ClassLoaderContext());
  if (result->Parse(spec)) {
    return result;
  } else {
    return nullptr;
  }
}

static size_t FindMatchingSharedLibraryCloseMarker(const std::string& spec,
                                                   size_t shared_library_open_index) {
  // Counter of opened shared library marker we've encountered so far.
  uint32_t counter = 1;
  // The index at which we're operating in the loop.
  uint32_t string_index = shared_library_open_index + 1;
  size_t shared_library_close = std::string::npos;
  while (counter != 0) {
    shared_library_close = spec.find_first_of(kClassLoaderSharedLibraryClosingMark, string_index);
    size_t shared_library_open =
        spec.find_first_of(kClassLoaderSharedLibraryOpeningMark, string_index);
    if (shared_library_close == std::string::npos) {
      // No matching closing marker. Return an error.
      break;
    }

    if ((shared_library_open == std::string::npos) ||
        (shared_library_close < shared_library_open)) {
      // We have seen a closing marker. Decrement the counter.
      --counter;
      // Move the search index forward.
      string_index = shared_library_close + 1;
    } else {
      // New nested opening marker. Increment the counter and move the search
      // index after the marker.
      ++counter;
      string_index = shared_library_open + 1;
    }
  }
  return shared_library_close;
}

// The expected format is:
// "ClassLoaderType1[ClasspathElem1*Checksum1:ClasspathElem2*Checksum2...]{ClassLoaderType2[...]}".
// The checksum part of the format is expected only if parse_cheksums is true.
std::unique_ptr<ClassLoaderContext::ClassLoaderInfo> ClassLoaderContext::ParseClassLoaderSpec(
    const std::string& class_loader_spec, bool parse_checksums) {
  ClassLoaderType class_loader_type = ExtractClassLoaderType(class_loader_spec);
  if (class_loader_type == kInvalidClassLoader) {
    return nullptr;
  }

  // InMemoryDexClassLoader's dex location is always bogus. Special-case it.
  if (class_loader_type == kInMemoryDexClassLoader) {
    if (parse_checksums) {
      // Make sure that OpenDexFiles() will never be attempted on this context
      // because the dex locations of IMC do not correspond to real files.
      CHECK(dex_files_state_ == kDexFilesNotOpened || dex_files_state_ == kDexFilesOpenFailed)
          << "Parsing spec not supported when context created from a ClassLoader object: "
          << "dex_files_state_=" << dex_files_state_;
      dex_files_state_ = kDexFilesOpenFailed;
    } else {
      // Checksums are not provided and dex locations themselves have no meaning
      // (although we keep them in the spec to simplify parsing). Treat this as
      // an unknown class loader.
      // We can hit this case if dex2oat is invoked with a spec containing IMC.
      // Because the dex file data is only available at runtime, we cannot proceed.
      return nullptr;
    }
  }

  const char* class_loader_type_str = GetClassLoaderTypeName(class_loader_type);
  size_t type_str_size = strlen(class_loader_type_str);

  CHECK_EQ(0, class_loader_spec.compare(0, type_str_size, class_loader_type_str));

  // Check the opening and closing markers.
  if (class_loader_spec[type_str_size] != kClassLoaderOpeningMark) {
    return nullptr;
  }
  if ((class_loader_spec[class_loader_spec.length() - 1] != kClassLoaderClosingMark) &&
      (class_loader_spec[class_loader_spec.length() - 1] != kClassLoaderSharedLibraryClosingMark)) {
    return nullptr;
  }

  size_t closing_index = class_loader_spec.find_first_of(kClassLoaderClosingMark);

  // At this point we know the format is ok; continue and extract the classpath.
  // Note that class loaders with an empty class path are allowed.
  std::string classpath =
      class_loader_spec.substr(type_str_size + 1, closing_index - type_str_size - 1);

  std::unique_ptr<ClassLoaderInfo> info(new ClassLoaderInfo(class_loader_type));

  if (!parse_checksums) {
    DCHECK(class_loader_type != kInMemoryDexClassLoader);
    Split(classpath, kClasspathSeparator, &info->classpath);
  } else {
    std::vector<std::string> classpath_elements;
    Split(classpath, kClasspathSeparator, &classpath_elements);
    for (const std::string& element : classpath_elements) {
      std::vector<std::string> dex_file_with_checksum;
      Split(element, kDexFileChecksumSeparator, &dex_file_with_checksum);
      if (dex_file_with_checksum.size() != 2) {
        return nullptr;
      }
      uint32_t checksum = 0;
      if (!android::base::ParseUint(dex_file_with_checksum[1].c_str(), &checksum)) {
        return nullptr;
      }
      if ((class_loader_type == kInMemoryDexClassLoader) &&
          (dex_file_with_checksum[0] != kInMemoryDexClassLoaderDexLocationMagic)) {
        return nullptr;
      }

      info->classpath.push_back(dex_file_with_checksum[0]);
      info->checksums.push_back(checksum);
    }
  }

  if ((class_loader_spec[class_loader_spec.length() - 1] == kClassLoaderSharedLibraryClosingMark) &&
      (class_loader_spec[class_loader_spec.length() - 2] != kClassLoaderSharedLibraryOpeningMark)) {
    // Non-empty list of shared libraries.
    size_t start_index = class_loader_spec.find_first_of(kClassLoaderSharedLibraryOpeningMark);
    if (start_index == std::string::npos) {
      return nullptr;
    }
    std::string shared_libraries_spec =
        class_loader_spec.substr(start_index + 1, class_loader_spec.length() - start_index - 2);
    std::vector<std::string> shared_libraries;
    size_t cursor = 0;
    while (cursor != shared_libraries_spec.length()) {
      bool is_after = false;
      size_t shared_library_separator =
          shared_libraries_spec.find_first_of(kClassLoaderSharedLibrarySeparator, cursor);
      size_t shared_library_open =
          shared_libraries_spec.find_first_of(kClassLoaderSharedLibraryOpeningMark, cursor);
      std::string shared_library_spec;
      if (shared_library_separator == std::string::npos) {
        // Only one shared library, for example:
        // PCL[...]
        if (shared_libraries_spec[cursor] == kClassLoaderSharedLibraryAfterSeparator) {
          // This library was marked to be loaded after the dex path
          is_after = true;
          // Pass the shared library after separator marker.
          ++cursor;
        }
        shared_library_spec =
            shared_libraries_spec.substr(cursor, shared_libraries_spec.length() - cursor);
        cursor = shared_libraries_spec.length();
      } else if ((shared_library_open == std::string::npos) ||
                 (shared_library_open > shared_library_separator)) {
        // We found a shared library without nested shared libraries, for example:
        // PCL[...]#PCL[...]{...}
        if (shared_libraries_spec[cursor] == kClassLoaderSharedLibraryAfterSeparator) {
          // This library was marked to be loaded after the dex path
          is_after = true;
          // Pass the shared library after separator marker.
          ++cursor;
        }
        shared_library_spec =
            shared_libraries_spec.substr(cursor, shared_library_separator - cursor);
        cursor = shared_library_separator + 1;
      } else {
        // The shared library contains nested shared libraries. Find the matching closing shared
        // marker for it.
        size_t closing_marker =
            FindMatchingSharedLibraryCloseMarker(shared_libraries_spec, shared_library_open);
        if (closing_marker == std::string::npos) {
          // No matching closing marker, return an error.
          return nullptr;
        }
        if (shared_libraries_spec[cursor] == kClassLoaderSharedLibraryAfterSeparator) {
          // This library was marked to be loaded after the dex path
          is_after = true;
          // Pass the shared library after separator marker.
          ++cursor;
        }
        shared_library_spec = shared_libraries_spec.substr(cursor, closing_marker + 1 - cursor);
        cursor = closing_marker + 1;
        if (cursor != shared_libraries_spec.length() &&
            shared_libraries_spec[cursor] == kClassLoaderSharedLibrarySeparator) {
          // Pass the shared library separator marker.
          ++cursor;
        }
      }

      std::unique_ptr<ClassLoaderInfo> shared_library_info(
          ParseInternal(shared_library_spec, parse_checksums));
      if (shared_library_info == nullptr) {
        return nullptr;
      }
      if (is_after) {
        info->shared_libraries_after.push_back(std::move(shared_library_info));
      } else {
        info->shared_libraries.push_back(std::move(shared_library_info));
      }
    }
  }

  return info;
}

// Extracts the class loader type from the given spec.
// Return ClassLoaderContext::kInvalidClassLoader if the class loader type is not
// recognized.
ClassLoaderContext::ClassLoaderType ClassLoaderContext::ExtractClassLoaderType(
    const std::string& class_loader_spec) {
  const ClassLoaderType kValidTypes[] = {
      kPathClassLoader, kDelegateLastClassLoader, kInMemoryDexClassLoader};
  for (const ClassLoaderType& type : kValidTypes) {
    const char* type_str = GetClassLoaderTypeName(type);
    if (class_loader_spec.compare(0, strlen(type_str), type_str) == 0) {
      return type;
    }
  }
  return kInvalidClassLoader;
}

// The format: ClassLoaderType1[ClasspathElem1:ClasspathElem2...];ClassLoaderType2[...]...
// ClassLoaderType is either "PCL" (PathClassLoader) or "DLC" (DelegateLastClassLoader).
// ClasspathElem is the path of dex/jar/apk file.
bool ClassLoaderContext::Parse(const std::string& spec, bool parse_checksums) {
  if (spec.empty()) {
    // By default we load the dex files in a PathClassLoader.
    // So an empty spec is equivalent to an empty PathClassLoader (this happens when running
    // tests)
    class_loader_chain_.reset(new ClassLoaderInfo(kPathClassLoader));
    return true;
  }

  CHECK(class_loader_chain_ == nullptr);
  class_loader_chain_.reset(ParseInternal(spec, parse_checksums));
  return class_loader_chain_ != nullptr;
}

ClassLoaderContext::ClassLoaderInfo* ClassLoaderContext::ParseInternal(const std::string& spec,
                                                                       bool parse_checksums) {
  CHECK(!spec.empty());
  std::string remaining = spec;
  std::unique_ptr<ClassLoaderInfo> first(nullptr);
  ClassLoaderInfo* previous_iteration = nullptr;
  while (!remaining.empty()) {
    std::string class_loader_spec;
    size_t first_class_loader_separator = remaining.find_first_of(kClassLoaderSeparator);
    size_t first_shared_library_open =
        remaining.find_first_of(kClassLoaderSharedLibraryOpeningMark);
    if (first_class_loader_separator == std::string::npos) {
      // Only one class loader, for example:
      // PCL[...]
      class_loader_spec = remaining;
      remaining = "";
    } else if ((first_shared_library_open == std::string::npos) ||
               (first_shared_library_open > first_class_loader_separator)) {
      // We found a class loader spec without shared libraries, for example:
      // PCL[...];PCL[...]{...}
      class_loader_spec = remaining.substr(0, first_class_loader_separator);
      remaining = remaining.substr(first_class_loader_separator + 1,
                                   remaining.size() - first_class_loader_separator - 1);
    } else {
      // The class loader spec contains shared libraries. Find the matching closing
      // shared library marker for it.

      size_t shared_library_close =
          FindMatchingSharedLibraryCloseMarker(remaining, first_shared_library_open);
      if (shared_library_close == std::string::npos) {
        LOG(ERROR) << "Invalid class loader spec: " << class_loader_spec;
        return nullptr;
      }
      class_loader_spec = remaining.substr(0, shared_library_close + 1);

      // Compute the remaining string to analyze.
      if (remaining.size() == shared_library_close + 1) {
        remaining = "";
      } else if ((remaining.size() == shared_library_close + 2) ||
                 (remaining.at(shared_library_close + 1) != kClassLoaderSeparator)) {
        LOG(ERROR) << "Invalid class loader spec: " << class_loader_spec;
        return nullptr;
      } else {
        remaining =
            remaining.substr(shared_library_close + 2, remaining.size() - shared_library_close - 2);
      }
    }

    std::unique_ptr<ClassLoaderInfo> info =
        ParseClassLoaderSpec(class_loader_spec, parse_checksums);
    if (info == nullptr) {
      LOG(ERROR) << "Invalid class loader spec: " << class_loader_spec;
      return nullptr;
    }
    if (first == nullptr) {
      first = std::move(info);
      previous_iteration = first.get();
    } else {
      CHECK(previous_iteration != nullptr);
      previous_iteration->parent = std::move(info);
      previous_iteration = previous_iteration->parent.get();
    }
  }
  return first.release();
}

// Opens requested class path files and appends them to opened_dex_files. If the dex files have
// been stripped, this opens them from their oat files (which get added to opened_oat_files).
bool ClassLoaderContext::OpenDexFiles(const std::string& classpath_dir,
                                      const std::vector<int>& fds,
                                      bool only_read_checksums) {
  switch (dex_files_state_) {
    case kDexFilesNotOpened:
      break;  // files not opened, continue.
    case kDexFilesOpenFailed:
      return false;  // previous attempt failed.
    case kDexFilesOpened:
      return true;  // previous attempt succeed.
    case kDexFilesChecksumsRead:
      if (only_read_checksums) {
        return true;  // we already read the checksums.
      } else {
        break;  // we already read the checksums but have to open the dex files; continue.
      }
  }

  // Assume we can open the files. If not, we will adjust as we go.
  dex_files_state_ = only_read_checksums ? kDexFilesChecksumsRead : kDexFilesOpened;

  // Note that we try to open all dex files even if some fail.
  // We may get resource-only apks which we cannot load.
  // TODO(calin): Refine the dex opening interface to be able to tell if an archive contains
  // no dex files. So that we can distinguish the real failures...
  std::vector<ClassLoaderInfo*> work_list;
  if (class_loader_chain_ == nullptr) {
    return true;
  }
  work_list.push_back(class_loader_chain_.get());
  size_t dex_file_index = 0;
  while (!work_list.empty()) {
    ClassLoaderInfo* info = work_list.back();
    work_list.pop_back();
    DCHECK(info->type != kInMemoryDexClassLoader) << __FUNCTION__ << " not supported for IMC";

    // Holds the dex locations for the classpath files we've opened.
    std::vector<std::string> dex_locations;
    // Holds the checksums for the classpath files we've opened.
    std::vector<uint32_t> dex_checksums;

    for (const std::string& cp_elem : info->classpath) {
      // If path is relative, append it to the provided base directory.
      std::string location = cp_elem;
      if (location[0] != '/' && !classpath_dir.empty()) {
        location =
            ART_FORMAT("{}{}{}", classpath_dir, classpath_dir.back() == '/' ? "" : "/", location);
      }

      // If file descriptors were provided for the class loader context dex paths,
      // get the descriptor which corresponds to this dex path. We assume the `fds`
      // vector follows the same order as a flattened class loader context.
      File file;
      if (!fds.empty()) {
        if (dex_file_index >= fds.size()) {
          LOG(WARNING) << "Number of FDs is smaller than number of dex files in the context";
          dex_files_state_ = kDexFilesOpenFailed;
          return false;
        }

        file = File(fds[dex_file_index++], /*check_usage=*/false);
        DCHECK(file.IsValid());
      }

      std::string error_msg;
      std::optional<uint32_t> dex_checksum;
      if (only_read_checksums) {
        bool zip_file_only_contains_uncompress_dex;
        ArtDexFileLoader dex_file_loader(&file, location);
        if (!dex_file_loader.GetMultiDexChecksum(
                &dex_checksum, &error_msg, &zip_file_only_contains_uncompress_dex)) {
          LOG(WARNING) << "Could not get dex checksums for location " << location
                       << ", fd=" << file.Fd();
          dex_files_state_ = kDexFilesOpenFailed;
        }
        file.Release();  // Don't close the file yet (we have only read the checksum).
      } else {
        // When opening the dex files from the context we expect their checksum to match their
        // contents. So pass true to verify_checksum.
        // We don't need to do structural dex file verification, we only need to
        // check the checksum, so pass false to verify.
        size_t i = info->opened_dex_files.size();
        ArtDexFileLoader dex_file_loader(&file, location);
        if (!dex_file_loader.Open(/*verify=*/false,
                                  /*verify_checksum=*/true,
                                  &error_msg,
                                  &info->opened_dex_files)) {
          LOG(WARNING) << "Could not open dex files for location " << location
                       << ", fd=" << file.Fd();
          dex_files_state_ = kDexFilesOpenFailed;
        } else {
          dex_checksum = DexFileLoader::GetMultiDexChecksum(info->opened_dex_files, &i);
          DCHECK_EQ(i, info->opened_dex_files.size());
        }
      }
      if (dex_checksum.has_value()) {
        dex_locations.push_back(location);
        dex_checksums.push_back(dex_checksum.value());
      }
    }

    // We finished opening the dex files from the classpath.
    // Now update the classpath and the checksum with the locations of the dex files.
    //
    // We do this because initially the classpath contains the paths of the dex files; and
    // some of them might be multi-dexes. So in order to have a consistent view we replace all the
    // file paths with the actual dex locations being loaded.
    // This will allow the context to VerifyClassLoaderContextMatch which expects or multidex
    // location in the class paths.
    // Note that this will also remove the paths that could not be opened.
    info->original_classpath = std::move(info->classpath);
    DCHECK(dex_locations.size() == dex_checksums.size());
    info->classpath = std::move(dex_locations);
    info->checksums = std::move(dex_checksums);
    AddToWorkList(info, work_list);
  }

  // Check that if file descriptors were provided, there were exactly as many
  // as we have encountered while iterating over this class loader context.
  if (dex_file_index != fds.size()) {
    LOG(WARNING) << fds.size() << " FDs provided but only " << dex_file_index
                 << " dex files are in the class loader context";
    dex_files_state_ = kDexFilesOpenFailed;
  }

  return dex_files_state_ != kDexFilesOpenFailed;
}

bool ClassLoaderContext::RemoveLocationsFromClassPaths(
    const dchecked_vector<std::string>& locations) {
  CHECK_EQ(dex_files_state_, kDexFilesNotOpened)
      << "RemoveLocationsFromClasspaths cannot be call after OpenDexFiles";

  if (class_loader_chain_ == nullptr) {
    return false;
  }

  std::set<std::string> canonical_locations;
  for (const std::string& location : locations) {
    canonical_locations.insert(DexFileLoader::GetDexCanonicalLocation(location.c_str()));
  }
  bool removed_locations = false;
  std::vector<ClassLoaderInfo*> work_list;
  work_list.push_back(class_loader_chain_.get());
  while (!work_list.empty()) {
    ClassLoaderInfo* info = work_list.back();
    work_list.pop_back();
    size_t initial_size = info->classpath.size();
    auto kept_it = std::remove_if(info->classpath.begin(),
                                  info->classpath.end(),
                                  [canonical_locations](const std::string& location) {
                                    return ContainsElement(
                                        canonical_locations,
                                        DexFileLoader::GetDexCanonicalLocation(location.c_str()));
                                  });
    info->classpath.erase(kept_it, info->classpath.end());
    if (initial_size != info->classpath.size()) {
      removed_locations = true;
    }
    AddToWorkList(info, work_list);
  }
  return removed_locations;
}

std::string ClassLoaderContext::EncodeContextForDex2oat(const std::string& base_dir) const {
  return EncodeContext(base_dir, /*for_dex2oat=*/true, /*stored_context=*/nullptr);
}

std::string ClassLoaderContext::EncodeContextForOatFile(const std::string& base_dir,
                                                        ClassLoaderContext* stored_context) const {
  return EncodeContext(base_dir, /*for_dex2oat=*/false, stored_context);
}

std::map<std::string, std::string> ClassLoaderContext::EncodeClassPathContexts(
    const std::string& base_dir) const {
  CheckDexFilesOpened("EncodeClassPathContexts");
  if (class_loader_chain_ == nullptr) {
    return std::map<std::string, std::string>{};
  }

  std::map<std::string, std::string> results;
  std::vector<std::string> dex_locations;
  std::vector<uint32_t> checksums;
  dex_locations.reserve(class_loader_chain_->original_classpath.size());

  std::ostringstream encoded_libs_and_parent_stream;
  EncodeSharedLibAndParent(*class_loader_chain_,
                           base_dir,
                           /*for_dex2oat=*/true,
                           /*stored_info=*/nullptr,
                           encoded_libs_and_parent_stream);
  std::string encoded_libs_and_parent(encoded_libs_and_parent_stream.str());

  std::set<std::string> seen_locations;
  for (const std::string& path : class_loader_chain_->classpath) {
    // The classpath will contain multiple entries for multidex files, so make sure this is the
    // first time we're seeing this file.
    const std::string base_location(DexFileLoader::GetBaseLocation(path));
    if (!seen_locations.insert(base_location).second) {
      continue;
    }

    std::ostringstream out;
    EncodeClassPath(base_dir, dex_locations, checksums, class_loader_chain_->type, out);
    out << encoded_libs_and_parent;
    results.emplace(base_location, out.str());

    dex_locations.push_back(base_location);
  }

  return results;
}

std::string ClassLoaderContext::EncodeContext(const std::string& base_dir,
                                              bool for_dex2oat,
                                              ClassLoaderContext* stored_context) const {
  CheckDexFilesOpened("EncodeContextForOatFile");

  if (stored_context != nullptr) {
    DCHECK_EQ(GetParentChainSize(), stored_context->GetParentChainSize());
  }

  std::ostringstream out;
  if (class_loader_chain_ == nullptr) {
    // We can get in this situation if the context was created with a class path containing the
    // source dex files which were later removed (happens during run-tests).
    out << GetClassLoaderTypeName(kPathClassLoader) << kClassLoaderOpeningMark
        << kClassLoaderClosingMark;
    return out.str();
  }

  EncodeContextInternal(
      *class_loader_chain_,
      base_dir,
      for_dex2oat,
      (stored_context == nullptr ? nullptr : stored_context->class_loader_chain_.get()),
      out);
  return out.str();
}

void ClassLoaderContext::EncodeClassPath(const std::string& base_dir,
                                         const std::vector<std::string>& dex_locations,
                                         const std::vector<uint32_t>& checksums,
                                         ClassLoaderType type,
                                         std::ostringstream& out) const {
  CHECK(checksums.empty() || dex_locations.size() == checksums.size());
  out << GetClassLoaderTypeName(type);
  out << kClassLoaderOpeningMark;
  const size_t len = dex_locations.size();
  for (size_t k = 0; k < len; k++) {
    const std::string& location = dex_locations[k];
    if (k > 0) {
      out << kClasspathSeparator;
    }
    if (type == kInMemoryDexClassLoader) {
      out << kInMemoryDexClassLoaderDexLocationMagic;
    } else if (!base_dir.empty() && location.substr(0, base_dir.length()) == base_dir) {
      // Find paths that were relative and convert them back from absolute.
      out << location.substr(base_dir.length() + 1).c_str();
    } else {
      out << location.c_str();
    }
    if (!checksums.empty()) {
      out << kDexFileChecksumSeparator;
      out << checksums[k];
    }
  }
  out << kClassLoaderClosingMark;
}

void ClassLoaderContext::EncodeContextInternal(const ClassLoaderInfo& info,
                                               const std::string& base_dir,
                                               bool for_dex2oat,
                                               ClassLoaderInfo* stored_info,
                                               std::ostringstream& out) const {
  std::vector<std::string> locations;
  std::vector<uint32_t> checksums;
  std::set<std::string> seen_locations;
  SafeMap<std::string, std::string> remap;
  if (stored_info != nullptr) {
    for (size_t k = 0; k < info.original_classpath.size(); ++k) {
      // Note that we don't care if the same name appears twice.
      remap.Put(info.original_classpath[k], stored_info->classpath[k]);
    }
  }

  DCHECK_EQ(info.classpath.size(), info.checksums.size());
  for (size_t i = 0; i < info.classpath.size(); i++) {
    if (for_dex2oat) {
      // De-duplicate locations.
      bool new_insert = seen_locations.insert(info.classpath[i]).second;
      if (!new_insert) {
        continue;
      }
    }

    std::string location = info.classpath[i];
    // If there is a stored class loader remap, fix up the multidex strings.
    if (!remap.empty()) {
      auto it = remap.find(location);
      CHECK(it != remap.end()) << location;
      location = it->second;
    }
    locations.emplace_back(std::move(location));

    // dex2oat does not need the checksums.
    if (!for_dex2oat) {
      checksums.push_back(info.checksums[i]);
    }
  }
  EncodeClassPath(base_dir, locations, checksums, info.type, out);
  EncodeSharedLibAndParent(info, base_dir, for_dex2oat, stored_info, out);
}

void ClassLoaderContext::EncodeSharedLibAndParent(const ClassLoaderInfo& info,
                                                  const std::string& base_dir,
                                                  bool for_dex2oat,
                                                  ClassLoaderInfo* stored_info,
                                                  std::ostringstream& out) const {
  if (!info.shared_libraries.empty() || !info.shared_libraries_after.empty()) {
    out << kClassLoaderSharedLibraryOpeningMark;
    for (uint32_t i = 0; i < info.shared_libraries.size(); ++i) {
      if (i > 0) {
        out << kClassLoaderSharedLibrarySeparator;
      }
      EncodeContextInternal(
          *info.shared_libraries[i].get(),
          base_dir,
          for_dex2oat,
          (stored_info == nullptr ? nullptr : stored_info->shared_libraries[i].get()),
          out);
    }

    for (uint32_t i = 0; i < info.shared_libraries_after.size(); ++i) {
      if (i > 0 || !info.shared_libraries.empty()) {
        out << kClassLoaderSharedLibrarySeparator;
      }
      out << kClassLoaderSharedLibraryAfterSeparator;
      EncodeContextInternal(
          *info.shared_libraries_after[i].get(),
          base_dir,
          for_dex2oat,
          (stored_info == nullptr ? nullptr : stored_info->shared_libraries_after[i].get()),
          out);
    }

    out << kClassLoaderSharedLibraryClosingMark;
  }
  if (info.parent != nullptr) {
    out << kClassLoaderSeparator;
    EncodeContextInternal(*info.parent.get(),
                          base_dir,
                          for_dex2oat,
                          (stored_info == nullptr ? nullptr : stored_info->parent.get()),
                          out);
  }
}

// Returns the WellKnownClass for the given class loader type.
static ObjPtr<mirror::Class> GetClassLoaderClass(ClassLoaderContext::ClassLoaderType type)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  switch (type) {
    case ClassLoaderContext::kPathClassLoader:
      return WellKnownClasses::dalvik_system_PathClassLoader.Get();
    case ClassLoaderContext::kDelegateLastClassLoader:
      return WellKnownClasses::dalvik_system_DelegateLastClassLoader.Get();
    case ClassLoaderContext::kInMemoryDexClassLoader:
      return WellKnownClasses::dalvik_system_InMemoryDexClassLoader.Get();
    case ClassLoaderContext::kInvalidClassLoader:
      break;  // will fail after the switch.
  }
  LOG(FATAL) << "Invalid class loader type " << type;
  UNREACHABLE();
}

static std::string FlattenClasspath(const std::vector<std::string>& classpath) {
  return android::base::Join(classpath, ':');
}

static ObjPtr<mirror::ClassLoader> CreateClassLoaderInternal(
    Thread* self,
    ScopedObjectAccess& soa,
    const ClassLoaderContext::ClassLoaderInfo& info,
    bool for_shared_library,
    VariableSizedHandleScope& map_scope,
    std::map<std::string, Handle<mirror::ClassLoader>>& canonicalized_libraries,
    bool add_compilation_sources,
    const std::vector<const DexFile*>& compilation_sources) REQUIRES_SHARED(Locks::mutator_lock_) {
  if (for_shared_library) {
    // Check if the shared library has already been created.
    auto search = canonicalized_libraries.find(FlattenClasspath(info.classpath));
    if (search != canonicalized_libraries.end()) {
      return search->second.Get();
    }
  }

  StackHandleScope<4> hs(self);
  MutableHandle<mirror::ObjectArray<mirror::ClassLoader>> libraries(
      hs.NewHandle<mirror::ObjectArray<mirror::ClassLoader>>(nullptr));
  MutableHandle<mirror::ObjectArray<mirror::ClassLoader>> libraries_after(
      hs.NewHandle<mirror::ObjectArray<mirror::ClassLoader>>(nullptr));

  if (!info.shared_libraries.empty()) {
    libraries.Assign(mirror::ObjectArray<mirror::ClassLoader>::Alloc(
        self,
        GetClassRoot<mirror::ObjectArray<mirror::ClassLoader>>(),
        info.shared_libraries.size()));
    for (uint32_t i = 0; i < info.shared_libraries.size(); ++i) {
      // We should only add the compilation sources to the first class loader.
      libraries->Set(i,
                     CreateClassLoaderInternal(self,
                                               soa,
                                               *info.shared_libraries[i].get(),
                                               /* for_shared_library= */ true,
                                               map_scope,
                                               canonicalized_libraries,
                                               /* add_compilation_sources= */ false,
                                               compilation_sources));
    }
  }

  if (!info.shared_libraries_after.empty()) {
    libraries_after.Assign(mirror::ObjectArray<mirror::ClassLoader>::Alloc(
        self,
        GetClassRoot<mirror::ObjectArray<mirror::ClassLoader>>(),
        info.shared_libraries_after.size()));
    for (uint32_t i = 0; i < info.shared_libraries_after.size(); ++i) {
      // We should only add the compilation sources to the first class loader.
      libraries_after->Set(i,
                           CreateClassLoaderInternal(self,
                                                     soa,
                                                     *info.shared_libraries_after[i].get(),
                                                     /* for_shared_library= */ true,
                                                     map_scope,
                                                     canonicalized_libraries,
                                                     /* add_compilation_sources= */ false,
                                                     compilation_sources));
    }
  }

  MutableHandle<mirror::ClassLoader> parent = hs.NewHandle<mirror::ClassLoader>(nullptr);
  if (info.parent != nullptr) {
    // We should only add the compilation sources to the first class loader.
    parent.Assign(CreateClassLoaderInternal(self,
                                            soa,
                                            *info.parent.get(),
                                            /* for_shared_library= */ false,
                                            map_scope,
                                            canonicalized_libraries,
                                            /* add_compilation_sources= */ false,
                                            compilation_sources));
  }
  std::vector<const DexFile*> class_path_files = MakeNonOwningPointerVector(info.opened_dex_files);
  if (add_compilation_sources) {
    // For the first class loader, its classpath comes first, followed by compilation sources.
    // This ensures that whenever we need to resolve classes from it the classpath elements
    // come first.
    class_path_files.insert(
        class_path_files.end(), compilation_sources.begin(), compilation_sources.end());
  }
  Handle<mirror::Class> loader_class = hs.NewHandle<mirror::Class>(GetClassLoaderClass(info.type));
  ObjPtr<mirror::ClassLoader> loader =
      Runtime::Current()->GetClassLinker()->CreateWellKnownClassLoader(
          self, class_path_files, loader_class, parent, libraries, libraries_after);
  if (for_shared_library) {
    canonicalized_libraries[FlattenClasspath(info.classpath)] =
        map_scope.NewHandle<mirror::ClassLoader>(loader);
  }
  return loader;
}

jobject ClassLoaderContext::CreateClassLoader(
    const std::vector<const DexFile*>& compilation_sources) const {
  CheckDexFilesOpened("CreateClassLoader");

  Thread* self = Thread::Current();
  ScopedObjectAccess soa(self);

  CHECK(class_loader_chain_ != nullptr);

  // Create a map of canonicalized shared libraries. As we're holding objects,
  // we're creating a variable size handle scope to put handles in the map.
  VariableSizedHandleScope map_scope(self);
  std::map<std::string, Handle<mirror::ClassLoader>> canonicalized_libraries;

  // Create the class loader.
  ObjPtr<mirror::ClassLoader> loader =
      CreateClassLoaderInternal(self,
                                soa,
                                *class_loader_chain_.get(),
                                /* for_shared_library= */ false,
                                map_scope,
                                canonicalized_libraries,
                                /* add_compilation_sources= */ true,
                                compilation_sources);
  // Make it a global ref and return.
  ScopedLocalRef<jobject> local_ref(soa.Env(), soa.Env()->AddLocalReference<jobject>(loader));
  return soa.Env()->NewGlobalRef(local_ref.get());
}

std::vector<const DexFile*> ClassLoaderContext::FlattenOpenedDexFiles() const {
  CheckDexFilesOpened("FlattenOpenedDexFiles");

  std::vector<const DexFile*> result;
  if (class_loader_chain_ == nullptr) {
    return result;
  }
  std::vector<ClassLoaderInfo*> work_list;
  work_list.push_back(class_loader_chain_.get());
  while (!work_list.empty()) {
    ClassLoaderInfo* info = work_list.back();
    work_list.pop_back();
    for (const std::unique_ptr<const DexFile>& dex_file : info->opened_dex_files) {
      result.push_back(dex_file.get());
    }
    AddToWorkList(info, work_list);
  }
  return result;
}

std::vector<std::string> ClassLoaderContext::FlattenDexPaths() const {
  std::vector<std::string> result;

  if (class_loader_chain_ == nullptr) {
    return result;
  }

  std::vector<ClassLoaderInfo*> work_list;
  work_list.push_back(class_loader_chain_.get());
  while (!work_list.empty()) {
    ClassLoaderInfo* info = work_list.back();
    work_list.pop_back();
    for (const std::string& dex_path : info->classpath) {
      result.push_back(dex_path);
    }
    AddToWorkList(info, work_list);
  }
  return result;
}

const char* ClassLoaderContext::GetClassLoaderTypeName(ClassLoaderType type) {
  switch (type) {
    case kPathClassLoader:
      return kPathClassLoaderString;
    case kDelegateLastClassLoader:
      return kDelegateLastClassLoaderString;
    case kInMemoryDexClassLoader:
      return kInMemoryDexClassLoaderString;
    default:
      LOG(FATAL) << "Invalid class loader type " << type;
      UNREACHABLE();
  }
}

void ClassLoaderContext::CheckDexFilesOpened(const std::string& calling_method) const {
  CHECK_NE(dex_files_state_, kDexFilesNotOpened)
      << "Dex files were not successfully opened before the call to " << calling_method
      << "status=" << dex_files_state_;
}

// Collects the dex files from the give Java dex_file object. Only the dex files with
// at least 1 class are collected. If a null java_dex_file is passed this method does nothing.
static bool CollectDexFilesFromJavaDexFile(ObjPtr<mirror::Object> java_dex_file,
                                           ArtField* const cookie_field,
                                           std::vector<const DexFile*>* out_dex_files)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  if (java_dex_file == nullptr) {
    return true;
  }
  // On the Java side, the dex files are stored in the cookie field.
  ObjPtr<mirror::LongArray> long_array = cookie_field->GetObject(java_dex_file)->AsLongArray();
  if (long_array == nullptr) {
    // This should never happen so log a warning.
    LOG(ERROR) << "Unexpected null cookie";
    return false;
  }
  int32_t long_array_size = long_array->GetLength();
  // Index 0 from the long array stores the oat file. The dex files start at index 1.
  for (int32_t j = 1; j < long_array_size; ++j) {
    const DexFile* cp_dex_file =
        reinterpret_cast64<const DexFile*>(long_array->GetWithoutChecks(j));
    if (cp_dex_file != nullptr && cp_dex_file->NumClassDefs() > 0) {
      // TODO(calin): It's unclear why the dex files with no classes are skipped here and when
      // cp_dex_file can be null.
      out_dex_files->push_back(cp_dex_file);
    }
  }
  return true;
}

// Collects all the dex files loaded by the given class loader.
// Returns true for success or false if an unexpected state is discovered (e.g. a null dex cookie,
// a null list of dex elements or a null dex element).
static bool CollectDexFilesFromSupportedClassLoader(Thread* self,
                                                    Handle<mirror::ClassLoader> class_loader,
                                                    std::vector<const DexFile*>* out_dex_files)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  CHECK(IsInstanceOfBaseDexClassLoader(class_loader));

  // All supported class loaders inherit from BaseDexClassLoader.
  // We need to get the DexPathList and loop through it.
  ArtField* const cookie_field = WellKnownClasses::dalvik_system_DexFile_cookie;
  ArtField* const dex_file_field = WellKnownClasses::dalvik_system_DexPathList__Element_dexFile;
  ObjPtr<mirror::Object> dex_path_list =
      WellKnownClasses::dalvik_system_BaseDexClassLoader_pathList->GetObject(class_loader.Get());
  CHECK(cookie_field != nullptr);
  CHECK(dex_file_field != nullptr);
  if (dex_path_list == nullptr) {
    // This may be null if the current class loader is under construction and it does not
    // have its fields setup yet.
    return true;
  }
  // DexPathList has an array dexElements of Elements[] which each contain a dex file.
  ObjPtr<mirror::Object> dex_elements_obj =
      WellKnownClasses::dalvik_system_DexPathList_dexElements->GetObject(dex_path_list);
  // Loop through each dalvik.system.DexPathList$Element's dalvik.system.DexFile and look
  // at the mCookie which is a DexFile vector.
  if (dex_elements_obj == nullptr) {
    // TODO(calin): It's unclear if we should just assert here. For now be prepared for the worse
    // and assume we have no elements.
    return true;
  } else {
    StackHandleScope<1> hs(self);
    Handle<mirror::ObjectArray<mirror::Object>> dex_elements(
        hs.NewHandle(dex_elements_obj->AsObjectArray<mirror::Object>()));
    for (auto element : dex_elements.Iterate<mirror::Object>()) {
      if (element == nullptr) {
        // Should never happen, log an error and break.
        // TODO(calin): It's unclear if we should just assert here.
        // This code was propagated to oat_file_manager from the class linker where it would
        // throw a NPE. For now, return false which will mark this class loader as unsupported.
        LOG(ERROR) << "Unexpected null in the dex element list";
        return false;
      }
      ObjPtr<mirror::Object> dex_file = dex_file_field->GetObject(element);
      if (!CollectDexFilesFromJavaDexFile(dex_file, cookie_field, out_dex_files)) {
        return false;
      }
    }
  }

  return true;
}

static bool GetDexFilesFromDexElementsArray(
    Handle<mirror::ObjectArray<mirror::Object>> dex_elements,
    std::vector<const DexFile*>* out_dex_files) REQUIRES_SHARED(Locks::mutator_lock_) {
  DCHECK(dex_elements != nullptr);

  ArtField* const cookie_field = WellKnownClasses::dalvik_system_DexFile_cookie;
  ArtField* const dex_file_field = WellKnownClasses::dalvik_system_DexPathList__Element_dexFile;
  const ObjPtr<mirror::Class> element_class =
      WellKnownClasses::dalvik_system_DexPathList__Element.Get();
  const ObjPtr<mirror::Class> dexfile_class = WellKnownClasses::dalvik_system_DexFile.Get();

  for (auto element : dex_elements.Iterate<mirror::Object>()) {
    // We can hit a null element here because this is invoked with a partially filled dex_elements
    // array from DexPathList. DexPathList will open each dex sequentially, each time passing the
    // list of dex files which were opened before.
    if (element == nullptr) {
      continue;
    }

    // We support this being dalvik.system.DexPathList$Element and dalvik.system.DexFile.
    // TODO(calin): Code caried over oat_file_manager: supporting both classes seem to be
    // a historical glitch. All the java code opens dex files using an array of Elements.
    ObjPtr<mirror::Object> dex_file;
    if (element_class == element->GetClass()) {
      dex_file = dex_file_field->GetObject(element);
    } else if (dexfile_class == element->GetClass()) {
      dex_file = element;
    } else {
      LOG(ERROR) << "Unsupported element in dex_elements: "
                 << mirror::Class::PrettyClass(element->GetClass());
      return false;
    }

    if (!CollectDexFilesFromJavaDexFile(dex_file, cookie_field, out_dex_files)) {
      return false;
    }
  }
  return true;
}

// Adds the `class_loader` info to the `context`.
// The dex file present in `dex_elements` array (if not null) will be added at the end of
// the classpath.
// This method is recursive (w.r.t. the class loader parent) and will stop once it reaches the
// BootClassLoader. Note that the class loader chain is expected to be short.
bool ClassLoaderContext::CreateInfoFromClassLoader(
    ScopedObjectAccessAlreadyRunnable& soa,
    Handle<mirror::ClassLoader> class_loader,
    Handle<mirror::ObjectArray<mirror::Object>> dex_elements,
    ClassLoaderInfo* child_info,
    bool is_shared_library,
    bool is_after) REQUIRES_SHARED(Locks::mutator_lock_) {
  if (ClassLinker::IsBootClassLoader(class_loader.Get())) {
    // Nothing to do for the boot class loader as we don't add its dex files to the context.
    return true;
  }

  ClassLoaderContext::ClassLoaderType type;
  if (IsPathOrDexClassLoader(class_loader)) {
    type = kPathClassLoader;
  } else if (IsDelegateLastClassLoader(class_loader)) {
    type = kDelegateLastClassLoader;
  } else if (IsInMemoryDexClassLoader(class_loader)) {
    type = kInMemoryDexClassLoader;
  } else {
    LOG(WARNING) << "Unsupported class loader";
    return false;
  }

  // Inspect the class loader for its dex files.
  std::vector<const DexFile*> dex_files_loaded;
  CollectDexFilesFromSupportedClassLoader(soa.Self(), class_loader, &dex_files_loaded);

  // If we have a dex_elements array extract its dex elements now.
  // This is used in two situations:
  //   1) when a new ClassLoader is created DexPathList will open each dex file sequentially
  //      passing the list of already open dex files each time. This ensures that we see the
  //      correct context even if the ClassLoader under construction is not fully build.
  //   2) when apk splits are loaded on the fly, the framework will load their dex files by
  //      appending them to the current class loader. When the new code paths are loaded in
  //      BaseDexClassLoader, the paths already present in the class loader will be passed
  //      in the dex_elements array.
  if (dex_elements != nullptr) {
    GetDexFilesFromDexElementsArray(dex_elements, &dex_files_loaded);
  }

  ClassLoaderInfo* info = new ClassLoaderContext::ClassLoaderInfo(type);
  // Attach the `ClassLoaderInfo` now, before populating dex files, as only the
  // `ClassLoaderContext` knows whether these dex files should be deleted or not.
  if (child_info == nullptr) {
    class_loader_chain_.reset(info);
  } else if (is_shared_library) {
    if (is_after) {
      child_info->shared_libraries_after.push_back(std::unique_ptr<ClassLoaderInfo>(info));
    } else {
      child_info->shared_libraries.push_back(std::unique_ptr<ClassLoaderInfo>(info));
    }
  } else {
    child_info->parent.reset(info);
  }

  // Now that `info` is in the chain, populate dex files.
  for (size_t i = 0; i < dex_files_loaded.size();) {
    const DexFile* dex_file = dex_files_loaded[i];
    uint32_t checksum = DexFileLoader::GetMultiDexChecksum(dex_files_loaded, &i);
    // Dex location of dex files loaded with InMemoryDexClassLoader is always bogus.
    // Use a magic value for the classpath instead.
    info->classpath.push_back((type == kInMemoryDexClassLoader) ?
                                  kInMemoryDexClassLoaderDexLocationMagic :
                                  dex_file->GetLocation());
    info->checksums.push_back(checksum);
  }
  for (auto* dex_file : dex_files_loaded) {
    info->opened_dex_files.emplace_back(dex_file);
  }

  // Note that dex_elements array is null here. The elements are considered to be part of the
  // current class loader and are not passed to the parents.
  ScopedNullHandle<mirror::ObjectArray<mirror::Object>> null_dex_elements;

  // Add the shared libraries.
  StackHandleScope<5> hs(Thread::Current());
  ArtField* field = WellKnownClasses::dalvik_system_BaseDexClassLoader_sharedLibraryLoaders;
  ObjPtr<mirror::Object> raw_shared_libraries = field->GetObject(class_loader.Get());
  if (raw_shared_libraries != nullptr) {
    Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries =
        hs.NewHandle(raw_shared_libraries->AsObjectArray<mirror::ClassLoader>());
    MutableHandle<mirror::ClassLoader> temp_loader = hs.NewHandle<mirror::ClassLoader>(nullptr);
    for (auto library : shared_libraries.Iterate<mirror::ClassLoader>()) {
      temp_loader.Assign(library);
      if (!CreateInfoFromClassLoader(soa,
                                     temp_loader,
                                     null_dex_elements,
                                     info,
                                     /*is_shared_library=*/true,
                                     /*is_after=*/false)) {
        return false;
      }
    }
  }
  ArtField* field2 = WellKnownClasses::dalvik_system_BaseDexClassLoader_sharedLibraryLoadersAfter;
  ObjPtr<mirror::Object> raw_shared_libraries_after = field2->GetObject(class_loader.Get());
  if (raw_shared_libraries_after != nullptr) {
    Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries_after =
        hs.NewHandle(raw_shared_libraries_after->AsObjectArray<mirror::ClassLoader>());
    MutableHandle<mirror::ClassLoader> temp_loader = hs.NewHandle<mirror::ClassLoader>(nullptr);
    for (auto library : shared_libraries_after.Iterate<mirror::ClassLoader>()) {
      temp_loader.Assign(library);
      if (!CreateInfoFromClassLoader(soa,
                                     temp_loader,
                                     null_dex_elements,
                                     info,
                                     /*is_shared_library=*/true,
                                     /*is_after=*/true)) {
        return false;
      }
    }
  }

  // We created the ClassLoaderInfo for the current loader. Move on to its parent.
  Handle<mirror::ClassLoader> parent = hs.NewHandle(class_loader->GetParent());
  if (!CreateInfoFromClassLoader(soa,
                                 parent,
                                 null_dex_elements,
                                 info,
                                 /*is_shared_library=*/false,
                                 /*is_after=*/false)) {
    return false;
  }
  return true;
}

std::unique_ptr<ClassLoaderContext> ClassLoaderContext::CreateContextForClassLoader(
    jobject class_loader, jobjectArray dex_elements) {
  ScopedTrace trace(__FUNCTION__);

  if (class_loader == nullptr) {
    return nullptr;
  }
  ScopedObjectAccess soa(Thread::Current());
  StackHandleScope<2> hs(soa.Self());
  Handle<mirror::ClassLoader> h_class_loader =
      hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader));
  Handle<mirror::ObjectArray<mirror::Object>> h_dex_elements =
      hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Object>>(dex_elements));
  std::unique_ptr<ClassLoaderContext> result(new ClassLoaderContext(/*owns_the_dex_files=*/false));
  if (!result->CreateInfoFromClassLoader(soa,
                                         h_class_loader,
                                         h_dex_elements,
                                         nullptr,
                                         /*is_shared_library=*/false,
                                         /*is_after=*/false)) {
    return nullptr;
  }
  return result;
}

std::map<std::string, std::string> ClassLoaderContext::EncodeClassPathContextsForClassLoader(
    jobject class_loader) {
  std::unique_ptr<ClassLoaderContext> clc =
      ClassLoaderContext::CreateContextForClassLoader(class_loader, nullptr);
  if (clc != nullptr) {
    return clc->EncodeClassPathContexts("");
  }

  ScopedObjectAccess soa(Thread::Current());
  StackHandleScope<1> hs(soa.Self());
  Handle<mirror::ClassLoader> h_class_loader =
      hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader));
  if (!IsInstanceOfBaseDexClassLoader(h_class_loader)) {
    return std::map<std::string, std::string>{};
  }

  std::vector<const DexFile*> dex_files_loaded;
  CollectDexFilesFromSupportedClassLoader(soa.Self(), h_class_loader, &dex_files_loaded);

  std::map<std::string, std::string> results;
  for (const DexFile* dex_file : dex_files_loaded) {
    results.emplace(DexFileLoader::GetBaseLocation(dex_file->GetLocation()),
                    ClassLoaderContext::kUnsupportedClassLoaderContextEncoding);
  }
  return results;
}

bool ClassLoaderContext::IsValidEncoding(const std::string& possible_encoded_class_loader_context) {
  return ClassLoaderContext::Create(possible_encoded_class_loader_context) != nullptr ||
         possible_encoded_class_loader_context == kUnsupportedClassLoaderContextEncoding;
}

ClassLoaderContext::VerificationResult ClassLoaderContext::VerifyClassLoaderContextMatch(
    const std::string& context_spec, bool verify_names, bool verify_checksums) const {
  ScopedTrace trace(__FUNCTION__);
  if (verify_names || verify_checksums) {
    DCHECK(dex_files_state_ == kDexFilesChecksumsRead || dex_files_state_ == kDexFilesOpened)
        << "dex_files_state_=" << dex_files_state_;
  }

  ClassLoaderContext expected_context;
  if (!expected_context.Parse(context_spec, verify_checksums)) {
    LOG(WARNING) << "Invalid class loader context: " << context_spec;
    return VerificationResult::kMismatch;
  }

  ClassLoaderInfo* info = class_loader_chain_.get();
  ClassLoaderInfo* expected = expected_context.class_loader_chain_.get();
  CHECK(info != nullptr);
  CHECK(expected != nullptr);
  if (!ClassLoaderInfoMatch(*info, *expected, context_spec, verify_names, verify_checksums)) {
    return VerificationResult::kMismatch;
  }
  return VerificationResult::kVerifies;
}

// Returns true if absolute `path` ends with relative `suffix` starting at
// a directory name boundary, i.e. after a '/'. For example, "foo/bar"
// is a valid suffix of "/data/foo/bar" but not "/data-foo/bar".
static inline bool AbsolutePathHasRelativeSuffix(const std::string& path,
                                                 const std::string& suffix) {
  DCHECK(IsAbsoluteLocation(path));
  DCHECK(!IsAbsoluteLocation(suffix));
  return (path.size() > suffix.size()) && (path[path.size() - suffix.size() - 1u] == '/') &&
         (std::string_view(path).substr(/*pos*/ path.size() - suffix.size()) == suffix);
}

// Resolves symlinks and returns the canonicalized absolute path. Returns relative path as is.
static std::string ResolveIfAbsolutePath(const std::string& path) {
  if (!IsAbsoluteLocation(path)) {
    return path;
  }

  std::string filename = path;
  std::string multi_dex_suffix;
  size_t pos = filename.find(DexFileLoader::kMultiDexSeparator);
  if (pos != std::string::npos) {
    multi_dex_suffix = filename.substr(pos);
    filename.resize(pos);
  }

  std::string resolved_filename;
  if (!android::base::Realpath(filename, &resolved_filename)) {
    PLOG(ERROR) << "Unable to resolve path '" << path << "'";
    return path;
  }
  return resolved_filename + multi_dex_suffix;
}

// Returns true if the given dex names are mathing, false otherwise.
static bool AreDexNameMatching(const std::string& actual_dex_name,
                               const std::string& expected_dex_name) {
  // Compute the dex location that must be compared.
  // We shouldn't do a naive comparison `actual_dex_name == expected_dex_name`
  // because even if they refer to the same file, one could be encoded as a relative location
  // and the other as an absolute one.
  bool is_dex_name_absolute = IsAbsoluteLocation(actual_dex_name);
  bool is_expected_dex_name_absolute = IsAbsoluteLocation(expected_dex_name);
  bool dex_names_match = false;
  std::string resolved_actual_dex_name = ResolveIfAbsolutePath(actual_dex_name);
  std::string resolved_expected_dex_name = ResolveIfAbsolutePath(expected_dex_name);

  if (is_dex_name_absolute == is_expected_dex_name_absolute) {
    // If both locations are absolute or relative then compare them as they are.
    // This is usually the case for: shared libraries and secondary dex files.
    dex_names_match = (resolved_actual_dex_name == resolved_expected_dex_name);
  } else if (is_dex_name_absolute) {
    // The runtime name is absolute but the compiled name (the expected one) is relative.
    // This is the case for split apks which depend on base or on other splits.
    dex_names_match =
        AbsolutePathHasRelativeSuffix(resolved_actual_dex_name, resolved_expected_dex_name);
  } else if (is_expected_dex_name_absolute) {
    // The runtime name is relative but the compiled name is absolute.
    // There is no expected use case that would end up here as dex files are always loaded
    // with their absolute location. However, be tolerant and do the best effort (in case
    // there are unexpected new use case...).
    dex_names_match =
        AbsolutePathHasRelativeSuffix(resolved_expected_dex_name, resolved_actual_dex_name);
  } else {
    // Both locations are relative. In this case there's not much we can be sure about
    // except that the names are the same. The checksum will ensure that the files are
    // are same. This should not happen outside testing and manual invocations.
    dex_names_match = (resolved_actual_dex_name == resolved_expected_dex_name);
  }

  return dex_names_match;
}

bool ClassLoaderContext::ClassLoaderInfoMatch(const ClassLoaderInfo& info,
                                              const ClassLoaderInfo& expected_info,
                                              const std::string& context_spec,
                                              bool verify_names,
                                              bool verify_checksums) const {
  if (info.type != expected_info.type) {
    LOG(WARNING) << "ClassLoaderContext type mismatch"
                 << ". expected=" << GetClassLoaderTypeName(expected_info.type)
                 << ", found=" << GetClassLoaderTypeName(info.type) << " (" << context_spec << " | "
                 << EncodeContextForOatFile("") << ")";
    return false;
  }
  if (info.classpath.size() != expected_info.classpath.size()) {
    LOG(WARNING) << "ClassLoaderContext classpath size mismatch"
                 << ". expected=" << expected_info.classpath.size()
                 << ", found=" << info.classpath.size() << " (" << context_spec << " | "
                 << EncodeContextForOatFile("") << ")";
    return false;
  }

  if (verify_checksums) {
    DCHECK_EQ(info.classpath.size(), info.checksums.size());
    DCHECK_EQ(expected_info.classpath.size(), expected_info.checksums.size());
  }

  if (verify_names) {
    for (size_t k = 0; k < info.classpath.size(); k++) {
      bool dex_names_match = AreDexNameMatching(info.classpath[k], expected_info.classpath[k]);

      // Compare the locations.
      if (!dex_names_match) {
        LOG(WARNING) << "ClassLoaderContext classpath element mismatch"
                     << ". expected=" << expected_info.classpath[k]
                     << ", found=" << info.classpath[k] << " (" << context_spec << " | "
                     << EncodeContextForOatFile("") << ")";
        return false;
      }

      // Compare the checksums.
      if (info.checksums[k] != expected_info.checksums[k]) {
        LOG(WARNING) << "ClassLoaderContext classpath element checksum mismatch"
                     << ". expected=" << expected_info.checksums[k]
                     << ", found=" << info.checksums[k] << " (" << context_spec << " | "
                     << EncodeContextForOatFile("") << ")";
        return false;
      }
    }
  }

  if (info.shared_libraries.size() != expected_info.shared_libraries.size()) {
    LOG(WARNING) << "ClassLoaderContext shared library size mismatch. "
                 << "Expected=" << expected_info.shared_libraries.size()
                 << ", found=" << info.shared_libraries.size() << " (" << context_spec << " | "
                 << EncodeContextForOatFile("") << ")";
    return false;
  }
  for (size_t i = 0; i < info.shared_libraries.size(); ++i) {
    if (!ClassLoaderInfoMatch(*info.shared_libraries[i].get(),
                              *expected_info.shared_libraries[i].get(),
                              context_spec,
                              verify_names,
                              verify_checksums)) {
      return false;
    }
  }
  if (info.parent.get() == nullptr) {
    if (expected_info.parent.get() != nullptr) {
      LOG(WARNING) << "ClassLoaderContext parent mismatch. "
                   << " (" << context_spec << " | " << EncodeContextForOatFile("") << ")";
      return false;
    }
    return true;
  } else if (expected_info.parent.get() == nullptr) {
    LOG(WARNING) << "ClassLoaderContext parent mismatch. "
                 << " (" << context_spec << " | " << EncodeContextForOatFile("") << ")";
    return false;
  } else {
    return ClassLoaderInfoMatch(*info.parent.get(),
                                *expected_info.parent.get(),
                                context_spec,
                                verify_names,
                                verify_checksums);
  }
}

std::set<const DexFile*> ClassLoaderContext::CheckForDuplicateDexFiles(
    const std::vector<const DexFile*>& dex_files_to_check) {
  DCHECK_EQ(dex_files_state_, kDexFilesOpened);

  std::set<const DexFile*> result;

  // If the chain is null there's nothing we can check, return an empty list.
  // The class loader chain can be null if there were issues when creating the
  // class loader context (e.g. tests).
  if (class_loader_chain_ == nullptr) {
    return result;
  }

  // We only check the current Class Loader which the first one in the chain.
  // Cross class-loader duplicates may be a valid scenario (though unlikely
  // in the Android world) - and as such we decide not to warn on them.
  ClassLoaderInfo* info = class_loader_chain_.get();
  for (size_t k = 0; k < info->classpath.size(); k++) {
    for (size_t i = 0; i < dex_files_to_check.size();) {
      const DexFile* dex_file = dex_files_to_check[i];
      uint32_t checksum = DexFileLoader::GetMultiDexChecksum(dex_files_to_check, &i);
      if (info->checksums[k] == checksum &&
          AreDexNameMatching(info->classpath[k], dex_file->GetLocation())) {
        result.insert(dex_file);
      }
    }
  }

  return result;
}

}  // namespace art
