Move the implementation of JNIHelp.h's FileDescriptor helpers into JNIHelp.c.

These functions used to be declared in dalvik/ but defined in libcore/, which
was a layering violation but not important. It now stands in the way of
switching FileDescriptor's JNI over to C++, so out it goes.

There's a functional change here: the libcore code was going out of its way
to ensure that FileDescriptor's <clinit> was being invoked, but it's not
obvious that there was any reason for this: the static initializers just set
the err/in/out fields' descriptor fields to the appropriate integers.

A separate change rewrites FileDescriptor's JNI in terms of JNIHelp.h's API,
so it no longer needs to know anything about FileDescriptor itself. (Amusingly,
the original motivation for switching to C++ was to rewrite code that I've now
simply deleted.)

Change-Id: I5d79e5b91835183c21a6b7a1545178d9d93f4b69
diff --git a/libnativehelper/JNIHelp.c b/libnativehelper/JNIHelp.c
index 1dff85d..59d457b 100644
--- a/libnativehelper/JNIHelp.c
+++ b/libnativehelper/JNIHelp.c
@@ -285,3 +285,55 @@
         return ret;
     }
 }
+
+static struct CachedFields {
+    jclass fileDescriptorClass;
+    jmethodID fileDescriptorCtor;
+    jfieldID descriptorField;
+} gCachedFields;
+
+int registerJniHelp(JNIEnv* env) {
+    gCachedFields.fileDescriptorClass =
+            (*env)->NewGlobalRef(env, (*env)->FindClass(env, "java/io/FileDescriptor"));
+    if (gCachedFields.fileDescriptorClass == NULL) {
+        return -1;
+    }
+
+    gCachedFields.fileDescriptorCtor =
+            (*env)->GetMethodID(env, gCachedFields.fileDescriptorClass, "<init>", "()V");
+    if (gCachedFields.fileDescriptorCtor == NULL) {
+        return -1;
+    }
+
+    gCachedFields.descriptorField =
+            (*env)->GetFieldID(env, gCachedFields.fileDescriptorClass, "descriptor", "I");
+    if (gCachedFields.descriptorField == NULL) {
+        return -1;
+    }
+
+    return 0;
+}
+
+/*
+ * Create a java.io.FileDescriptor given an integer fd
+ */
+jobject jniCreateFileDescriptor(JNIEnv* env, int fd) {
+    jobject fileDescriptor = (*env)->NewObject(env,
+            gCachedFields.fileDescriptorClass, gCachedFields.fileDescriptorCtor);
+    jniSetFileDescriptorOfFD(env, fileDescriptor, fd);
+    return fileDescriptor;
+}
+
+/*
+ * Get an int file descriptor from a java.io.FileDescriptor
+ */
+int jniGetFDFromFileDescriptor(JNIEnv* env, jobject fileDescriptor) {
+    return (*env)->GetIntField(env, fileDescriptor, gCachedFields.descriptorField);
+}
+
+/*
+ * Set the descriptor of a java.io.FileDescriptor
+ */
+void jniSetFileDescriptorOfFD(JNIEnv* env, jobject fileDescriptor, int value) {
+    (*env)->SetIntField(env, fileDescriptor, gCachedFields.descriptorField, value);
+}
diff --git a/libnativehelper/Register.c b/libnativehelper/Register.c
index 1de679a..e3cd407 100644
--- a/libnativehelper/Register.c
+++ b/libnativehelper/Register.c
@@ -17,11 +17,13 @@
 #include "jni.h"
 
 extern int registerCoreLibrariesJni(JNIEnv* env);
+extern int registerJniHelp(JNIEnv* env);
 
 /*
  * Register all methods for system classes.
  */
 int jniRegisterSystemMethods(JNIEnv* env)
 {
-    return registerCoreLibrariesJni(env);
+    // We initialize JNIHelp.c first so that the core libraries can safely rely on it.
+    return registerJniHelp(env) != -1 && registerCoreLibrariesJni(env) != -1;
 }