Workaround for apps using a copy of libnativehelper

When this library is loaded by app via greylist
it ends up having its own copy of the library which does
not have JNI constants properly initialized.

This workaround checks the initialization status and
initializes them lazily in this case.

Bug: http://b/27724707
Change-Id: I4d12913c86a7e8e86c910c90316fc0b94190ac94
(cherry picked from commit 3c9164503aed5e8837480267d77917c3f33cbb9f)
diff --git a/JniConstants.cpp b/JniConstants.cpp
index 46df126..43ad419 100644
--- a/JniConstants.cpp
+++ b/JniConstants.cpp
@@ -22,6 +22,12 @@
 
 #include <stdlib.h>
 
+#include <atomic>
+#include <mutex>
+
+static std::atomic<bool> g_constants_initialized(false);
+static std::mutex g_constants_mutex;
+
 jclass JniConstants::booleanClass;
 jclass JniConstants::byteArrayClass;
 jclass JniConstants::calendarClass;
@@ -72,6 +78,19 @@
 }
 
 void JniConstants::init(JNIEnv* env) {
+    // Fast check
+    if (g_constants_initialized) {
+      // already initialized
+      return;
+    }
+
+    // Slightly slower check
+    std::lock_guard<std::mutex> guard(g_constants_mutex);
+    if (g_constants_initialized) {
+      // already initialized
+      return;
+    }
+
     booleanClass = findClass(env, "java/lang/Boolean");
     byteArrayClass = findClass(env, "[B");
     calendarClass = findClass(env, "java/util/Calendar");
@@ -110,4 +129,6 @@
     structUtsnameClass = findClass(env, "android/system/StructUtsname");
     unixSocketAddressClass = findClass(env, "android/system/UnixSocketAddress");
     zipEntryClass = findClass(env, "java/util/zip/ZipEntry");
+
+    g_constants_initialized = true;
 }