/*
 * 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_file_assistant.h"
#include "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
