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;
}