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

#include <stdlib.h>
#include <sys/stat.h>

#include <memory>
#include <queue>
#include <vector>

#include "android-base/file.h"
#include "android-base/stringprintf.h"
#include "android-base/strings.h"
#include "art_field-inl.h"
#include "base/bit_vector-inl.h"
#include "base/file_utils.h"
#include "base/logging.h"  // For VLOG.
#include "base/mutex-inl.h"
#include "base/sdk_version.h"
#include "base/stl_util.h"
#include "base/systrace.h"
#include "class_linker.h"
#include "class_loader_context.h"
#include "dex/art_dex_file_loader.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_file_loader.h"
#include "dex/dex_file_tracking_registrar.h"
#include "gc/scoped_gc_critical_section.h"
#include "gc/space/image_space.h"
#include "handle_scope-inl.h"
#include "jit/jit.h"
#include "jni/java_vm_ext.h"
#include "jni/jni_internal.h"
#include "mirror/class_loader.h"
#include "mirror/object-inl.h"
#include "oat_file.h"
#include "oat_file_assistant.h"
#include "obj_ptr-inl.h"
#include "runtime_image.h"
#include "scoped_thread_state_change-inl.h"
#include "thread-current-inl.h"
#include "thread_list.h"
#include "thread_pool.h"
#include "vdex_file.h"
#include "verifier/verifier_deps.h"
#include "well_known_classes.h"

namespace art {

using android::base::StringPrintf;

// If true, we attempt to load the application image if it exists.
static constexpr bool kEnableAppImage = true;

// If true, we attempt to load an app image generated by the runtime.
static const bool kEnableRuntimeAppImage = true;

#if defined(__ANDROID__)
static const char* kDisableAppImageKeyword = "_disable_art_image_";
#endif

const OatFile* OatFileManager::RegisterOatFile(std::unique_ptr<const OatFile> oat_file,
                                               bool in_memory) {
  // Use class_linker vlog to match the log for dex file registration.
  VLOG(class_linker) << "Registered oat file " << oat_file->GetLocation();
  PaletteNotifyOatFileLoaded(oat_file->GetLocation().c_str());

  WriterMutexLock mu(Thread::Current(), *Locks::oat_file_manager_lock_);
  CHECK(in_memory ||
        !only_use_system_oat_files_ ||
        LocationIsTrusted(oat_file->GetLocation(), !Runtime::Current()->DenyArtApexDataFiles()) ||
        !oat_file->IsExecutable())
      << "Registering a non /system oat file: " << oat_file->GetLocation() << " android-root="
      << GetAndroidRoot();
  DCHECK(oat_file != nullptr);
  if (kIsDebugBuild) {
    CHECK(oat_files_.find(oat_file) == oat_files_.end());
    for (const std::unique_ptr<const OatFile>& existing : oat_files_) {
      CHECK_NE(oat_file.get(), existing.get()) << oat_file->GetLocation();
      // Check that we don't have an oat file with the same address. Copies of the same oat file
      // should be loaded at different addresses.
      CHECK_NE(oat_file->Begin(), existing->Begin()) << "Oat file already mapped at that location";
    }
  }
  const OatFile* ret = oat_file.get();
  oat_files_.insert(std::move(oat_file));
  return ret;
}

void OatFileManager::UnRegisterAndDeleteOatFile(const OatFile* oat_file) {
  WriterMutexLock mu(Thread::Current(), *Locks::oat_file_manager_lock_);
  DCHECK(oat_file != nullptr);
  std::unique_ptr<const OatFile> compare(oat_file);
  auto it = oat_files_.find(compare);
  CHECK(it != oat_files_.end());
  oat_files_.erase(it);
  compare.release();  // NOLINT b/117926937
}

const OatFile* OatFileManager::FindOpenedOatFileFromDexLocation(
    const std::string& dex_base_location) const {
  ReaderMutexLock mu(Thread::Current(), *Locks::oat_file_manager_lock_);
  for (const std::unique_ptr<const OatFile>& oat_file : oat_files_) {
    const std::vector<const OatDexFile*>& oat_dex_files = oat_file->GetOatDexFiles();
    for (const OatDexFile* oat_dex_file : oat_dex_files) {
      if (DexFileLoader::GetBaseLocation(oat_dex_file->GetDexFileLocation()) == dex_base_location) {
        return oat_file.get();
      }
    }
  }
  return nullptr;
}

const OatFile* OatFileManager::FindOpenedOatFileFromOatLocation(const std::string& oat_location)
    const {
  ReaderMutexLock mu(Thread::Current(), *Locks::oat_file_manager_lock_);
  return FindOpenedOatFileFromOatLocationLocked(oat_location);
}

const OatFile* OatFileManager::FindOpenedOatFileFromOatLocationLocked(
    const std::string& oat_location) const {
  for (const std::unique_ptr<const OatFile>& oat_file : oat_files_) {
    if (oat_file->GetLocation() == oat_location) {
      return oat_file.get();
    }
  }
  return nullptr;
}

std::vector<const OatFile*> OatFileManager::GetBootOatFiles() const {
  std::vector<gc::space::ImageSpace*> image_spaces =
      Runtime::Current()->GetHeap()->GetBootImageSpaces();
  std::vector<const OatFile*> oat_files;
  oat_files.reserve(image_spaces.size());
  for (gc::space::ImageSpace* image_space : image_spaces) {
    oat_files.push_back(image_space->GetOatFile());
  }
  return oat_files;
}

OatFileManager::OatFileManager()
    : only_use_system_oat_files_(false) {}

OatFileManager::~OatFileManager() {
  // Explicitly clear oat_files_ since the OatFile destructor calls back into OatFileManager for
  // UnRegisterOatFileLocation.
  oat_files_.clear();
}

std::vector<const OatFile*> OatFileManager::RegisterImageOatFiles(
    const std::vector<gc::space::ImageSpace*>& spaces) {
  std::vector<const OatFile*> oat_files;
  oat_files.reserve(spaces.size());
  for (gc::space::ImageSpace* space : spaces) {
    // The oat file was generated in memory if the image space has a profile.
    bool in_memory = !space->GetProfileFiles().empty();
    oat_files.push_back(RegisterOatFile(space->ReleaseOatFile(), in_memory));
  }
  return oat_files;
}

bool OatFileManager::ShouldLoadAppImage(const OatFile* source_oat_file) const {
  Runtime* const runtime = Runtime::Current();
  if (!kEnableAppImage || (runtime->IsJavaDebuggableAtInit() && !source_oat_file->IsDebuggable())) {
    return false;
  }

#if defined(__ANDROID__)
  const char* process_name = getprogname();
  // Some processes would rather take the runtime impact in the interest of memory (b/292210260)
  if (process_name != nullptr && strstr(process_name, kDisableAppImageKeyword) != nullptr) {
    LOG(INFO) << "Skipping app image load for " << process_name;
    return false;
  }
#endif

  return true;
}

std::vector<std::unique_ptr<const DexFile>> OatFileManager::OpenDexFilesFromOat(
    const char* dex_location,
    jobject class_loader,
    jobjectArray dex_elements,
    const OatFile** out_oat_file,
    std::vector<std::string>* error_msgs) {
  ScopedTrace trace(StringPrintf("%s(%s)", __FUNCTION__, dex_location));
  CHECK(dex_location != nullptr);
  CHECK(error_msgs != nullptr);

  // Verify we aren't holding the mutator lock, which could starve GC when
  // hitting the disk.
  Thread* const self = Thread::Current();
  Locks::mutator_lock_->AssertNotHeld(self);
  Runtime* const runtime = Runtime::Current();

  std::vector<std::unique_ptr<const DexFile>> dex_files;
  std::unique_ptr<ClassLoaderContext> context(
      ClassLoaderContext::CreateContextForClassLoader(class_loader, dex_elements));

  // If the class_loader is null there's not much we can do. This happens if a dex files is loaded
  // directly with DexFile APIs instead of using class loaders.
  if (class_loader == nullptr) {
    LOG(WARNING) << "Opening an oat file without a class loader. "
                 << "Are you using the deprecated DexFile APIs?";
  } else if (context != nullptr) {
    auto oat_file_assistant = std::make_unique<OatFileAssistant>(dex_location,
                                                                 kRuntimeISA,
                                                                 context.get(),
                                                                 runtime->GetOatFilesExecutable(),
                                                                 only_use_system_oat_files_);

    // Get the current optimization status for trace debugging.
    // Implementation detail note: GetOptimizationStatus will select the same
    // oat file as GetBestOatFile used below, and in doing so it already pre-populates
    // some OatFileAssistant internal fields.
    std::string odex_location;
    std::string compilation_filter;
    std::string compilation_reason;
    std::string odex_status;
    oat_file_assistant->GetOptimizationStatus(
        &odex_location, &compilation_filter, &compilation_reason, &odex_status);

    ScopedTrace odex_loading(StringPrintf(
        "location=%s status=%s filter=%s reason=%s",
        odex_location.c_str(),
        odex_status.c_str(),
        compilation_filter.c_str(),
        compilation_reason.c_str()));

    const bool has_registered_app_info = Runtime::Current()->GetAppInfo()->HasRegisteredAppInfo();
    const AppInfo::CodeType code_type =
        Runtime::Current()->GetAppInfo()->GetRegisteredCodeType(dex_location);
    // We only want to madvise primary/split dex artifacts as a startup optimization. However,
    // as the code_type for those artifacts may not be set until the initial app info registration,
    // we conservatively madvise everything until the app info registration is complete.
    const bool should_madvise = !has_registered_app_info ||
                                code_type == AppInfo::CodeType::kPrimaryApk ||
                                code_type == AppInfo::CodeType::kSplitApk;

    // Proceed with oat file loading.
    std::unique_ptr<const OatFile> oat_file(oat_file_assistant->GetBestOatFile().release());
    VLOG(oat) << "OatFileAssistant(" << dex_location << ").GetBestOatFile()="
              << (oat_file != nullptr ? oat_file->GetLocation() : "")
              << " (executable=" << (oat_file != nullptr ? oat_file->IsExecutable() : false) << ")";

    CHECK(oat_file == nullptr || odex_location == oat_file->GetLocation())
        << "OatFileAssistant non-determinism in choosing best oat files. "
        << "optimization-status-location=" << odex_location
        << " best_oat_file-location=" << oat_file->GetLocation();

    if (oat_file != nullptr) {
      bool compilation_enabled =
          CompilerFilter::IsAotCompilationEnabled(oat_file->GetCompilerFilter());
      // Load the dex files from the oat file.
      bool added_image_space = false;
      if (should_madvise) {
        VLOG(oat) << "Madvising oat file: " << oat_file->GetLocation();
        size_t madvise_size_limit = runtime->GetMadviseWillNeedSizeOdex();
        Runtime::MadviseFileForRange(madvise_size_limit,
                                     oat_file->Size(),
                                     oat_file->Begin(),
                                     oat_file->End(),
                                     oat_file->GetLocation());
      }

      ScopedTrace app_image_timing("AppImage:Loading");

      // We need to throw away the image space if we are debuggable but the oat-file source of the
      // image is not otherwise we might get classes with inlined methods or other such things.
      std::unique_ptr<gc::space::ImageSpace> image_space;
      if (ShouldLoadAppImage(oat_file.get())) {
        if (oat_file->IsExecutable()) {
          // App images generated by the compiler can only be used if the oat file
          // is executable.
          image_space = oat_file_assistant->OpenImageSpace(oat_file.get());
        }
        if (kEnableRuntimeAppImage && image_space == nullptr && !compilation_enabled) {
          std::string art_file = RuntimeImage::GetRuntimeImagePath(dex_location);
          std::string error_msg;
          ScopedObjectAccess soa(self);
          image_space = gc::space::ImageSpace::CreateFromAppImage(
              art_file.c_str(), oat_file.get(), &error_msg);
          if (image_space == nullptr) {
            (OS::FileExists(art_file.c_str()) ? LOG_STREAM(INFO) : VLOG_STREAM(image))
                << "Could not load runtime generated app image: " << error_msg;
          }
        }
      }
      if (image_space != nullptr) {
        ScopedObjectAccess soa(self);
        StackHandleScope<1> hs(self);
        Handle<mirror::ClassLoader> h_loader(
            hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
        // Can not load app image without class loader.
        if (h_loader != nullptr) {
          std::string temp_error_msg;
          // Add image space has a race condition since other threads could be reading from the
          // spaces array.
          {
            ScopedThreadSuspension sts(self, ThreadState::kSuspended);
            gc::ScopedGCCriticalSection gcs(self,
                                            gc::kGcCauseAddRemoveAppImageSpace,
                                            gc::kCollectorTypeAddRemoveAppImageSpace);
            ScopedSuspendAll ssa("Add image space");
            runtime->GetHeap()->AddSpace(image_space.get());
          }
          {
            ScopedTrace image_space_timing("Adding image space");
            gc::space::ImageSpace* space_ptr = image_space.get();
            added_image_space = runtime->GetClassLinker()->AddImageSpaces(
                ArrayRef<gc::space::ImageSpace*>(&space_ptr, /*size=*/1),
                h_loader,
                context.get(),
                /*out*/ &dex_files,
                /*out*/ &temp_error_msg);
          }
          if (added_image_space) {
            // Successfully added image space to heap, release the map so that it does not get
            // freed.
            image_space.release();  // NOLINT b/117926937

            // Register for tracking.
            for (const auto& dex_file : dex_files) {
              dex::tracking::RegisterDexFile(dex_file.get());
            }

            if (!compilation_enabled) {
              // Update the filter we are going to report to 'speed-profile'.
              // Ideally, we would also update the compiler filter of the odex
              // file, but at this point it's just too late.
              compilation_filter = CompilerFilter::NameOfFilter(CompilerFilter::kSpeedProfile);
            }
          } else {
            LOG(INFO) << "Failed to add image file: " << temp_error_msg;
            dex_files.clear();
            {
              ScopedThreadSuspension sts(self, ThreadState::kSuspended);
              gc::ScopedGCCriticalSection gcs(self,
                                              gc::kGcCauseAddRemoveAppImageSpace,
                                              gc::kCollectorTypeAddRemoveAppImageSpace);
              ScopedSuspendAll ssa("Remove image space");
              runtime->GetHeap()->RemoveSpace(image_space.get());
            }
            // Non-fatal, don't update error_msg.
          }
        }
      }
      if (!added_image_space) {
        DCHECK(dex_files.empty());

        if (oat_file->RequiresImage()) {
          LOG(WARNING) << "Loading "
                       << oat_file->GetLocation()
                       << " non-executable as it requires an image which we failed to load";
          // file as non-executable.
          auto nonexecutable_oat_file_assistant =
              std::make_unique<OatFileAssistant>(dex_location,
                                                 kRuntimeISA,
                                                 context.get(),
                                                 /*load_executable=*/false,
                                                 only_use_system_oat_files_);
          oat_file.reset(nonexecutable_oat_file_assistant->GetBestOatFile().release());

          // The file could be deleted concurrently (for example background
          // dexopt, or secondary oat file being deleted by the app).
          if (oat_file == nullptr) {
            LOG(WARNING) << "Failed to reload oat file non-executable " << dex_location;
          }
        }

        if (oat_file != nullptr) {
          dex_files = oat_file_assistant->LoadDexFiles(*oat_file.get(), dex_location);

          // Register for tracking.
          for (const auto& dex_file : dex_files) {
            dex::tracking::RegisterDexFile(dex_file.get());
          }
        }
      }
      if (dex_files.empty()) {
        ScopedTrace failed_to_open_dex_files("FailedToOpenDexFilesFromOat");
        error_msgs->push_back("Failed to open dex files from " + odex_location);
      } else if (should_madvise) {
        size_t madvise_size_limit = Runtime::Current()->GetMadviseWillNeedTotalDexSize();
        for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
          // Prefetch the dex file based on vdex size limit (name should
          // have been dex size limit).
          VLOG(oat) << "Madvising dex file: " << dex_file->GetLocation();
          Runtime::MadviseFileForRange(madvise_size_limit,
                                       dex_file->Size(),
                                       dex_file->Begin(),
                                       dex_file->Begin() + dex_file->Size(),
                                       dex_file->GetLocation());
          if (dex_file->Size() >= madvise_size_limit) {
            break;
          }
          madvise_size_limit -= dex_file->Size();
        }
      }

      if (oat_file != nullptr) {
        VLOG(class_linker) << "Registering " << oat_file->GetLocation();
        *out_oat_file = RegisterOatFile(std::move(oat_file));
      }
    } else {
      // oat_file == nullptr
      // Verify if any of the dex files being loaded is already in the class path.
      // If so, report an error with the current stack trace.
      // Most likely the developer didn't intend to do this because it will waste
      // performance and memory.
      if (oat_file_assistant->GetBestStatus() == OatFileAssistant::kOatContextOutOfDate) {
        std::set<const DexFile*> already_exists_in_classpath =
            context->CheckForDuplicateDexFiles(MakeNonOwningPointerVector(dex_files));
        if (!already_exists_in_classpath.empty()) {
          ScopedTrace duplicate_dex_files("DuplicateDexFilesInContext");
          auto duplicate_it = already_exists_in_classpath.begin();
          std::string duplicates = (*duplicate_it)->GetLocation();
          for (duplicate_it++ ; duplicate_it != already_exists_in_classpath.end(); duplicate_it++) {
            duplicates += "," + (*duplicate_it)->GetLocation();
          }

          std::ostringstream out;
          out << "Trying to load dex files which is already loaded in the same ClassLoader "
              << "hierarchy.\n"
              << "This is a strong indication of bad ClassLoader construct which leads to poor "
              << "performance and wastes memory.\n"
              << "The list of duplicate dex files is: " << duplicates << "\n"
              << "The current class loader context is: "
              << context->EncodeContextForOatFile("") << "\n"
              << "Java stack trace:\n";

          {
            ScopedObjectAccess soa(self);
            self->DumpJavaStack(out);
          }

          // We log this as an ERROR to stress the fact that this is most likely unintended.
          // Note that ART cannot do anything about it. It is up to the app to fix their logic.
          // Here we are trying to give a heads up on why the app might have performance issues.
          LOG(ERROR) << out.str();
        }
      }
    }

    Runtime::Current()->GetAppInfo()->RegisterOdexStatus(
        dex_location,
        compilation_filter,
        compilation_reason,
        odex_status);
  }

  // If we arrive here with an empty dex files list, it means we fail to load
  // it/them through an .oat file.
  if (dex_files.empty()) {
    std::string error_msg;
    static constexpr bool kVerifyChecksum = true;
    ArtDexFileLoader dex_file_loader(dex_location);
    if (!dex_file_loader.Open(Runtime::Current()->IsVerificationEnabled(),
                              kVerifyChecksum,
                              /*out*/ &error_msg,
                              &dex_files)) {
      ScopedTrace fail_to_open_dex_from_apk("FailedToOpenDexFilesFromApk");
      LOG(WARNING) << error_msg;
      error_msgs->push_back("Failed to open dex files from " + std::string(dex_location)
                            + " because: " + error_msg);
    }
  }

  if (Runtime::Current()->GetJit() != nullptr) {
    Runtime::Current()->GetJit()->RegisterDexFiles(dex_files, class_loader);
  }

  // Now that we loaded the dex/odex files, notify the runtime.
  // Note that we do this everytime we load dex files.
  Runtime::Current()->NotifyDexFileLoaded();

  return dex_files;
}

static std::vector<const DexFile::Header*> GetDexFileHeaders(const std::vector<MemMap>& maps) {
  std::vector<const DexFile::Header*> headers;
  headers.reserve(maps.size());
  for (const MemMap& map : maps) {
    DCHECK(map.IsValid());
    headers.push_back(reinterpret_cast<const DexFile::Header*>(map.Begin()));
  }
  return headers;
}

std::vector<std::unique_ptr<const DexFile>> OatFileManager::OpenDexFilesFromOat(
    std::vector<MemMap>&& dex_mem_maps,
    jobject class_loader,
    jobjectArray dex_elements,
    const OatFile** out_oat_file,
    std::vector<std::string>* error_msgs) {
  std::vector<std::unique_ptr<const DexFile>> dex_files = OpenDexFilesFromOat_Impl(
      std::move(dex_mem_maps),
      class_loader,
      dex_elements,
      out_oat_file,
      error_msgs);

  if (error_msgs->empty()) {
    // Remove write permission from DexFile pages. We do this at the end because
    // OatFile assigns OatDexFile pointer in the DexFile objects.
    for (std::unique_ptr<const DexFile>& dex_file : dex_files) {
      if (!dex_file->DisableWrite()) {
        error_msgs->push_back("Failed to make dex file " + dex_file->GetLocation() + " read-only");
      }
    }
  }

  if (!error_msgs->empty()) {
    return std::vector<std::unique_ptr<const DexFile>>();
  }

  return dex_files;
}

std::vector<std::unique_ptr<const DexFile>> OatFileManager::OpenDexFilesFromOat_Impl(
    std::vector<MemMap>&& dex_mem_maps,
    jobject class_loader,
    jobjectArray dex_elements,
    const OatFile** out_oat_file,
    std::vector<std::string>* error_msgs) {
  ScopedTrace trace(__FUNCTION__);
  std::string error_msg;
  DCHECK(error_msgs != nullptr);

  // Extract dex file headers from `dex_mem_maps`.
  const std::vector<const DexFile::Header*> dex_headers = GetDexFileHeaders(dex_mem_maps);

  // Determine dex/vdex locations and the combined location checksum.
  std::string dex_location;
  std::string vdex_path;
  bool has_vdex = OatFileAssistant::AnonymousDexVdexLocation(dex_headers,
                                                             kRuntimeISA,
                                                             &dex_location,
                                                             &vdex_path);

  // Attempt to open an existing vdex and check dex file checksums match.
  std::unique_ptr<VdexFile> vdex_file = nullptr;
  if (has_vdex && OS::FileExists(vdex_path.c_str())) {
    vdex_file = VdexFile::Open(vdex_path,
                               /* writable= */ false,
                               /* low_4gb= */ false,
                               &error_msg);
    if (vdex_file == nullptr) {
      LOG(WARNING) << "Failed to open vdex " << vdex_path << ": " << error_msg;
    } else if (!vdex_file->MatchesDexFileChecksums(dex_headers)) {
      LOG(WARNING) << "Failed to open vdex " << vdex_path << ": dex file checksum mismatch";
      vdex_file.reset(nullptr);
    }
  }

  // Load dex files. Skip structural dex file verification if vdex was found
  // and dex checksums matched.
  std::vector<std::unique_ptr<const DexFile>> dex_files;
  for (size_t i = 0; i < dex_mem_maps.size(); ++i) {
    static constexpr bool kVerifyChecksum = true;
    ArtDexFileLoader dex_file_loader(std::move(dex_mem_maps[i]),
                                     DexFileLoader::GetMultiDexLocation(i, dex_location.c_str()));
    std::unique_ptr<const DexFile> dex_file(dex_file_loader.Open(
        dex_headers[i]->checksum_,
        /* verify= */ (vdex_file == nullptr) && Runtime::Current()->IsVerificationEnabled(),
        kVerifyChecksum,
        &error_msg));
    if (dex_file != nullptr) {
      dex::tracking::RegisterDexFile(dex_file.get());  // Register for tracking.
      dex_files.push_back(std::move(dex_file));
    } else {
      error_msgs->push_back("Failed to open dex files from memory: " + error_msg);
    }
  }

  // Check if we should proceed to creating an OatFile instance backed by the vdex.
  // We need: (a) an existing vdex, (b) class loader (can be null if invoked via reflection),
  // and (c) no errors during dex file loading.
  if (vdex_file == nullptr || class_loader == nullptr || !error_msgs->empty()) {
    return dex_files;
  }

  // Attempt to create a class loader context, check OpenDexFiles succeeds (prerequisite
  // for using the context later).
  std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::CreateContextForClassLoader(
      class_loader,
      dex_elements);
  if (context == nullptr) {
    LOG(ERROR) << "Could not create class loader context for " << vdex_path;
    return dex_files;
  }
  DCHECK(context->OpenDexFiles())
      << "Context created from already opened dex files should not attempt to open again";

  // Initialize an OatFile instance backed by the loaded vdex.
  std::unique_ptr<OatFile> oat_file(OatFile::OpenFromVdex(MakeNonOwningPointerVector(dex_files),
                                                          std::move(vdex_file),
                                                          dex_location,
                                                          context.get()));
  if (oat_file != nullptr) {
    VLOG(class_linker) << "Registering " << oat_file->GetLocation();
    *out_oat_file = RegisterOatFile(std::move(oat_file));
  }
  return dex_files;
}

// Check how many vdex files exist in the same directory as the vdex file we are about
// to write. If more than or equal to kAnonymousVdexCacheSize, unlink the least
// recently used one(s) (according to stat-reported atime).
static bool UnlinkLeastRecentlyUsedVdexIfNeeded(const std::string& vdex_path_to_add,
                                                std::string* error_msg) {
  std::string basename = android::base::Basename(vdex_path_to_add);
  if (!OatFileAssistant::IsAnonymousVdexBasename(basename)) {
    // File is not for in memory dex files.
    return true;
  }

  if (OS::FileExists(vdex_path_to_add.c_str())) {
    // File already exists and will be overwritten.
    // This will not change the number of entries in the cache.
    return true;
  }

  auto last_slash = vdex_path_to_add.rfind('/');
  CHECK(last_slash != std::string::npos);
  std::string vdex_dir = vdex_path_to_add.substr(0, last_slash + 1);

  if (!OS::DirectoryExists(vdex_dir.c_str())) {
    // Folder does not exist yet. Cache has zero entries.
    return true;
  }

  std::vector<std::pair<time_t, std::string>> cache;

  DIR* c_dir = opendir(vdex_dir.c_str());
  if (c_dir == nullptr) {
    *error_msg = "Unable to open " + vdex_dir + " to delete unused vdex files";
    return false;
  }
  for (struct dirent* de = readdir(c_dir); de != nullptr; de = readdir(c_dir)) {
    if (de->d_type != DT_REG) {
      continue;
    }
    basename = de->d_name;
    if (!OatFileAssistant::IsAnonymousVdexBasename(basename)) {
      continue;
    }
    std::string fullname = vdex_dir + basename;

    struct stat s;
    int rc = TEMP_FAILURE_RETRY(stat(fullname.c_str(), &s));
    if (rc == -1) {
      *error_msg = "Failed to stat() anonymous vdex file " + fullname;
      return false;
    }

    cache.push_back(std::make_pair(s.st_atime, fullname));
  }
  CHECK_EQ(0, closedir(c_dir)) << "Unable to close directory.";

  if (cache.size() < OatFileManager::kAnonymousVdexCacheSize) {
    return true;
  }

  std::sort(cache.begin(),
            cache.end(),
            [](const auto& a, const auto& b) { return a.first < b.first; });
  for (size_t i = OatFileManager::kAnonymousVdexCacheSize - 1; i < cache.size(); ++i) {
    if (unlink(cache[i].second.c_str()) != 0) {
      *error_msg = "Could not unlink anonymous vdex file " + cache[i].second;
      return false;
    }
  }

  return true;
}

class BackgroundVerificationTask final : public Task {
 public:
  BackgroundVerificationTask(const std::vector<const DexFile*>& dex_files,
                             jobject class_loader,
                             const std::string& vdex_path)
      : dex_files_(dex_files),
        vdex_path_(vdex_path) {
    Thread* const self = Thread::Current();
    ScopedObjectAccess soa(self);
    // Create a global ref for `class_loader` because it will be accessed from a different thread.
    class_loader_ = soa.Vm()->AddGlobalRef(self, soa.Decode<mirror::ClassLoader>(class_loader));
    CHECK(class_loader_ != nullptr);
  }

  ~BackgroundVerificationTask() {
    Thread* const self = Thread::Current();
    ScopedObjectAccess soa(self);
    soa.Vm()->DeleteGlobalRef(self, class_loader_);
  }

  void Run(Thread* self) override {
    std::string error_msg;
    ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
    verifier::VerifierDeps verifier_deps(dex_files_);

    // Iterate over all classes and verify them.
    for (const DexFile* dex_file : dex_files_) {
      for (uint32_t cdef_idx = 0; cdef_idx < dex_file->NumClassDefs(); cdef_idx++) {
        const dex::ClassDef& class_def = dex_file->GetClassDef(cdef_idx);

        // Take handles inside the loop. The background verification is low priority
        // and we want to minimize the risk of blocking anyone else.
        ScopedObjectAccess soa(self);
        StackHandleScope<2> hs(self);
        Handle<mirror::ClassLoader> h_loader(hs.NewHandle(
            soa.Decode<mirror::ClassLoader>(class_loader_)));
        Handle<mirror::Class> h_class(hs.NewHandle<mirror::Class>(class_linker->FindClass(
            self,
            dex_file->GetClassDescriptor(class_def),
            h_loader)));

        if (h_class == nullptr) {
          DCHECK(self->IsExceptionPending());
          self->ClearException();
          continue;
        }

        if (&h_class->GetDexFile() != dex_file) {
          // There is a different class in the class path or a parent class loader
          // with the same descriptor. This `h_class` is not resolvable, skip it.
          continue;
        }

        DCHECK(h_class->IsResolved()) << h_class->PrettyDescriptor();
        class_linker->VerifyClass(self, &verifier_deps, h_class);
        if (self->IsExceptionPending()) {
          // ClassLinker::VerifyClass can throw, but the exception isn't useful here.
          self->ClearException();
        }

        DCHECK(h_class->IsVerified() || h_class->IsErroneous())
            << h_class->PrettyDescriptor() << ": state=" << h_class->GetStatus();

        if (h_class->IsVerified()) {
          verifier_deps.RecordClassVerified(*dex_file, class_def);
        }
      }
    }

    // Delete old vdex files if there are too many in the folder.
    if (!UnlinkLeastRecentlyUsedVdexIfNeeded(vdex_path_, &error_msg)) {
      LOG(ERROR) << "Could not unlink old vdex files " << vdex_path_ << ": " << error_msg;
      return;
    }

    // Construct a vdex file and write `verifier_deps` into it.
    if (!VdexFile::WriteToDisk(vdex_path_,
                               dex_files_,
                               verifier_deps,
                               &error_msg)) {
      LOG(ERROR) << "Could not write anonymous vdex " << vdex_path_ << ": " << error_msg;
      return;
    }
  }

  void Finalize() override {
    delete this;
  }

 private:
  const std::vector<const DexFile*> dex_files_;
  jobject class_loader_;
  const std::string vdex_path_;

  DISALLOW_COPY_AND_ASSIGN(BackgroundVerificationTask);
};

void OatFileManager::RunBackgroundVerification(const std::vector<const DexFile*>& dex_files,
                                               jobject class_loader) {
  Runtime* const runtime = Runtime::Current();
  Thread* const self = Thread::Current();

  if (runtime->IsJavaDebuggable()) {
    // Threads created by ThreadPool ("runtime threads") are not allowed to load
    // classes when debuggable to match class-initialization semantics
    // expectations. Do not verify in the background.
    return;
  }

  {
    // Temporarily create a class loader context to see if we recognize the
    // chain.
    std::unique_ptr<ClassLoaderContext> context(
        ClassLoaderContext::CreateContextForClassLoader(class_loader, nullptr));
    if (context == nullptr) {
      // We only run background verification for class loaders we know the lookup
      // chain. Because the background verification runs on runtime threads,
      // which do not call Java, we won't be able to load classes when
      // verifying, which is something the current verifier relies on.
      return;
    }
  }

  if (!IsSdkVersionSetAndAtLeast(runtime->GetTargetSdkVersion(), SdkVersion::kQ)) {
    // Do not run for legacy apps as they may depend on the previous class loader behaviour.
    return;
  }

  if (runtime->IsShuttingDown(self)) {
    // Not allowed to create new threads during runtime shutdown.
    return;
  }

  if (dex_files.size() < 1) {
    // Nothing to verify.
    return;
  }

  std::string dex_location = dex_files[0]->GetLocation();
  const std::string& data_dir = Runtime::Current()->GetProcessDataDirectory();
  if (!android::base::StartsWith(dex_location, data_dir)) {
    // For now, we only run background verification for secondary dex files.
    // Running it for primary or split APKs could have some undesirable
    // side-effects, like overloading the device on app startup.
    return;
  }

  std::string error_msg;
  std::string odex_filename;
  if (!OatFileAssistant::DexLocationToOdexFilename(dex_location,
                                                   kRuntimeISA,
                                                   &odex_filename,
                                                   &error_msg)) {
    LOG(WARNING) << "Could not get odex filename for " << dex_location << ": " << error_msg;
    return;
  }

  if (LocationIsOnArtApexData(odex_filename) && Runtime::Current()->DenyArtApexDataFiles()) {
    // Ignore vdex file associated with this odex file as the odex file is not trustworthy.
    return;
  }

  {
    WriterMutexLock mu(self, *Locks::oat_file_manager_lock_);
    if (verification_thread_pool_ == nullptr) {
      verification_thread_pool_.reset(
          new ThreadPool("Verification thread pool", /* num_threads= */ 1));
      verification_thread_pool_->StartWorkers(self);
    }
  }
  verification_thread_pool_->AddTask(self, new BackgroundVerificationTask(
      dex_files,
      class_loader,
      GetVdexFilename(odex_filename)));
}

void OatFileManager::WaitForWorkersToBeCreated() {
  DCHECK(!Runtime::Current()->IsShuttingDown(Thread::Current()))
      << "Cannot create new threads during runtime shutdown";
  if (verification_thread_pool_ != nullptr) {
    verification_thread_pool_->WaitForWorkersToBeCreated();
  }
}

void OatFileManager::DeleteThreadPool() {
  verification_thread_pool_.reset(nullptr);
}

void OatFileManager::WaitForBackgroundVerificationTasksToFinish() {
  if (verification_thread_pool_ == nullptr) {
    return;
  }

  Thread* const self = Thread::Current();
  verification_thread_pool_->Wait(self, /* do_work= */ true, /* may_hold_locks= */ false);
}

void OatFileManager::WaitForBackgroundVerificationTasks() {
  if (verification_thread_pool_ != nullptr) {
    Thread* const self = Thread::Current();
    verification_thread_pool_->WaitForWorkersToBeCreated();
    verification_thread_pool_->Wait(self, /* do_work= */ true, /* may_hold_locks= */ false);
  }
}

void OatFileManager::ClearOnlyUseTrustedOatFiles() {
  only_use_system_oat_files_ = false;
}

void OatFileManager::SetOnlyUseTrustedOatFiles() {
  ReaderMutexLock mu(Thread::Current(), *Locks::oat_file_manager_lock_);
  if (!oat_files_.empty()) {
    LOG(FATAL) << "Unexpected non-empty loaded oat files ";
  }
  only_use_system_oat_files_ = true;
}

void OatFileManager::DumpForSigQuit(std::ostream& os) {
  ReaderMutexLock mu(Thread::Current(), *Locks::oat_file_manager_lock_);
  std::vector<const OatFile*> boot_oat_files = GetBootOatFiles();
  for (const std::unique_ptr<const OatFile>& oat_file : oat_files_) {
    if (ContainsElement(boot_oat_files, oat_file.get())) {
      continue;
    }
    os << oat_file->GetLocation() << ": " << oat_file->GetCompilerFilter() << "\n";
  }
}

bool OatFileManager::ContainsPc(const void* code) {
  ReaderMutexLock mu(Thread::Current(), *Locks::oat_file_manager_lock_);
  std::vector<const OatFile*> boot_oat_files = GetBootOatFiles();
  for (const std::unique_ptr<const OatFile>& oat_file : oat_files_) {
    if (oat_file->Contains(code)) {
      return true;
    }
  }
  return false;
}

}  // namespace art
