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

#ifdef ART_TARGET_ANDROID
#include <sys/resource.h>
#include <sys/time.h>
extern "C" void android_set_application_target_sdk_version(uint32_t version);
#endif
#include <inttypes.h>
#include <limits>
#include <limits.h>
#include "nativehelper/scoped_utf_chars.h"

#include <android-base/stringprintf.h>
#include <android-base/strings.h>

#include "android-base/properties.h"
#include "arch/instruction_set.h"
#include "art_method-inl.h"
#include "base/pointer_size.h"
#include "base/sdk_version.h"
#include "class_linker-inl.h"
#include "class_loader_context.h"
#include "common_throws.h"
#include "debugger.h"
#include "dex/class_accessor-inl.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_file_types.h"
#include "gc/accounting/card_table-inl.h"
#include "gc/allocator/art-dlmalloc.h"
#include "gc/heap.h"
#include "gc/space/dlmalloc_space.h"
#include "gc/space/image_space.h"
#include "gc/task_processor.h"
#include "intern_table.h"
#include "jit/jit.h"
#include "jni/java_vm_ext.h"
#include "jni/jni_internal.h"
#include "mirror/array-alloc-inl.h"
#include "mirror/class-inl.h"
#include "mirror/dex_cache-inl.h"
#include "mirror/object-inl.h"
#include "native_util.h"
#include "nativehelper/jni_macros.h"
#include "nativehelper/scoped_local_ref.h"
#include "runtime.h"
#include "scoped_fast_native_object_access-inl.h"
#include "scoped_thread_state_change-inl.h"
#include "startup_completed_task.h"
#include "string_array_utils.h"
#include "thread-inl.h"
#include "thread_list.h"

namespace art HIDDEN {

using android::base::StringPrintf;

static jfloat VMRuntime_getTargetHeapUtilization(JNIEnv*, jobject) {
  return Runtime::Current()->GetHeap()->GetTargetHeapUtilization();
}

static void VMRuntime_nativeSetTargetHeapUtilization(JNIEnv*, jobject, jfloat target) {
  Runtime::Current()->GetHeap()->SetTargetHeapUtilization(target);
}

static void VMRuntime_setHiddenApiExemptions(JNIEnv* env,
                                            jclass,
                                            jobjectArray exemptions) {
  std::vector<std::string> exemptions_vec;
  int exemptions_length = env->GetArrayLength(exemptions);
  for (int i = 0; i < exemptions_length; i++) {
    jstring exemption = reinterpret_cast<jstring>(env->GetObjectArrayElement(exemptions, i));
    const char* raw_exemption = env->GetStringUTFChars(exemption, nullptr);
    exemptions_vec.push_back(raw_exemption);
    env->ReleaseStringUTFChars(exemption, raw_exemption);
  }

  Runtime::Current()->SetHiddenApiExemptions(exemptions_vec);
}

static void VMRuntime_setHiddenApiAccessLogSamplingRate(JNIEnv*, jclass, jint rate) {
  Runtime::Current()->SetHiddenApiEventLogSampleRate(rate);
}

static jobject VMRuntime_newNonMovableArray(JNIEnv* env, jobject, jclass javaElementClass,
                                            jint length) {
  ScopedFastNativeObjectAccess soa(env);
  if (UNLIKELY(length < 0)) {
    ThrowNegativeArraySizeException(length);
    return nullptr;
  }
  ObjPtr<mirror::Class> element_class = soa.Decode<mirror::Class>(javaElementClass);
  if (UNLIKELY(element_class == nullptr)) {
    ThrowNullPointerException("element class == null");
    return nullptr;
  }
  Runtime* runtime = Runtime::Current();
  ObjPtr<mirror::Class> array_class =
      runtime->GetClassLinker()->FindArrayClass(soa.Self(), element_class);
  if (UNLIKELY(array_class == nullptr)) {
    return nullptr;
  }
  gc::AllocatorType allocator = runtime->GetHeap()->GetCurrentNonMovingAllocator();
  ObjPtr<mirror::Array> result = mirror::Array::Alloc(soa.Self(),
                                                      array_class,
                                                      length,
                                                      array_class->GetComponentSizeShift(),
                                                      allocator);
  return soa.AddLocalReference<jobject>(result);
}

static jobject VMRuntime_newUnpaddedArray(JNIEnv* env, jobject, jclass javaElementClass,
                                          jint length) {
  ScopedFastNativeObjectAccess soa(env);
  if (UNLIKELY(length < 0)) {
    ThrowNegativeArraySizeException(length);
    return nullptr;
  }
  ObjPtr<mirror::Class> element_class = soa.Decode<mirror::Class>(javaElementClass);
  if (UNLIKELY(element_class == nullptr)) {
    ThrowNullPointerException("element class == null");
    return nullptr;
  }
  Runtime* runtime = Runtime::Current();
  ObjPtr<mirror::Class> array_class = runtime->GetClassLinker()->FindArrayClass(soa.Self(),
                                                                                element_class);
  if (UNLIKELY(array_class == nullptr)) {
    return nullptr;
  }
  gc::AllocatorType allocator = runtime->GetHeap()->GetCurrentAllocator();
  ObjPtr<mirror::Array> result =
      mirror::Array::Alloc</*kIsInstrumented=*/ true, /*kFillUsable=*/ true>(
          soa.Self(),
          array_class,
          length,
          array_class->GetComponentSizeShift(),
          allocator);
  return soa.AddLocalReference<jobject>(result);
}

static jlong VMRuntime_addressOf(JNIEnv* env, jobject, jobject javaArray) {
  if (javaArray == nullptr) {  // Most likely allocation failed
    return 0;
  }
  ScopedFastNativeObjectAccess soa(env);
  ObjPtr<mirror::Array> array = soa.Decode<mirror::Array>(javaArray);
  if (!array->IsArrayInstance()) {
    ThrowIllegalArgumentException("not an array");
    return 0;
  }
  if (array->IsObjectArray()) {
    ThrowIllegalArgumentException("not a primitive array");
    return 0;
  }
  if (Runtime::Current()->GetHeap()->IsMovableObject(array)) {
    ThrowRuntimeException("Trying to get address of movable array object");
    return 0;
  }
  return reinterpret_cast<uintptr_t>(array->GetRawData(array->GetClass()->GetComponentSize(), 0));
}

static void VMRuntime_clearGrowthLimit(JNIEnv*, jobject) {
  Runtime::Current()->GetHeap()->ClearGrowthLimit();
}

static void VMRuntime_clampGrowthLimit(JNIEnv*, jobject) {
  Runtime::Current()->GetHeap()->ClampGrowthLimit();
}

static jboolean VMRuntime_isNativeDebuggable(JNIEnv*, jobject) {
  return Runtime::Current()->IsNativeDebuggable();
}

static jboolean VMRuntime_isJavaDebuggable(JNIEnv*, jobject) {
  return Runtime::Current()->IsJavaDebuggable();
}

static jobjectArray VMRuntime_properties(JNIEnv* env, jobject) {
  const std::vector<std::string>& properties = Runtime::Current()->GetProperties();
  ScopedObjectAccess soa(Thread::ForEnv(env));
  return soa.AddLocalReference<jobjectArray>(CreateStringArray(soa.Self(), properties));
}

// This is for backward compatibility with dalvik which returned the
// meaningless "." when no boot classpath or classpath was
// specified. Unfortunately, some tests were using java.class.path to
// lookup relative file locations, so they are counting on this to be
// ".", presumably some applications or libraries could have as well.
static const char* DefaultToDot(const std::string& class_path) {
  return class_path.empty() ? "." : class_path.c_str();
}

static jstring VMRuntime_bootClassPath(JNIEnv* env, jobject) {
  std::string boot_class_path = android::base::Join(Runtime::Current()->GetBootClassPath(), ':');
  return env->NewStringUTF(DefaultToDot(boot_class_path));
}

static jstring VMRuntime_classPath(JNIEnv* env, jobject) {
  return env->NewStringUTF(DefaultToDot(Runtime::Current()->GetClassPathString()));
}

static jstring VMRuntime_vmVersion(JNIEnv* env, jobject) {
  return env->NewStringUTF(Runtime::GetVersion());
}

static jstring VMRuntime_vmLibrary(JNIEnv* env, jobject) {
  return env->NewStringUTF(kIsDebugBuild ? "libartd.so" : "libart.so");
}

static jstring VMRuntime_vmInstructionSet(JNIEnv* env, jobject) {
  InstructionSet isa = Runtime::Current()->GetInstructionSet();
  const char* isa_string = GetInstructionSetString(isa);
  return env->NewStringUTF(isa_string);
}

static jboolean VMRuntime_is64Bit(JNIEnv*, jobject) {
  bool is64BitMode = (sizeof(void*) == sizeof(uint64_t));
  return is64BitMode ? JNI_TRUE : JNI_FALSE;
}

static jboolean VMRuntime_isCheckJniEnabled(JNIEnv* env, jobject) {
  return down_cast<JNIEnvExt*>(env)->GetVm()->IsCheckJniEnabled() ? JNI_TRUE : JNI_FALSE;
}

static jint VMRuntime_getSdkVersionNative([[maybe_unused]] JNIEnv* env,
                                          [[maybe_unused]] jclass klass,
                                          jint default_sdk_version) {
  return android::base::GetIntProperty("ro.build.version.sdk",
                                       default_sdk_version);
}

static void VMRuntime_setTargetSdkVersionNative(JNIEnv*, jobject, jint target_sdk_version) {
  // This is the target SDK version of the app we're about to run. It is intended that this a place
  // where workarounds can be enabled.
  // Note that targetSdkVersion may be CUR_DEVELOPMENT (10000).
  // Note that targetSdkVersion may be 0, meaning "current".
  uint32_t uint_target_sdk_version =
      target_sdk_version <= 0 ? static_cast<uint32_t>(SdkVersion::kUnset)
                              : static_cast<uint32_t>(target_sdk_version);
  Runtime::Current()->SetTargetSdkVersion(uint_target_sdk_version);

#ifdef ART_TARGET_ANDROID
  // This part is letting libc/dynamic linker know about current app's
  // target sdk version to enable compatibility workarounds.
  android_set_application_target_sdk_version(uint_target_sdk_version);
#endif
}

static void VMRuntime_setDisabledCompatChangesNative(JNIEnv* env, jobject,
    jlongArray disabled_compat_changes) {
  if (disabled_compat_changes == nullptr) {
    return;
  }
  std::set<uint64_t> disabled_compat_changes_set;
  {
    ScopedObjectAccess soa(env);
    ObjPtr<mirror::LongArray> array = soa.Decode<mirror::LongArray>(disabled_compat_changes);
    int length = array->GetLength();
    for (int i = 0; i < length; i++) {
      disabled_compat_changes_set.insert(static_cast<uint64_t>(array->Get(i)));
    }
  }
  Runtime::Current()->GetCompatFramework().SetDisabledCompatChanges(disabled_compat_changes_set);
}

static inline size_t clamp_to_size_t(jlong n) {
  if (sizeof(jlong) > sizeof(size_t)
      && UNLIKELY(n > static_cast<jlong>(std::numeric_limits<size_t>::max()))) {
    return std::numeric_limits<size_t>::max();
  } else {
    return n;
  }
}

static void VMRuntime_registerNativeAllocation(JNIEnv* env, jobject, jlong bytes) {
  if (UNLIKELY(bytes < 0)) {
    ScopedObjectAccess soa(env);
    ThrowRuntimeException("allocation size negative %" PRId64, bytes);
    return;
  }
  Runtime::Current()->GetHeap()->RegisterNativeAllocation(env, clamp_to_size_t(bytes));
}

static void VMRuntime_registerNativeFree(JNIEnv* env, jobject, jlong bytes) {
  if (UNLIKELY(bytes < 0)) {
    ScopedObjectAccess soa(env);
    ThrowRuntimeException("allocation size negative %" PRId64, bytes);
    return;
  }
  Runtime::Current()->GetHeap()->RegisterNativeFree(env, clamp_to_size_t(bytes));
}

static jint VMRuntime_getNotifyNativeInterval(JNIEnv*, jclass) {
  return Runtime::Current()->GetHeap()->GetNotifyNativeInterval();
}

static void VMRuntime_notifyNativeAllocationsInternal(JNIEnv* env, jobject) {
  Runtime::Current()->GetHeap()->NotifyNativeAllocations(env);
}

static jlong VMRuntime_getFinalizerTimeoutMs(JNIEnv*, jobject) {
  return Runtime::Current()->GetFinalizerTimeoutMs();
}

static void VMRuntime_registerSensitiveThread(JNIEnv*, jobject) {
  Runtime::Current()->RegisterSensitiveThread();
}

static void VMRuntime_updateProcessState(JNIEnv*, jobject, jint process_state) {
  Runtime* runtime = Runtime::Current();
  runtime->UpdateProcessState(static_cast<ProcessState>(process_state));
}

static void VMRuntime_notifyStartupCompleted(JNIEnv*, jobject) {
  Runtime::Current()->GetHeap()->AddHeapTask(new StartupCompletedTask(NanoTime()));
}

static void VMRuntime_trimHeap(JNIEnv* env, jobject) {
  Runtime::Current()->GetHeap()->Trim(Thread::ForEnv(env));
}

static void VMRuntime_requestHeapTrim(JNIEnv* env, jobject) {
  Runtime::Current()->GetHeap()->RequestTrim(Thread::ForEnv(env));
}

static void VMRuntime_requestConcurrentGC(JNIEnv* env, jobject) {
  gc::Heap *heap = Runtime::Current()->GetHeap();
  heap->RequestConcurrentGC(Thread::ForEnv(env),
                            gc::kGcCauseBackground,
                            true,
                            heap->GetCurrentGcNum());
}

static void VMRuntime_startHeapTaskProcessor(JNIEnv* env, jobject) {
  Runtime::Current()->GetHeap()->GetTaskProcessor()->Start(Thread::ForEnv(env));
}

static void VMRuntime_stopHeapTaskProcessor(JNIEnv* env, jobject) {
  Runtime::Current()->GetHeap()->GetTaskProcessor()->Stop(Thread::ForEnv(env));
}

static void VMRuntime_runHeapTasks(JNIEnv* env, jobject) {
  Runtime::Current()->GetHeap()->GetTaskProcessor()->RunAllTasks(Thread::ForEnv(env));
}

static void VMRuntime_preloadDexCaches([[maybe_unused]] JNIEnv* env, jobject) {}

/*
 * This is called by the framework after it loads a code path on behalf of the app.
 * The code_path_type indicates the type of the apk being loaded and can be used
 * for more precise telemetry (e.g. is the split apk odex up to date?) and debugging.
 */
static void VMRuntime_registerAppInfo(JNIEnv* env,
                                      [[maybe_unused]] jclass clazz,
                                      jstring package_name,
                                      jstring cur_profile_file,
                                      jstring ref_profile_file,
                                      jobjectArray code_paths,
                                      jint code_path_type) {
  std::vector<std::string> code_paths_vec;
  int code_paths_length = env->GetArrayLength(code_paths);
  for (int i = 0; i < code_paths_length; i++) {
    jstring code_path = reinterpret_cast<jstring>(env->GetObjectArrayElement(code_paths, i));
    const char* raw_code_path = env->GetStringUTFChars(code_path, nullptr);
    code_paths_vec.push_back(raw_code_path);
    env->ReleaseStringUTFChars(code_path, raw_code_path);
  }

  const char* raw_cur_profile_file = env->GetStringUTFChars(cur_profile_file, nullptr);
  std::string cur_profile_file_str(raw_cur_profile_file);
  env->ReleaseStringUTFChars(cur_profile_file, raw_cur_profile_file);

  const char* raw_ref_profile_file = env->GetStringUTFChars(ref_profile_file, nullptr);
  std::string ref_profile_file_str(raw_ref_profile_file);
  env->ReleaseStringUTFChars(ref_profile_file, raw_ref_profile_file);

  const char* raw_package_name = env->GetStringUTFChars(package_name, nullptr);
  std::string package_name_str(raw_package_name);
  env->ReleaseStringUTFChars(package_name, raw_package_name);

  Runtime::Current()->RegisterAppInfo(
      package_name_str,
      code_paths_vec,
      cur_profile_file_str,
      ref_profile_file_str,
      static_cast<int32_t>(code_path_type));
}

static jboolean VMRuntime_isBootClassPathOnDisk(JNIEnv* env, jclass, jstring java_instruction_set) {
  ScopedUtfChars instruction_set(env, java_instruction_set);
  if (instruction_set.c_str() == nullptr) {
    return JNI_FALSE;
  }
  InstructionSet isa = GetInstructionSetFromString(instruction_set.c_str());
  if (isa == InstructionSet::kNone) {
    ScopedLocalRef<jclass> iae(env, env->FindClass("java/lang/IllegalArgumentException"));
    std::string message(StringPrintf("Instruction set %s is invalid.", instruction_set.c_str()));
    env->ThrowNew(iae.get(), message.c_str());
    return JNI_FALSE;
  }
  return gc::space::ImageSpace::IsBootClassPathOnDisk(isa);
}

static jstring VMRuntime_getCurrentInstructionSet(JNIEnv* env, jclass) {
  return env->NewStringUTF(GetInstructionSetString(kRuntimeISA));
}

static void VMRuntime_setSystemDaemonThreadPriority([[maybe_unused]] JNIEnv* env,
                                                    [[maybe_unused]] jclass klass) {
#ifdef ART_TARGET_ANDROID
  Thread* self = Thread::Current();
  DCHECK(self != nullptr);
  pid_t tid = self->GetTid();
  // We use a priority lower than the default for the system daemon threads (eg HeapTaskDaemon) to
  // avoid jank due to CPU contentions between GC and other UI-related threads. b/36631902.
  // We may use a native priority that doesn't have a corresponding java.lang.Thread-level priority.
  static constexpr int kSystemDaemonNiceValue = 4;  // priority 124
  if (setpriority(PRIO_PROCESS, tid, kSystemDaemonNiceValue) != 0) {
    PLOG(INFO) << *self << " setpriority(PRIO_PROCESS, " << tid << ", "
               << kSystemDaemonNiceValue << ") failed";
  }
#endif
}

static void VMRuntime_setDedupeHiddenApiWarnings([[maybe_unused]] JNIEnv* env,
                                                 [[maybe_unused]] jclass klass,
                                                 jboolean dedupe) {
  Runtime::Current()->SetDedupeHiddenApiWarnings(dedupe);
}

static void VMRuntime_setProcessPackageName(JNIEnv* env,
                                            [[maybe_unused]] jclass klass,
                                            jstring java_package_name) {
  ScopedUtfChars package_name(env, java_package_name);
  Runtime::Current()->SetProcessPackageName(package_name.c_str());
}

static void VMRuntime_setProcessDataDirectory(JNIEnv* env, jclass, jstring java_data_dir) {
  ScopedUtfChars data_dir(env, java_data_dir);
  Runtime::Current()->SetProcessDataDirectory(data_dir.c_str());
}

static void VMRuntime_bootCompleted([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass klass) {
  jit::Jit* jit = Runtime::Current()->GetJit();
  if (jit != nullptr) {
    jit->BootCompleted();
  }
}

class ClearJitCountersVisitor : public ClassVisitor {
 public:
  bool operator()(ObjPtr<mirror::Class> klass) override REQUIRES_SHARED(Locks::mutator_lock_) {
    // Avoid some types of classes that don't need their methods visited.
    if (klass->IsProxyClass() ||
        klass->IsArrayClass() ||
        klass->IsPrimitive() ||
        !klass->IsResolved() ||
        klass->IsErroneousResolved()) {
      return true;
    }
    uint16_t threshold = Runtime::Current()->GetJITOptions()->GetWarmupThreshold();
    for (ArtMethod& m : klass->GetMethods(kRuntimePointerSize)) {
      if (!m.IsAbstract()) {
        m.ResetCounter(threshold);
      }
    }
    return true;
  }
};

static void VMRuntime_resetJitCounters(JNIEnv* env, [[maybe_unused]] jclass klass) {
  ScopedObjectAccess soa(env);
  ClearJitCountersVisitor visitor;
  Runtime::Current()->GetClassLinker()->VisitClasses(&visitor);
}

static jboolean VMRuntime_isValidClassLoaderContext(JNIEnv* env,
                                                    [[maybe_unused]] jclass klass,
                                                    jstring jencoded_class_loader_context) {
  if (UNLIKELY(jencoded_class_loader_context == nullptr)) {
    ScopedFastNativeObjectAccess soa(env);
    ThrowNullPointerException("encoded_class_loader_context == null");
    return false;
  }
  ScopedUtfChars encoded_class_loader_context(env, jencoded_class_loader_context);
  return ClassLoaderContext::IsValidEncoding(encoded_class_loader_context.c_str());
}

static jobject VMRuntime_getBaseApkOptimizationInfo(JNIEnv* env, [[maybe_unused]] jclass klass) {
  AppInfo* app_info = Runtime::Current()->GetAppInfo();
  DCHECK(app_info != nullptr);

  std::string compiler_filter;
  std::string compilation_reason;
  app_info->GetPrimaryApkOptimizationStatus(&compiler_filter, &compilation_reason);

  ScopedLocalRef<jclass> cls(env, env->FindClass("dalvik/system/DexFile$OptimizationInfo"));
  if (cls == nullptr) {
    DCHECK(env->ExceptionCheck());
    return nullptr;
  }

  jmethodID ctor = env->GetMethodID(cls.get(), "<init>", "(Ljava/lang/String;Ljava/lang/String;)V");
  if (ctor == nullptr) {
    DCHECK(env->ExceptionCheck());
    return nullptr;
  }

  ScopedLocalRef<jstring> j_compiler_filter(env, env->NewStringUTF(compiler_filter.c_str()));
  if (j_compiler_filter == nullptr) {
    DCHECK(env->ExceptionCheck());
    return nullptr;
  }

  ScopedLocalRef<jstring> j_compilation_reason(env, env->NewStringUTF(compilation_reason.c_str()));
  if (j_compilation_reason == nullptr) {
    DCHECK(env->ExceptionCheck());
    return nullptr;
  }

  return env->NewObject(cls.get(), ctor, j_compiler_filter.get(), j_compilation_reason.get());
}

static JNINativeMethod gMethods[] = {
  FAST_NATIVE_METHOD(VMRuntime, addressOf, "(Ljava/lang/Object;)J"),
  NATIVE_METHOD(VMRuntime, bootClassPath, "()Ljava/lang/String;"),
  NATIVE_METHOD(VMRuntime, clampGrowthLimit, "()V"),
  NATIVE_METHOD(VMRuntime, classPath, "()Ljava/lang/String;"),
  NATIVE_METHOD(VMRuntime, clearGrowthLimit, "()V"),
  NATIVE_METHOD(VMRuntime, setHiddenApiExemptions, "([Ljava/lang/String;)V"),
  NATIVE_METHOD(VMRuntime, setHiddenApiAccessLogSamplingRate, "(I)V"),
  NATIVE_METHOD(VMRuntime, getTargetHeapUtilization, "()F"),
  FAST_NATIVE_METHOD(VMRuntime, isNativeDebuggable, "()Z"),
  NATIVE_METHOD(VMRuntime, isJavaDebuggable, "()Z"),
  NATIVE_METHOD(VMRuntime, nativeSetTargetHeapUtilization, "(F)V"),
  FAST_NATIVE_METHOD(VMRuntime, newNonMovableArray, "(Ljava/lang/Class;I)Ljava/lang/Object;"),
  FAST_NATIVE_METHOD(VMRuntime, newUnpaddedArray, "(Ljava/lang/Class;I)Ljava/lang/Object;"),
  NATIVE_METHOD(VMRuntime, properties, "()[Ljava/lang/String;"),
  NATIVE_METHOD(VMRuntime, getSdkVersionNative, "(I)I"),
  NATIVE_METHOD(VMRuntime, setTargetSdkVersionNative, "(I)V"),
  NATIVE_METHOD(VMRuntime, setDisabledCompatChangesNative, "([J)V"),
  NATIVE_METHOD(VMRuntime, registerNativeAllocation, "(J)V"),
  NATIVE_METHOD(VMRuntime, registerNativeFree, "(J)V"),
  NATIVE_METHOD(VMRuntime, getNotifyNativeInterval, "()I"),
  NATIVE_METHOD(VMRuntime, getFinalizerTimeoutMs, "()J"),
  NATIVE_METHOD(VMRuntime, notifyNativeAllocationsInternal, "()V"),
  NATIVE_METHOD(VMRuntime, notifyStartupCompleted, "()V"),
  NATIVE_METHOD(VMRuntime, registerSensitiveThread, "()V"),
  NATIVE_METHOD(VMRuntime, requestConcurrentGC, "()V"),
  NATIVE_METHOD(VMRuntime, requestHeapTrim, "()V"),
  NATIVE_METHOD(VMRuntime, runHeapTasks, "()V"),
  NATIVE_METHOD(VMRuntime, updateProcessState, "(I)V"),
  NATIVE_METHOD(VMRuntime, startHeapTaskProcessor, "()V"),
  NATIVE_METHOD(VMRuntime, stopHeapTaskProcessor, "()V"),
  NATIVE_METHOD(VMRuntime, trimHeap, "()V"),
  NATIVE_METHOD(VMRuntime, vmVersion, "()Ljava/lang/String;"),
  NATIVE_METHOD(VMRuntime, vmLibrary, "()Ljava/lang/String;"),
  NATIVE_METHOD(VMRuntime, vmInstructionSet, "()Ljava/lang/String;"),
  FAST_NATIVE_METHOD(VMRuntime, is64Bit, "()Z"),
  FAST_NATIVE_METHOD(VMRuntime, isCheckJniEnabled, "()Z"),
  NATIVE_METHOD(VMRuntime, preloadDexCaches, "()V"),
  NATIVE_METHOD(VMRuntime, registerAppInfo,
      "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;I)V"),
  NATIVE_METHOD(VMRuntime, isBootClassPathOnDisk, "(Ljava/lang/String;)Z"),
  NATIVE_METHOD(VMRuntime, getCurrentInstructionSet, "()Ljava/lang/String;"),
  NATIVE_METHOD(VMRuntime, setSystemDaemonThreadPriority, "()V"),
  NATIVE_METHOD(VMRuntime, setDedupeHiddenApiWarnings, "(Z)V"),
  NATIVE_METHOD(VMRuntime, setProcessPackageName, "(Ljava/lang/String;)V"),
  NATIVE_METHOD(VMRuntime, setProcessDataDirectory, "(Ljava/lang/String;)V"),
  NATIVE_METHOD(VMRuntime, bootCompleted, "()V"),
  NATIVE_METHOD(VMRuntime, resetJitCounters, "()V"),
  NATIVE_METHOD(VMRuntime, isValidClassLoaderContext, "(Ljava/lang/String;)Z"),
  NATIVE_METHOD(VMRuntime, getBaseApkOptimizationInfo,
      "()Ldalvik/system/DexFile$OptimizationInfo;"),
};

void register_dalvik_system_VMRuntime(JNIEnv* env) {
  if (Runtime::Current()->GetTargetSdkVersion() <= static_cast<uint32_t>(SdkVersion::kU)) {
    real_register_dalvik_system_VMRuntime(env);
  } else {
    Runtime::Current()->Abort(
        "Call to internal function 'register_dalvik_system_VMRuntime' is not allowed");
  }
}

void real_register_dalvik_system_VMRuntime(JNIEnv* env) {
  REGISTER_NATIVE_METHODS("dalvik/system/VMRuntime");
}

}  // namespace art
