am e0f789dc: Merge "Remove dead code: jniGetStackTrace."

* commit 'e0f789dcfc4ff18127fa00a6f99c5236c2e27eed':
  Remove dead code: jniGetStackTrace.
diff --git a/Android.mk b/Android.mk
index 11ba0a3..8a30e5b 100644
--- a/Android.mk
+++ b/Android.mk
@@ -18,6 +18,7 @@
 local_src_files := \
     JNIHelp.cpp \
     JniConstants.cpp \
+    JniInvocation.cpp \
     toStringArray.cpp
 
 
@@ -30,10 +31,10 @@
 LOCAL_SHARED_LIBRARIES := liblog
 LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE := libnativehelper
-
+LOCAL_CFLAGS := -Werror
 LOCAL_C_INCLUDES := external/stlport/stlport bionic/ bionic/libstdc++/include libcore/include
-LOCAL_SHARED_LIBRARIES += libstlport
-
+LOCAL_SHARED_LIBRARIES += libcutils libstlport libdl
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 include $(BUILD_SHARED_LIBRARY)
 
 
@@ -45,6 +46,9 @@
 LOCAL_MODULE := libnativehelper
 LOCAL_MODULE_TAGS := optional
 LOCAL_SRC_FILES := $(local_src_files)
+LOCAL_CFLAGS := -Werror
 LOCAL_C_INCLUDES := libcore/include
 LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_LDFLAGS := -ldl
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 include $(BUILD_HOST_SHARED_LIBRARY)
diff --git a/JniInvocation.cpp b/JniInvocation.cpp
new file mode 100644
index 0000000..e78cff8
--- /dev/null
+++ b/JniInvocation.cpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2013 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 "JniInvocation.h"
+
+#include <dlfcn.h>
+#include <stdlib.h>
+
+#include <cstddef>
+
+#define LOG_TAG "JniInvocation"
+#include "cutils/log.h"
+
+#ifdef HAVE_ANDROID_OS
+#include "cutils/properties.h"
+#endif
+
+JniInvocation* JniInvocation::jni_invocation_ = NULL;
+
+JniInvocation::JniInvocation() :
+    handle_(NULL),
+    JNI_GetDefaultJavaVMInitArgs_(NULL),
+    JNI_CreateJavaVM_(NULL),
+    JNI_GetCreatedJavaVMs_(NULL) {
+
+  LOG_ALWAYS_FATAL_IF(jni_invocation_ != NULL, "JniInvocation instance already initialized");
+  jni_invocation_ = this;
+}
+
+JniInvocation::~JniInvocation() {
+  jni_invocation_ = NULL;
+  if (handle_ != NULL) {
+    dlclose(handle_);
+  }
+}
+
+bool JniInvocation::Init(const char* library) {
+#ifdef HAVE_ANDROID_OS
+  char default_library[PROPERTY_VALUE_MAX];
+  property_get("persist.sys.dalvik.vm.lib", default_library, "libdvm.so");
+#else
+  const char* default_library = "libdvm.so";
+#endif
+  if (library == NULL) {
+    library = default_library;
+  }
+
+  handle_ = dlopen(library, RTLD_NOW);
+  if (handle_ == NULL) {
+    ALOGE("Failed to dlopen %s: %s", library, dlerror());
+    return false;
+  }
+  if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetDefaultJavaVMInitArgs_),
+                  "JNI_GetDefaultJavaVMInitArgs")) {
+    return false;
+  }
+  if (!FindSymbol(reinterpret_cast<void**>(&JNI_CreateJavaVM_),
+                  "JNI_CreateJavaVM")) {
+    return false;
+  }
+  if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetCreatedJavaVMs_),
+                  "JNI_GetCreatedJavaVMs")) {
+    return false;
+  }
+  return true;
+}
+
+jint JniInvocation::JNI_GetDefaultJavaVMInitArgs(void* vmargs) {
+  return JNI_GetDefaultJavaVMInitArgs_(vmargs);
+}
+
+jint JniInvocation::JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
+  return JNI_CreateJavaVM_(p_vm, p_env, vm_args);
+}
+
+jint JniInvocation::JNI_GetCreatedJavaVMs(JavaVM** vms, jsize size, jsize* vm_count) {
+  return JNI_GetCreatedJavaVMs_(vms, size, vm_count);
+}
+
+bool JniInvocation::FindSymbol(void** pointer, const char* symbol) {
+  *pointer = dlsym(handle_, symbol);
+  if (*pointer == NULL) {
+    ALOGE("Failed to find symbol %s: %s\n", symbol, dlerror());
+    dlclose(handle_);
+    handle_ = NULL;
+    return false;
+  }
+  return true;
+}
+
+JniInvocation& JniInvocation::GetJniInvocation() {
+  LOG_ALWAYS_FATAL_IF(jni_invocation_ == NULL,
+                      "Failed to create JniInvocation instance before using JNI invocation API");
+  return *jni_invocation_;
+}
+
+extern "C" jint JNI_GetDefaultJavaVMInitArgs(void* vm_args) {
+  return JniInvocation::GetJniInvocation().JNI_GetDefaultJavaVMInitArgs(vm_args);
+}
+
+extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
+  return JniInvocation::GetJniInvocation().JNI_CreateJavaVM(p_vm, p_env, vm_args);
+}
+
+extern "C" jint JNI_GetCreatedJavaVMs(JavaVM** vms, jsize size, jsize* vm_count) {
+  return JniInvocation::GetJniInvocation().JNI_GetCreatedJavaVMs(vms, size, vm_count);
+}
diff --git a/include/nativehelper/JniInvocation.h b/include/nativehelper/JniInvocation.h
new file mode 100644
index 0000000..9876d8d
--- /dev/null
+++ b/include/nativehelper/JniInvocation.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#ifndef JNI_INVOCATION_H_included
+#define JNI_INVOCATION_H_included
+
+#include <jni.h>
+
+// JniInvocation adds a layer of indirection for applications using
+// the JNI invocation API to allow the JNI implementation to be
+// selected dynamically. Apps can specify a specific implementation to
+// be used by calling InitJniInvocation. If this is not done, the
+// library will chosen based on the value of Android system property
+// persist.sys.dalvik.vm.lib on the device, and otherwise fall back to
+// a hard-coded default implementation.
+class JniInvocation {
+ public:
+  JniInvocation();
+
+  ~JniInvocation();
+
+  // Initialize JNI invocation API. library should specifiy a valid
+  // shared library for opening via dlopen providing a JNI invocation
+  // implementation, or null to allow defaulting via
+  // persist.sys.dalvik.vm.lib.
+  bool Init(const char* library);
+
+ private:
+
+  bool FindSymbol(void** pointer, const char* symbol);
+
+  static JniInvocation& GetJniInvocation();
+
+  jint JNI_GetDefaultJavaVMInitArgs(void* vmargs);
+  jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args);
+  jint JNI_GetCreatedJavaVMs(JavaVM** vms, jsize size, jsize* vm_count);
+
+  static JniInvocation* jni_invocation_;
+
+  void* handle_;
+  jint (*JNI_GetDefaultJavaVMInitArgs_)(void*);
+  jint (*JNI_CreateJavaVM_)(JavaVM**, JNIEnv**, void*);
+  jint (*JNI_GetCreatedJavaVMs_)(JavaVM**, jsize, jsize*);
+
+  friend jint JNI_GetDefaultJavaVMInitArgs(void* vm_args);
+  friend jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args);
+  friend jint JNI_GetCreatedJavaVMs(JavaVM** vms, jsize size, jsize* vm_count);
+};
+
+#endif  // JNI_INVOCATION_H_included