/*
 * 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 <memory>
#include <queue>
#include <vector>
#include <sys/stat.h>

#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 "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;

const OatFile* OatFileManager::RegisterOatFile(std::unique_ptr<const OatFile> oat_file) {
  // 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(!only_use_system_oat_files_ ||
        LocationIsTrusted(oat_file->GetLocation(), !Runtime::Current()->DenyArtApexDataFiles()) ||
        !oat_file->IsExecutable())
      << "Registering a non /system oat file: " << oat_file->GetLocation();
  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) {
    oat_files.push_back(RegisterOatFile(space->ReleaseOatFile()));
  }
  return oat_files;
}

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

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) {
    OatFileAssistant oat_file_assistant(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);

    Runtime::Current()->GetAppInfo()->RegisterOdexStatus(
        dex_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()));

    // 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) {
      // Load the dex files from the oat file.
      bool added_image_space = false;
      if (oat_file->IsExecutable()) {
        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())) {
          image_space = oat_file_assistant.OpenImageSpace(oat_file.get());
        }
        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, 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");
              added_image_space = runtime->GetClassLinker()->AddImageSpace(image_space.get(),
                                                                           h_loader,
                                                                           /*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());
              }
            } else {
              LOG(INFO) << "Failed to add image file " << temp_error_msg;
              dex_files.clear();
              {
                ScopedThreadSuspension sts(self, 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.
          OatFileAssistant nonexecutable_oat_file_assistant(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 {
        // Opened dex files from an oat file, madvise them to their loaded state.
         for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
           OatDexFile::MadviseDexFileAtLoad(*dex_file);
         }
      }

      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();
        }
      }
    }
  }

  // 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;
    const ArtDexFileLoader dex_file_loader;
    if (!dex_file_loader.Open(dex_location,
                              dex_location,
                              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,
                               /* unquicken= */ 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;
    const ArtDexFileLoader dex_file_loader;
    std::unique_ptr<const DexFile> dex_file(dex_file_loader.Open(
        DexFileLoader::GetMultiDexLocation(i, dex_location.c_str()),
        dex_headers[i]->checksum_,
        std::move(dex_mem_maps[i]),
        /* 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));
  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) {
          CHECK(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;
        }

        CHECK(h_class->IsResolved()) << h_class->PrettyDescriptor();
        class_linker->VerifyClass(self, &verifier_deps, h_class);
        if (h_class->IsErroneous()) {
          // ClassLinker::VerifyClass throws, which isn't useful here.
          CHECK(soa.Self()->IsExceptionPending());
          soa.Self()->ClearException();
        }

        CHECK(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;
  }

  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::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::SetOnlyUseTrustedOatFiles() {
  ReaderMutexLock mu(Thread::Current(), *Locks::oat_file_manager_lock_);
  // Make sure all files that were loaded up to this point are on /system.
  // Skip the image files as they can encode locations that don't exist (eg not
  // containing the arch in the path, or for JIT zygote /nonx/existent).
  std::vector<const OatFile*> boot_vector = GetBootOatFiles();
  std::unordered_set<const OatFile*> boot_set(boot_vector.begin(), boot_vector.end());

  for (const std::unique_ptr<const OatFile>& oat_file : oat_files_) {
    if (boot_set.find(oat_file.get()) == boot_set.end()) {
      // This method is called during runtime initialization before we can call
      // Runtime::Current()->DenyArtApexDataFiles(). Since we don't want to fail hard if
      // the ART APEX data files are untrusted, just treat them as trusted for the check here.
      const bool trust_art_apex_data_files = true;
      if (!LocationIsTrusted(oat_file->GetLocation(), trust_art_apex_data_files)) {
        // When the file is not in a trusted location, we check whether the oat file has any
        // AOT or DEX code. It is a fatal error if it has.
        if (CompilerFilter::IsAotCompilationEnabled(oat_file->GetCompilerFilter()) ||
            oat_file->ContainsDexCode()) {
          LOG(FATAL) << "Executing untrusted code from " << oat_file->GetLocation();
        }
      }
    }
  }
  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";
  }
}

}  // namespace art
