/*
 * 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 "base/file_utils.h"
#include "class_loader_utils.h"
#include "jni.h"
#include "nativehelper/scoped_utf_chars.h"
#include "oat/oat_file_assistant.h"
#include "oat/oat_file_manager.h"
#include "scoped_thread_state_change-inl.h"
#include "thread.h"

namespace art {
namespace Test692VdexInmemLoader {

extern "C" JNIEXPORT void JNICALL Java_Main_waitForVerifier(JNIEnv*, jclass) {
  Runtime::Current()->GetOatFileManager().WaitForBackgroundVerificationTasks();
}

extern "C" JNIEXPORT void JNICALL Java_Main_setProcessDataDir(JNIEnv* env, jclass, jstring jpath) {
  const char* path = env->GetStringUTFChars(jpath, nullptr);
  Runtime::Current()->SetProcessDataDirectory(path);
  env->ReleaseStringUTFChars(jpath, path);
}

extern "C" JNIEXPORT jboolean JNICALL Java_Main_areClassesVerified(JNIEnv*,
                                                                   jclass,
                                                                   jobject loader) {
  ScopedObjectAccess soa(Thread::Current());
  StackHandleScope<2> hs(soa.Self());
  Handle<mirror::ClassLoader> h_loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(loader)));

  std::vector<const DexFile*> dex_files;
  VisitClassLoaderDexFiles(
      soa.Self(),
      h_loader,
      [&](const DexFile* dex_file) {
        dex_files.push_back(dex_file);
        return true;
      });

  MutableHandle<mirror::Class> h_class(hs.NewHandle<mirror::Class>(nullptr));
  ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();

  bool is_first = true;
  bool all_verified = false;
  for (const DexFile* dex_file : dex_files) {
    for (uint16_t cdef_idx = 0; cdef_idx < dex_file->NumClassDefs(); ++cdef_idx) {
      const char* desc = dex_file->GetClassDescriptor(dex_file->GetClassDef(cdef_idx));
      h_class.Assign(class_linker->FindClass(soa.Self(), desc, h_loader));
      CHECK(h_class != nullptr) << "Could not find class " << desc;
      bool is_verified = h_class->IsVerified();
      if (is_first) {
        all_verified = is_verified;
        is_first = false;
      } else if (all_verified != is_verified) {
        // Classes should either all or none be verified.
        LOG(ERROR) << "areClassesVerified is inconsistent";
      }
    }
  }
  return all_verified ? JNI_TRUE : JNI_FALSE;
}

extern "C" JNIEXPORT bool JNICALL Java_Main_hasVdexFile(JNIEnv*,
                                                        jclass,
                                                        jobject loader) {
  ScopedObjectAccess soa(Thread::Current());
  StackHandleScope<1> hs(soa.Self());
  Handle<mirror::ClassLoader> h_loader = hs.NewHandle(soa.Decode<mirror::ClassLoader>(loader));

  std::vector<const DexFile*> dex_files;
  VisitClassLoaderDexFiles(
      soa.Self(),
      h_loader,
      [&](const DexFile* dex_file) {
        dex_files.push_back(dex_file);
        return true;
      });

  std::string dex_location = dex_files[0]->GetLocation();
  std::string odex_filename;
  std::string error_msg;
  if (!OatFileAssistant::DexLocationToOdexFilename(dex_location,
                                                   kRuntimeISA,
                                                   &odex_filename,
                                                   &error_msg)) {
    LOG(WARNING) << "Could not get odex filename for " << dex_location << ": " << error_msg;
    return false;
  }

  return OS::FileExists(GetVdexFilename(odex_filename).c_str());
}

extern "C" JNIEXPORT jboolean JNICALL Java_Main_isBackedByOatFile(JNIEnv*,
                                                                  jclass,
                                                                  jobject loader) {
  ScopedObjectAccess soa(Thread::Current());
  StackHandleScope<1> hs(soa.Self());
  Handle<mirror::ClassLoader> h_loader = hs.NewHandle(soa.Decode<mirror::ClassLoader>(loader));

  bool is_first = true;
  bool all_backed_by_oat = false;

  VisitClassLoaderDexFiles(
      soa.Self(),
      h_loader,
      [&](const DexFile* dex_file) {
        bool is_backed_by_oat = (dex_file->GetOatDexFile() != nullptr);
        if (is_first) {
          all_backed_by_oat = is_backed_by_oat;
          is_first = false;
        } else if (all_backed_by_oat != is_backed_by_oat) {
          // DexFiles should either all or none be backed by oat.
          LOG(ERROR) << "isBackedByOatFile is inconsistent";
        }
        return true;
      });
  return all_backed_by_oat ? JNI_TRUE : JNI_FALSE;
}

extern "C" JNIEXPORT jboolean JNICALL Java_Main_areClassesPreverified(JNIEnv*,
                                                                      jclass,
                                                                      jobject loader) {
  ScopedObjectAccess soa(Thread::Current());
  StackHandleScope<2> hs(soa.Self());
  Handle<mirror::ClassLoader> h_loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(loader)));

  std::vector<const DexFile*> dex_files;
  VisitClassLoaderDexFiles(
      soa.Self(),
      h_loader,
      [&](const DexFile* dex_file) {
        dex_files.push_back(dex_file);
        return true;
      });

  MutableHandle<mirror::Class> h_class(hs.NewHandle<mirror::Class>(nullptr));
  ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();

  bool is_first = true;
  bool all_preverified = false;
  for (const DexFile* dex_file : dex_files) {
    for (uint16_t cdef_idx = 0; cdef_idx < dex_file->NumClassDefs(); ++cdef_idx) {
      const char* desc = dex_file->GetClassDescriptor(dex_file->GetClassDef(cdef_idx));
      h_class.Assign(class_linker->FindClass(soa.Self(), desc, h_loader));
      CHECK(h_class != nullptr) << "Could not find class " << desc;

      ClassStatus oat_file_class_status(ClassStatus::kNotReady);
      bool is_preverified = class_linker->VerifyClassUsingOatFile(
          soa.Self(), *dex_file, h_class, oat_file_class_status);

      if (is_first) {
        all_preverified = is_preverified;
        is_first = false;
      } else if (all_preverified != is_preverified) {
        // Classes should either all or none be preverified.
        LOG(ERROR) << "areClassesPreverified is inconsistent";
      }
    }
  }

  return all_preverified ? JNI_TRUE : JNI_FALSE;
}

extern "C" JNIEXPORT jint JNICALL Java_Main_getVdexCacheSize(JNIEnv*, jclass) {
  return static_cast<jint>(OatFileManager::kAnonymousVdexCacheSize);
}

extern "C" JNIEXPORT jboolean JNICALL Java_Main_isAnonymousVdexBasename(JNIEnv* env,
                                                                        jclass,
                                                                        jstring basename) {
  if (basename == nullptr) {
    return JNI_FALSE;
  }
  ScopedUtfChars basename_utf(env, basename);
  return OatFileAssistant::IsAnonymousVdexBasename(basename_utf.c_str()) ? JNI_TRUE : JNI_FALSE;
}

}  // namespace Test692VdexInmemLoader
}  // namespace art
