You don't need to poke around inside FileDescriptor manually.

We can help you with that.

Note also that getParcelFileDescriptorFD did no such thing. All its callers
were passing in a regular java.io.FileDescriptor and expecting the int. No
ParcelFileDescriptors involved.

Change-Id: Idc233626f20c092e719f152562601f406cc1b64a
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 1034fbd..258ffa5 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -12,6 +12,7 @@
 #include "CreateJavaOutputStreamAdaptor.h"
 #include "AutoDecodeCancel.h"
 #include "Utils.h"
+#include "JNIHelp.h"
 
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/Asset.h>
@@ -20,7 +21,6 @@
 #include <sys/mman.h>
 #include <sys/stat.h>
 
-jclass gOptions_class;
 jfieldID gOptions_justBoundsFieldID;
 jfieldID gOptions_sampleSizeFieldID;
 jfieldID gOptions_configFieldID;
@@ -34,12 +34,8 @@
 jfieldID gOptions_mimeFieldID;
 jfieldID gOptions_mCancelID;
 jfieldID gOptions_bitmapFieldID;
-jclass gBitmap_class;
 jfieldID gBitmap_nativeBitmapFieldID;
 
-static jclass gFileDescriptor_class;
-static jfieldID gFileDescriptor_descriptor;
-
 #if 0
     #define TRACE_BITMAP(code)  code
 #else
@@ -66,7 +62,7 @@
         { SkImageDecoder::kPNG_Format,  "image/png" },
         { SkImageDecoder::kWBMP_Format, "image/vnd.wap.wbmp" }
     };
-    
+
     const char* cstr = NULL;
     for (size_t i = 0; i < SK_ARRAY_COUNT(gMimeTypes); i++) {
         if (gMimeTypes[i].fFormat == format) {
@@ -127,7 +123,7 @@
                         (allowPurgeable && optionsPurgeable(env, options));
     bool preferQualityOverSpeed = false;
     jobject javaBitmap = NULL;
-    
+
     if (NULL != options) {
         sampleSize = env->GetIntField(options, gOptions_sampleSizeFieldID);
         if (optionsJustBounds(env, options)) {
@@ -137,7 +133,7 @@
         env->SetIntField(options, gOptions_widthFieldID, -1);
         env->SetIntField(options, gOptions_heightFieldID, -1);
         env->SetObjectField(options, gOptions_mimeFieldID, 0);
-        
+
         jobject jconfig = env->GetObjectField(options, gOptions_configFieldID);
         prefConfig = GraphicsJNI::getNativeBitmapConfig(env, jconfig);
         isMutable = env->GetBooleanField(options, gOptions_mutableFieldID);
@@ -151,7 +147,7 @@
     if (NULL == decoder) {
         return nullObjectReturn("SkImageDecoder::Factory returned null");
     }
-    
+
     decoder->setSampleSize(sampleSize);
     decoder->setDitherImage(doDither);
     decoder->setPreferQualityOverSpeed(preferQualityOverSpeed);
@@ -298,8 +294,7 @@
                                           jobject bitmapFactoryOptions) {
     NPE_CHECK_RETURN_ZERO(env, fileDescriptor);
 
-    jint descriptor = env->GetIntField(fileDescriptor,
-                                       gFileDescriptor_descriptor);
+    jint descriptor = jniGetFDFromFileDescriptor(env, fileDescriptor);
 
     bool isPurgeable = optionsPurgeable(env, bitmapFactoryOptions);
     bool isShareable = optionsShareable(env, bitmapFactoryOptions);
@@ -424,7 +419,7 @@
         }
 
         for (int i = 0; i < chunk->numYDivs; i++) {
-            chunk->yDivs[i] = int(chunk->yDivs[i] * scale + 0.5f);            
+            chunk->yDivs[i] = int(chunk->yDivs[i] * scale + 0.5f);
             if (i > 0 && chunk->yDivs[i] == chunk->yDivs[i - 1]) {
                 chunk->yDivs[i]++;
             }
@@ -460,7 +455,7 @@
 }
 
 static jboolean nativeIsSeekable(JNIEnv* env, jobject, jobject fileDescriptor) {
-    jint descriptor = env->GetIntField(fileDescriptor, gFileDescriptor_descriptor);
+    jint descriptor = jniGetFDFromFileDescriptor(env, fileDescriptor);
     return ::lseek64(descriptor, 0, SEEK_CUR) != -1 ? JNI_TRUE : JNI_FALSE;
 }
 
@@ -504,12 +499,6 @@
     {   "requestCancel", "()V", (void*)nativeRequestCancel }
 };
 
-static jclass make_globalref(JNIEnv* env, const char classname[]) {
-    jclass c = env->FindClass(classname);
-    SkASSERT(c);
-    return (jclass)env->NewGlobalRef(c);
-}
-
 static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz,
                                 const char fieldname[], const char type[]) {
     jfieldID id = env->GetFieldID(clazz, fieldname, type);
@@ -517,35 +506,29 @@
     return id;
 }
 
-#define kClassPathName  "android/graphics/BitmapFactory"
-
-#define RETURN_ERR_IF_NULL(value) \
-    do { if (!(value)) { assert(0); return -1; } } while (false)
-
-int register_android_graphics_BitmapFactory(JNIEnv* env);
 int register_android_graphics_BitmapFactory(JNIEnv* env) {
-    gOptions_class = make_globalref(env, "android/graphics/BitmapFactory$Options");
-    gOptions_bitmapFieldID = getFieldIDCheck(env, gOptions_class, "inBitmap",
+    jclass options_class = env->FindClass("android/graphics/BitmapFactory$Options");
+    SkASSERT(options_class);
+    gOptions_bitmapFieldID = getFieldIDCheck(env, options_class, "inBitmap",
         "Landroid/graphics/Bitmap;");
-    gOptions_justBoundsFieldID = getFieldIDCheck(env, gOptions_class, "inJustDecodeBounds", "Z");
-    gOptions_sampleSizeFieldID = getFieldIDCheck(env, gOptions_class, "inSampleSize", "I");
-    gOptions_configFieldID = getFieldIDCheck(env, gOptions_class, "inPreferredConfig",
+    gOptions_justBoundsFieldID = getFieldIDCheck(env, options_class, "inJustDecodeBounds", "Z");
+    gOptions_sampleSizeFieldID = getFieldIDCheck(env, options_class, "inSampleSize", "I");
+    gOptions_configFieldID = getFieldIDCheck(env, options_class, "inPreferredConfig",
             "Landroid/graphics/Bitmap$Config;");
-    gOptions_mutableFieldID = getFieldIDCheck(env, gOptions_class, "inMutable", "Z");
-    gOptions_ditherFieldID = getFieldIDCheck(env, gOptions_class, "inDither", "Z");
-    gOptions_purgeableFieldID = getFieldIDCheck(env, gOptions_class, "inPurgeable", "Z");
-    gOptions_shareableFieldID = getFieldIDCheck(env, gOptions_class, "inInputShareable", "Z");
-    gOptions_preferQualityOverSpeedFieldID = getFieldIDCheck(env, gOptions_class,
+    gOptions_mutableFieldID = getFieldIDCheck(env, options_class, "inMutable", "Z");
+    gOptions_ditherFieldID = getFieldIDCheck(env, options_class, "inDither", "Z");
+    gOptions_purgeableFieldID = getFieldIDCheck(env, options_class, "inPurgeable", "Z");
+    gOptions_shareableFieldID = getFieldIDCheck(env, options_class, "inInputShareable", "Z");
+    gOptions_preferQualityOverSpeedFieldID = getFieldIDCheck(env, options_class,
             "inPreferQualityOverSpeed", "Z");
-    gOptions_widthFieldID = getFieldIDCheck(env, gOptions_class, "outWidth", "I");
-    gOptions_heightFieldID = getFieldIDCheck(env, gOptions_class, "outHeight", "I");
-    gOptions_mimeFieldID = getFieldIDCheck(env, gOptions_class, "outMimeType", "Ljava/lang/String;");
-    gOptions_mCancelID = getFieldIDCheck(env, gOptions_class, "mCancel", "Z");
+    gOptions_widthFieldID = getFieldIDCheck(env, options_class, "outWidth", "I");
+    gOptions_heightFieldID = getFieldIDCheck(env, options_class, "outHeight", "I");
+    gOptions_mimeFieldID = getFieldIDCheck(env, options_class, "outMimeType", "Ljava/lang/String;");
+    gOptions_mCancelID = getFieldIDCheck(env, options_class, "mCancel", "Z");
 
-    gBitmap_class = make_globalref(env, "android/graphics/Bitmap");
-    gBitmap_nativeBitmapFieldID = getFieldIDCheck(env, gBitmap_class, "mNativeBitmap", "I");
-    gFileDescriptor_class = make_globalref(env, "java/io/FileDescriptor");
-    gFileDescriptor_descriptor = getFieldIDCheck(env, gFileDescriptor_class, "descriptor", "I");
+    jclass bitmap_class = env->FindClass("android/graphics/Bitmap");
+    SkASSERT(bitmap_class);
+    gBitmap_nativeBitmapFieldID = getFieldIDCheck(env, bitmap_class, "mNativeBitmap", "I");
 
     int ret = AndroidRuntime::registerNativeMethods(env,
                                     "android/graphics/BitmapFactory$Options",
@@ -554,6 +537,6 @@
     if (ret) {
         return ret;
     }
-    return android::AndroidRuntime::registerNativeMethods(env, kClassPathName,
+    return android::AndroidRuntime::registerNativeMethods(env, "android/graphics/BitmapFactory",
                                          gMethods, SK_ARRAY_COUNT(gMethods));
 }
diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp
index ee3e209..d437929 100644
--- a/core/jni/android/graphics/BitmapRegionDecoder.cpp
+++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp
@@ -28,6 +28,7 @@
 #include "SkBitmapRegionDecoder.h"
 #include "CreateJavaOutputStreamAdaptor.h"
 #include "Utils.h"
+#include "JNIHelp.h"
 
 #include <android_runtime/AndroidRuntime.h>
 #include "android_util_Binder.h"
@@ -39,9 +40,6 @@
 #include <utils/Asset.h>
 #include <sys/stat.h>
 
-static jclass gFileDescriptor_class;
-static jfieldID gFileDescriptor_descriptor;
-
 #if 0
     #define TRACE_BITMAP(code)  code
 #else
@@ -111,8 +109,7 @@
                                           jobject fileDescriptor, jboolean isShareable) {
     NPE_CHECK_RETURN_ZERO(env, fileDescriptor);
 
-    jint descriptor = env->GetIntField(fileDescriptor,
-                                       gFileDescriptor_descriptor);
+    jint descriptor = jniGetFDFromFileDescriptor(env, fileDescriptor);
     SkStream *stream = NULL;
     struct stat fdStat;
     int newFD;
@@ -300,25 +297,8 @@
 
 #define kClassPathName  "android/graphics/BitmapRegionDecoder"
 
-static jclass make_globalref(JNIEnv* env, const char classname[]) {
-    jclass c = env->FindClass(classname);
-    SkASSERT(c);
-    return (jclass)env->NewGlobalRef(c);
-}
-
-static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz,
-                                const char fieldname[], const char type[]) {
-    jfieldID id = env->GetFieldID(clazz, fieldname, type);
-    SkASSERT(id);
-    return id;
-}
-
-int register_android_graphics_BitmapRegionDecoder(JNIEnv* env);
 int register_android_graphics_BitmapRegionDecoder(JNIEnv* env)
 {
-
-    gFileDescriptor_class = make_globalref(env, "java/io/FileDescriptor");
-    gFileDescriptor_descriptor = getFieldIDCheck(env, gFileDescriptor_class, "descriptor", "I");
     return android::AndroidRuntime::registerNativeMethods(env, kClassPathName,
             gBitmapRegionDecoderMethods, SK_ARRAY_COUNT(gBitmapRegionDecoderMethods));
 }
diff --git a/core/jni/android_backup_BackupDataInput.cpp b/core/jni/android_backup_BackupDataInput.cpp
index b03dd16..c174a41 100644
--- a/core/jni/android_backup_BackupDataInput.cpp
+++ b/core/jni/android_backup_BackupDataInput.cpp
@@ -25,9 +25,6 @@
 namespace android
 {
 
-// java.io.FileDescriptor
-static jfieldID s_descriptorField = 0;
-
 // android.app.backup.BackupDataInput$EntityHeader
 static jfieldID s_keyField = 0;
 static jfieldID s_dataSizeField = 0;
@@ -35,9 +32,7 @@
 static int
 ctor_native(JNIEnv* env, jobject clazz, jobject fileDescriptor)
 {
-    int err;
-
-    int fd = env->GetIntField(fileDescriptor, s_descriptorField);
+    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
     if (fd == -1) {
         return NULL;
     }
@@ -140,15 +135,7 @@
 {
     //LOGD("register_android_backup_BackupDataInput");
 
-    jclass clazz;
-
-    clazz = env->FindClass("java/io/FileDescriptor");
-    LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor");
-    s_descriptorField = env->GetFieldID(clazz, "descriptor", "I");
-    LOG_FATAL_IF(s_descriptorField == NULL,
-            "Unable to find descriptor field in java.io.FileDescriptor");
-
-    clazz = env->FindClass("android/app/backup/BackupDataInput$EntityHeader");
+    jclass clazz = env->FindClass("android/app/backup/BackupDataInput$EntityHeader");
     LOG_FATAL_IF(clazz == NULL, "Unable to find class android.app.backup.BackupDataInput.EntityHeader");
     s_keyField = env->GetFieldID(clazz, "key", "Ljava/lang/String;");
     LOG_FATAL_IF(s_keyField == NULL,
diff --git a/core/jni/android_backup_BackupDataOutput.cpp b/core/jni/android_backup_BackupDataOutput.cpp
index b895d11..144a10c 100644
--- a/core/jni/android_backup_BackupDataOutput.cpp
+++ b/core/jni/android_backup_BackupDataOutput.cpp
@@ -25,14 +25,10 @@
 namespace android
 {
 
-static jfieldID s_descriptorField = 0;
-
 static int
 ctor_native(JNIEnv* env, jobject clazz, jobject fileDescriptor)
 {
-    int err;
-
-    int fd = env->GetIntField(fileDescriptor, s_descriptorField);
+    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
     if (fd == -1) {
         return NULL;
     }
@@ -112,15 +108,6 @@
 int register_android_backup_BackupDataOutput(JNIEnv* env)
 {
     //LOGD("register_android_backup_BackupDataOutput");
-
-    jclass clazz;
-
-    clazz = env->FindClass("java/io/FileDescriptor");
-    LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor");
-    s_descriptorField = env->GetFieldID(clazz, "descriptor", "I");
-    LOG_FATAL_IF(s_descriptorField == NULL,
-            "Unable to find descriptor field in java.io.FileDescriptor");
-
     return AndroidRuntime::registerNativeMethods(env, "android/app/backup/BackupDataOutput",
             g_methods, NELEM(g_methods));
 }
diff --git a/core/jni/android_backup_BackupHelperDispatcher.cpp b/core/jni/android_backup_BackupHelperDispatcher.cpp
index 26e7d66..49f1cd4 100644
--- a/core/jni/android_backup_BackupHelperDispatcher.cpp
+++ b/core/jni/android_backup_BackupHelperDispatcher.cpp
@@ -37,8 +37,6 @@
     int nameLength; // not including the NULL terminator, which is not written to the file
 };
 
-// java.io.FileDescriptor
-static jfieldID s_descriptorField = 0;
 static jfieldID s_chunkSizeField = 0;
 static jfieldID s_keyPrefixField = 0;
 
@@ -46,12 +44,11 @@
 readHeader_native(JNIEnv* env, jobject clazz, jobject headerObj, jobject fdObj)
 {
     chunk_header_v1 flattenedHeader;
-    int fd;
     ssize_t amt;
     String8 keyPrefix;
     char* buf;
 
-    fd = env->GetIntField(fdObj, s_descriptorField);
+    int fd = jniGetFDFromFileDescriptor(env, fdObj);
 
     amt = read(fd, &flattenedHeader.headerSize, sizeof(flattenedHeader.headerSize));
     if (amt != sizeof(flattenedHeader.headerSize)) {
@@ -128,9 +125,7 @@
 static int
 skipChunk_native(JNIEnv* env, jobject clazz, jobject fdObj, jint bytesToSkip)
 {
-    int fd;
-
-    fd = env->GetIntField(fdObj, s_descriptorField);
+    int fd = jniGetFDFromFileDescriptor(env, fdObj);
 
     lseek(fd, bytesToSkip, SEEK_CUR);
 
@@ -152,9 +147,8 @@
     int nameLength;
     int namePadding;
     int headerSize;
-    int fd;
 
-    fd = env->GetIntField(fdObj, s_descriptorField);
+    int fd = jniGetFDFromFileDescriptor(env, fdObj);
 
     nameObj = (jstring)env->GetObjectField(headerObj, s_keyPrefixField);
 
@@ -166,7 +160,7 @@
     pos = lseek(fd, 0, SEEK_CUR);
 
     lseek(fd, headerSize, SEEK_CUR);
-    
+
     return pos;
 }
 
@@ -175,13 +169,12 @@
 {
     int err;
     chunk_header_v1 header;
-    int fd;
     int namePadding;
     int prevPos;
     jstring nameObj;
     const char* buf;
 
-    fd = env->GetIntField(fdObj, s_descriptorField);
+    int fd = jniGetFDFromFileDescriptor(env, fdObj);
     prevPos = lseek(fd, 0, SEEK_CUR);
 
     nameObj = (jstring)env->GetObjectField(headerObj, s_keyPrefixField);
@@ -234,15 +227,7 @@
 
 int register_android_backup_BackupHelperDispatcher(JNIEnv* env)
 {
-    jclass clazz;
-
-    clazz = env->FindClass("java/io/FileDescriptor");
-    LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor");
-    s_descriptorField = env->GetFieldID(clazz, "descriptor", "I");
-    LOG_FATAL_IF(s_descriptorField == NULL,
-            "Unable to find descriptor field in java.io.FileDescriptor");
-    
-    clazz = env->FindClass("android/app/backup/BackupHelperDispatcher$Header");
+    jclass clazz = env->FindClass("android/app/backup/BackupHelperDispatcher$Header");
     LOG_FATAL_IF(clazz == NULL,
             "Unable to find class android.app.backup.BackupHelperDispatcher.Header");
     s_chunkSizeField = env->GetFieldID(clazz, "chunkSize", "I");
@@ -251,7 +236,7 @@
     s_keyPrefixField = env->GetFieldID(clazz, "keyPrefix", "Ljava/lang/String;");
     LOG_FATAL_IF(s_keyPrefixField == NULL,
             "Unable to find keyPrefix field in android.app.backup.BackupHelperDispatcher.Header");
-    
+
     return AndroidRuntime::registerNativeMethods(env, "android/app/backup/BackupHelperDispatcher",
             g_methods, NELEM(g_methods));
 }
diff --git a/core/jni/android_backup_FileBackupHelperBase.cpp b/core/jni/android_backup_FileBackupHelperBase.cpp
index 0137a06..0dfd8db 100644
--- a/core/jni/android_backup_FileBackupHelperBase.cpp
+++ b/core/jni/android_backup_FileBackupHelperBase.cpp
@@ -25,9 +25,6 @@
 namespace android
 {
 
-// java.io.FileDescriptor
-static jfieldID s_descriptorField = 0;
-
 static int
 ctor(JNIEnv* env, jobject clazz)
 {
@@ -47,8 +44,8 @@
     int err;
 
     // all parameters have already been checked against null
-    int oldStateFD = oldState != NULL ? env->GetIntField(oldState, s_descriptorField) : -1;
-    int newStateFD = env->GetIntField(newState, s_descriptorField);
+    int oldStateFD = oldState != NULL ? jniGetFDFromFileDescriptor(env, oldState) : -1;
+    int newStateFD = jniGetFDFromFileDescriptor(env, newState);
     BackupDataWriter* dataStream = (BackupDataWriter*)data;
 
     const int fileCount = env->GetArrayLength(files);
@@ -102,7 +99,7 @@
     int err;
 
     RestoreHelperBase* restore = (RestoreHelperBase*)ptr;
-    int fd = env->GetIntField(fileDescriptor, s_descriptorField);
+    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
 
     err = restore->WriteSnapshot(fd);
 
@@ -121,14 +118,6 @@
 
 int register_android_backup_FileBackupHelperBase(JNIEnv* env)
 {
-    jclass clazz;
-
-    clazz = env->FindClass("java/io/FileDescriptor");
-    LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor");
-    s_descriptorField = env->GetFieldID(clazz, "descriptor", "I");
-    LOG_FATAL_IF(s_descriptorField == NULL,
-            "Unable to find descriptor field in java.io.FileDescriptor");
-    
     return AndroidRuntime::registerNativeMethods(env, "android/app/backup/FileBackupHelperBase",
             g_methods, NELEM(g_methods));
 }
diff --git a/core/jni/android_database_SQLiteStatement.cpp b/core/jni/android_database_SQLiteStatement.cpp
index 97e0483..05ffbb1 100644
--- a/core/jni/android_database_SQLiteStatement.cpp
+++ b/core/jni/android_database_SQLiteStatement.cpp
@@ -143,7 +143,7 @@
 static jobject createParcelFileDescriptor(JNIEnv * env, int fd)
 {
     // Create FileDescriptor object
-    jobject fileDesc = newFileDescriptor(env, fd);
+    jobject fileDesc = jniCreateFileDescriptor(env, fd);
     if (fileDesc == NULL) {
         // FileDescriptor constructor has thrown an exception
         close(fd);
diff --git a/core/jni/android_hardware_UsbDeviceConnection.cpp b/core/jni/android_hardware_UsbDeviceConnection.cpp
index e259514..4d73bf3 100644
--- a/core/jni/android_hardware_UsbDeviceConnection.cpp
+++ b/core/jni/android_hardware_UsbDeviceConnection.cpp
@@ -42,7 +42,7 @@
 android_hardware_UsbDeviceConnection_open(JNIEnv *env, jobject thiz, jstring deviceName,
         jobject fileDescriptor)
 {
-    int fd = getParcelFileDescriptorFD(env, fileDescriptor);
+    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
     // duplicate the file descriptor, since ParcelFileDescriptor will eventually close its copy
     fd = dup(fd);
     if (fd < 0)
diff --git a/core/jni/android_media_JetPlayer.cpp b/core/jni/android_media_JetPlayer.cpp
index a7ffff4..e124069 100644
--- a/core/jni/android_media_JetPlayer.cpp
+++ b/core/jni/android_media_JetPlayer.cpp
@@ -175,7 +175,7 @@
     lpJet->setEventCallback(jetPlayerEventCallback);
 
     LOGV("android_media_JetPlayer_openFileDescr(): trying to load JET file through its fd" );
-    EAS_RESULT result = lpJet->loadFromFD(getParcelFileDescriptorFD(env, fileDescriptor),
+    EAS_RESULT result = lpJet->loadFromFD(jniGetFDFromFileDescriptor(env, fileDescriptor),
         (long long)offset, (long long)length); // cast params to types used by EAS_FILE
 
     if(result==EAS_SUCCESS) {
diff --git a/core/jni/android_os_ParcelFileDescriptor.cpp b/core/jni/android_os_ParcelFileDescriptor.cpp
index 1f737f9..bfa80e1 100644
--- a/core/jni/android_os_ParcelFileDescriptor.cpp
+++ b/core/jni/android_os_ParcelFileDescriptor.cpp
@@ -29,13 +29,6 @@
 namespace android
 {
 
-static struct file_descriptor_offsets_t
-{
-    jclass mClass;
-    jmethodID mConstructor;
-    jfieldID mDescriptor;
-} gFileDescriptorOffsets;
-
 static struct socket_offsets_t
 {
     jfieldID mSocketImpl;
@@ -57,13 +50,8 @@
 {
     jobject socketImpl = env->GetObjectField(object, gSocketOffsets.mSocketImpl);
     jobject fileDescriptor = env->GetObjectField(socketImpl, gSocketImplOffsets.mFileDescriptor);
-    jint fd = env->GetIntField(fileDescriptor, gFileDescriptorOffsets.mDescriptor);
-    jobject fileDescriptorClone = env->NewObject(gFileDescriptorOffsets.mClass,
-        gFileDescriptorOffsets.mConstructor);
-    if (fileDescriptorClone != NULL) {
-        env->SetIntField(fileDescriptorClone, gFileDescriptorOffsets.mDescriptor, dup(fd));
-    }
-    return fileDescriptorClone;
+    jint fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
+    return jniCreateFileDescriptor(env, dup(fd));
 }
 
 static int android_os_ParcelFileDescriptor_createPipeNative(JNIEnv* env,
@@ -75,11 +63,7 @@
     }
 
     for (int i=0; i<2; i++) {
-        jobject fdObj = env->NewObject(gFileDescriptorOffsets.mClass,
-                gFileDescriptorOffsets.mConstructor);
-        if (fdObj != NULL) {
-            env->SetIntField(fdObj, gFileDescriptorOffsets.mDescriptor, fds[i]);
-        }
+        jobject fdObj = jniCreateFileDescriptor(env, fds[i]);
         env->SetObjectArrayElement(outFds, i, fdObj);
     }
 
@@ -90,7 +74,7 @@
 {
     jobject descriptor = env->GetObjectField(clazz, gParcelFileDescriptorOffsets.mFileDescriptor);
     if (descriptor == NULL) return -1;
-    return env->GetIntField(descriptor, gFileDescriptorOffsets.mDescriptor);
+    return jniGetFDFromFileDescriptor(env, descriptor);
 }
 
 static jlong android_os_ParcelFileDescriptor_getStatSize(JNIEnv* env,
@@ -101,16 +85,16 @@
         jniThrowException(env, "java/lang/IllegalArgumentException", "bad file descriptor");
         return -1;
     }
-    
+
     struct stat st;
     if (fstat(fd, &st) != 0) {
         return -1;
     }
-    
+
     if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
         return st.st_size;
     }
-    
+
     return -1;
 }
 
@@ -122,7 +106,7 @@
         jniThrowException(env, "java/lang/IllegalArgumentException", "bad file descriptor");
         return -1;
     }
-    
+
     return lseek(fd, pos, SEEK_SET);
 }
 
@@ -168,14 +152,6 @@
     LOG_FATAL_IF(gSocketImplOffsets.mFileDescriptor == NULL,
                  "Unable to find fd field in java.net.SocketImpl");
 
-    clazz = env->FindClass("java/io/FileDescriptor");
-    LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor");
-    gFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
-    gFileDescriptorOffsets.mConstructor = env->GetMethodID(clazz, "<init>", "()V");
-    gFileDescriptorOffsets.mDescriptor = env->GetFieldID(clazz, "descriptor", "I");
-    LOG_FATAL_IF(gFileDescriptorOffsets.mDescriptor == NULL,
-                 "Unable to find descriptor field in java.io.FileDescriptor");
-    
     clazz = env->FindClass(kParcelFileDescriptorPathName);
     LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor");
     gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 8ea7e90..b0e92e4 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -169,7 +169,7 @@
 
     env->ReleasePrimitiveArrayCritical(outOffsets, offsets, 0);
 
-    jobject fileDesc = newFileDescriptor(env, fd);
+    jobject fileDesc = jniCreateFileDescriptor(env, fd);
     if (fileDesc == NULL) {
         close(fd);
         return NULL;
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 8618b79..0681195 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -131,13 +131,6 @@
     jmethodID mLogE;
 } gLogOffsets;
 
-static struct file_descriptor_offsets_t
-{
-    jclass mClass;
-    jmethodID mConstructor;
-    jfieldID mDescriptor;
-} gFileDescriptorOffsets;
-
 static struct parcel_file_descriptor_offsets_t
 {
     jclass mClass;
@@ -591,17 +584,6 @@
     return NULL;
 }
 
-jobject newFileDescriptor(JNIEnv* env, int fd)
-{
-    jobject object = env->NewObject(
-            gFileDescriptorOffsets.mClass, gFileDescriptorOffsets.mConstructor);
-    if (object != NULL) {
-        //LOGI("Created new FileDescriptor %p with fd %d\n", object, fd);
-        env->SetIntField(object, gFileDescriptorOffsets.mDescriptor, fd);
-    }
-    return object;
-}
-
 jobject newParcelFileDescriptor(JNIEnv* env, jobject fileDesc)
 {
     return env->NewObject(
@@ -1358,8 +1340,8 @@
 {
     Parcel* parcel = parcelForJavaObject(env, clazz);
     if (parcel != NULL) {
-        const status_t err = parcel->writeDupFileDescriptor(
-                env->GetIntField(object, gFileDescriptorOffsets.mDescriptor));
+        const status_t err =
+                parcel->writeDupFileDescriptor(jniGetFDFromFileDescriptor(env, object));
         if (err != NO_ERROR) {
             jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
         }
@@ -1459,13 +1441,7 @@
         if (fd < 0) return NULL;
         fd = dup(fd);
         if (fd < 0) return NULL;
-        jobject object = env->NewObject(
-                gFileDescriptorOffsets.mClass, gFileDescriptorOffsets.mConstructor);
-        if (object != NULL) {
-            //LOGI("Created new FileDescriptor %p with fd %d\n", object, fd);
-            env->SetIntField(object, gFileDescriptorOffsets.mDescriptor, fd);
-        }
-        return object;
+        return jniCreateFileDescriptor(env, fd);
     }
     return NULL;
 }
@@ -1512,7 +1488,7 @@
         jniThrowException(env, "java/io/FileNotFoundException", strerror(errno));
         return NULL;
     }
-    jobject object = newFileDescriptor(env, fd);
+    jobject object = jniCreateFileDescriptor(env, fd);
     if (object == NULL) {
         close(fd);
     }
@@ -1525,7 +1501,7 @@
         jniThrowNullPointerException(env, NULL);
         return NULL;
     }
-    int origfd = env->GetIntField(orig, gFileDescriptorOffsets.mDescriptor);
+    int origfd = jniGetFDFromFileDescriptor(env, orig);
     if (origfd < 0) {
         jniThrowException(env, "java/lang/IllegalArgumentException", "bad FileDescriptor");
         return NULL;
@@ -1536,7 +1512,7 @@
         jniThrowIOException(env, errno);
         return NULL;
     }
-    jobject object = newFileDescriptor(env, fd);
+    jobject object = jniCreateFileDescriptor(env, fd);
     if (object == NULL) {
         close(fd);
     }
@@ -1549,9 +1525,9 @@
         jniThrowNullPointerException(env, NULL);
         return;
     }
-    int fd = env->GetIntField(object, gFileDescriptorOffsets.mDescriptor);
+    int fd = jniGetFDFromFileDescriptor(env, object);
     if (fd >= 0) {
-        env->SetIntField(object, gFileDescriptorOffsets.mDescriptor, -1);
+        jniSetFileDescriptorOfFD(env, object, -1);
         //LOGI("Closing ParcelFileDescriptor %d\n", fd);
         close(fd);
     }
@@ -1563,9 +1539,9 @@
         jniThrowNullPointerException(env, NULL);
         return;
     }
-    int fd = env->GetIntField(object, gFileDescriptorOffsets.mDescriptor);
+    int fd = jniGetFDFromFileDescriptor(env, object);
     if (fd >= 0) {
-        env->SetIntField(object, gFileDescriptorOffsets.mDescriptor, -1);
+        jniSetFileDescriptorOfFD(env, object, -1);
     }
 }
 
@@ -1794,15 +1770,6 @@
         clazz, "e", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I");
     assert(gLogOffsets.mLogE);
 
-    clazz = env->FindClass("java/io/FileDescriptor");
-    LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor");
-    gFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
-    gFileDescriptorOffsets.mConstructor
-        = env->GetMethodID(clazz, "<init>", "()V");
-    gFileDescriptorOffsets.mDescriptor = env->GetFieldID(clazz, "descriptor", "I");
-    LOG_FATAL_IF(gFileDescriptorOffsets.mDescriptor == NULL,
-                 "Unable to find descriptor field in java.io.FileDescriptor");
-
     clazz = env->FindClass("android/os/ParcelFileDescriptor");
     LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor");
     gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
@@ -1842,13 +1809,3 @@
         return -1;
     return 0;
 }
-
-namespace android {
-
-// Returns the Unix file descriptor for a ParcelFileDescriptor object
-int getParcelFileDescriptorFD(JNIEnv* env, jobject object)
-{
-    return env->GetIntField(object, gFileDescriptorOffsets.mDescriptor);
-}
-
-}
diff --git a/core/jni/android_util_Binder.h b/core/jni/android_util_Binder.h
index 495e76a..0122691 100644
--- a/core/jni/android_util_Binder.h
+++ b/core/jni/android_util_Binder.h
@@ -2,16 +2,16 @@
 **
 ** Copyright 2006, 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 
+** 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 
+**     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 
+** 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.
 */
 
@@ -29,7 +29,6 @@
 // Note: does not type checking; must guarantee jobject is a Java Parcel
 extern Parcel* parcelForJavaObject(JNIEnv* env, jobject obj);
 
-extern jobject newFileDescriptor(JNIEnv* env, int fd);
 extern jobject newParcelFileDescriptor(JNIEnv* env, jobject fileDesc);
 
 }
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index f31bba9..314c2ee 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -595,13 +595,11 @@
 // Logging
 // ----------------------------------------------------------------------------
 
-jfieldID gFileDescriptorField;
-
 static void
 android_app_ActivityThread_dumpGraphics(JNIEnv* env, jobject clazz, jobject javaFileDescriptor)
 {
 #ifdef USE_OPENGL_RENDERER
-    int fd = env->GetIntField(javaFileDescriptor, gFileDescriptorField);
+    int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
     android::uirenderer::DisplayList::outputLogBuffer(fd);
 #endif // USE_OPENGL_RENDERER
 }
@@ -736,12 +734,6 @@
 
 int register_android_app_ActivityThread(JNIEnv* env)
 {
-    jclass fileDescriptorClass = env->FindClass("java/io/FileDescriptor");
-    LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor");
-    gFileDescriptorField = env->GetFieldID(fileDescriptorClass, "descriptor", "I");
-    LOG_FATAL_IF(gFileDescriptorField == NULL,
-                 "Unable to find descriptor field in java.io.FileDescriptor");
-
     return AndroidRuntime::registerNativeMethods(
             env, kActivityThreadPathName,
             gActivityThreadMethods, NELEM(gActivityThreadMethods));
diff --git a/include/android_runtime/AndroidRuntime.h b/include/android_runtime/AndroidRuntime.h
index 22c9b72..de2d50b 100644
--- a/include/android_runtime/AndroidRuntime.h
+++ b/include/android_runtime/AndroidRuntime.h
@@ -56,7 +56,7 @@
     status_t callMain(const char* className, int argc, const char* const argv[]);
 
     /**
-     * Find a class, with the input either of the form 
+     * Find a class, with the input either of the form
      * "package/class" or "package.class".
      */
     static jclass findClass(JNIEnv* env, const char* className);
@@ -67,7 +67,7 @@
     void start();       // start in android.util.RuntimeInit
 
     static AndroidRuntime* getRuntime();
-    
+
     /**
      * This gets called after the JavaVM has initialized.  Override it
      * with the system's native entry point.
@@ -112,7 +112,7 @@
      * Thread creation helpers.
      */
     static int javaCreateThreadEtc(
-                                android_thread_func_t entryFunction, 
+                                android_thread_func_t entryFunction,
                                 void* userData,
                                 const char* threadName,
                                 int32_t threadPriority,
@@ -121,9 +121,6 @@
     static int javaThreadShell(void* args);
 };
 
-// Returns the Unix file descriptor for a ParcelFileDescriptor object
-extern int getParcelFileDescriptorFD(JNIEnv* env, jobject object);
-
 extern CursorWindow * get_window_from_object(JNIEnv * env, jobject javaWindow);
 
 }
diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp
index a219623..2ba9b3f 100644
--- a/media/jni/android_media_MediaMetadataRetriever.cpp
+++ b/media/jni/android_media_MediaMetadataRetriever.cpp
@@ -241,7 +241,7 @@
         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
         return;
     }
-    int fd = getParcelFileDescriptorFD(env, fileDescriptor);
+    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
     if (offset < 0 || length < 0 || fd < 0) {
         if (offset < 0) {
             LOGE("negative offset (%lld)", offset);
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index ecbd288..aa0adf3 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -325,7 +325,7 @@
         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
         return;
     }
-    int fd = getParcelFileDescriptorFD(env, fileDescriptor);
+    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
     LOGV("setDataSourceFD: fd %d", fd);
     process_media_player_call( env, thiz, mp->setDataSource(fd, offset, length), "java/io/IOException", "setDataSourceFD failed." );
 }
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index a8a46c1..4750b0b 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -253,7 +253,7 @@
         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
         return;
     }
-    int fd = getParcelFileDescriptorFD(env, fileDescriptor);
+    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
     sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
     status_t opStatus = mr->setOutputFile(fd, offset, length);
     process_media_recorder_call(env, opStatus, "java/io/IOException", "setOutputFile failed.");
@@ -267,7 +267,7 @@
         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
         return;
     }
-    int fd = getParcelFileDescriptorFD(env, fileDescriptor);
+    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
     sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
     status_t opStatus = mr->setOutputFileAuxiliary(fd);
     process_media_recorder_call(env, opStatus, "java/io/IOException", "setOutputFile failed.");
diff --git a/media/jni/android_media_MediaScanner.cpp b/media/jni/android_media_MediaScanner.cpp
index 06058dc..043f373 100644
--- a/media/jni/android_media_MediaScanner.cpp
+++ b/media/jni/android_media_MediaScanner.cpp
@@ -303,7 +303,7 @@
         return NULL;
     }
 
-    int fd = getParcelFileDescriptorFD(env, fileDescriptor);
+    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
     char* data = mp->extractAlbumArt(fd);
     if (!data) {
         return NULL;
@@ -426,5 +426,3 @@
     return AndroidRuntime::registerNativeMethods(env,
                 kClassMediaScanner, gMethods, NELEM(gMethods));
 }
-
-
diff --git a/media/jni/soundpool/android_media_SoundPool.cpp b/media/jni/soundpool/android_media_SoundPool.cpp
index 447f931..03d3388 100644
--- a/media/jni/soundpool/android_media_SoundPool.cpp
+++ b/media/jni/soundpool/android_media_SoundPool.cpp
@@ -60,7 +60,7 @@
     LOGV("android_media_SoundPool_load_FD");
     SoundPool *ap = MusterSoundPool(env, thiz);
     if (ap == NULL) return 0;
-    return ap->load(getParcelFileDescriptorFD(env, fileDescriptor),
+    return ap->load(jniGetFDFromFileDescriptor(env, fileDescriptor),
             int64_t(offset), int64_t(length), int(priority));
 }
 
diff --git a/services/jni/com_android_server_UsbService.cpp b/services/jni/com_android_server_UsbService.cpp
index 00ee7e3..9cd04f6 100644
--- a/services/jni/com_android_server_UsbService.cpp
+++ b/services/jni/com_android_server_UsbService.cpp
@@ -37,13 +37,6 @@
 namespace android
 {
 
-static struct file_descriptor_offsets_t
-{
-    jclass mClass;
-    jmethodID mConstructor;
-    jfieldID mDescriptor;
-} gFileDescriptorOffsets;
-
 static struct parcel_file_descriptor_offsets_t
 {
     jclass mClass;
@@ -167,11 +160,8 @@
     int newFD = dup(fd);
     usb_device_close(device);
 
-    jobject fileDescriptor = env->NewObject(gFileDescriptorOffsets.mClass,
-        gFileDescriptorOffsets.mConstructor);
-    if (fileDescriptor != NULL) {
-        env->SetIntField(fileDescriptor, gFileDescriptorOffsets.mDescriptor, newFD);
-    } else {
+    jobject fileDescriptor = jniCreateFileDescriptor(env, newFD);
+    if (fileDescriptor == NULL) {
         return NULL;
     }
     return env->NewObject(gParcelFileDescriptorOffsets.mClass,
@@ -221,11 +211,8 @@
         LOGE("could not open %s", DRIVER_NAME);
         return NULL;
     }
-    jobject fileDescriptor = env->NewObject(gFileDescriptorOffsets.mClass,
-        gFileDescriptorOffsets.mConstructor);
-    if (fileDescriptor != NULL) {
-        env->SetIntField(fileDescriptor, gFileDescriptorOffsets.mDescriptor, fd);
-    } else {
+    jobject fileDescriptor = jniCreateFileDescriptor(env, fd);
+    if (fileDescriptor == NULL) {
         return NULL;
     }
     return env->NewObject(gParcelFileDescriptorOffsets.mClass,
@@ -260,14 +247,6 @@
         return -1;
     }
 
-    clazz = env->FindClass("java/io/FileDescriptor");
-    LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor");
-    gFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
-    gFileDescriptorOffsets.mConstructor = env->GetMethodID(clazz, "<init>", "()V");
-    gFileDescriptorOffsets.mDescriptor = env->GetFieldID(clazz, "descriptor", "I");
-    LOG_FATAL_IF(gFileDescriptorOffsets.mDescriptor == NULL,
-                 "Unable to find descriptor field in java.io.FileDescriptor");
-
     clazz = env->FindClass("android/os/ParcelFileDescriptor");
     LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor");
     gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);