Home | History | Annotate | Download | only in jni
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define LOG_TAG "Parcel"
     18 //#define LOG_NDEBUG 0
     19 
     20 #include "android_os_Parcel.h"
     21 #include "android_util_Binder.h"
     22 
     23 #include "JNIHelp.h"
     24 
     25 #include <fcntl.h>
     26 #include <stdio.h>
     27 #include <sys/stat.h>
     28 #include <sys/types.h>
     29 #include <unistd.h>
     30 
     31 #include <utils/Atomic.h>
     32 #include <binder/IInterface.h>
     33 #include <binder/IPCThreadState.h>
     34 #include <utils/Log.h>
     35 #include <utils/SystemClock.h>
     36 #include <utils/List.h>
     37 #include <utils/KeyedVector.h>
     38 #include <binder/Parcel.h>
     39 #include <binder/ProcessState.h>
     40 #include <binder/IServiceManager.h>
     41 #include <utils/threads.h>
     42 #include <utils/String8.h>
     43 
     44 #include <ScopedUtfChars.h>
     45 #include <ScopedLocalRef.h>
     46 
     47 #include <android_runtime/AndroidRuntime.h>
     48 
     49 //#undef ALOGV
     50 //#define ALOGV(...) fprintf(stderr, __VA_ARGS__)
     51 
     52 #define DEBUG_DEATH 0
     53 #if DEBUG_DEATH
     54 #define LOGDEATH ALOGD
     55 #else
     56 #define LOGDEATH ALOGV
     57 #endif
     58 
     59 namespace android {
     60 
     61 static struct parcel_offsets_t
     62 {
     63     jclass clazz;
     64     jfieldID mNativePtr;
     65     jmethodID obtain;
     66     jmethodID recycle;
     67 } gParcelOffsets;
     68 
     69 Parcel* parcelForJavaObject(JNIEnv* env, jobject obj)
     70 {
     71     if (obj) {
     72         Parcel* p = (Parcel*)env->GetIntField(obj, gParcelOffsets.mNativePtr);
     73         if (p != NULL) {
     74             return p;
     75         }
     76         jniThrowException(env, "java/lang/IllegalStateException", "Parcel has been finalized!");
     77     }
     78     return NULL;
     79 }
     80 
     81 jobject createJavaParcelObject(JNIEnv* env)
     82 {
     83     return env->CallStaticObjectMethod(gParcelOffsets.clazz, gParcelOffsets.obtain);
     84 }
     85 
     86 void recycleJavaParcelObject(JNIEnv* env, jobject parcelObj)
     87 {
     88     env->CallVoidMethod(parcelObj, gParcelOffsets.recycle);
     89 }
     90 
     91 static jint android_os_Parcel_dataSize(JNIEnv* env, jclass clazz, jint nativePtr)
     92 {
     93     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
     94     return parcel ? parcel->dataSize() : 0;
     95 }
     96 
     97 static jint android_os_Parcel_dataAvail(JNIEnv* env, jclass clazz, jint nativePtr)
     98 {
     99     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    100     return parcel ? parcel->dataAvail() : 0;
    101 }
    102 
    103 static jint android_os_Parcel_dataPosition(JNIEnv* env, jclass clazz, jint nativePtr)
    104 {
    105     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    106     return parcel ? parcel->dataPosition() : 0;
    107 }
    108 
    109 static jint android_os_Parcel_dataCapacity(JNIEnv* env, jclass clazz, jint nativePtr)
    110 {
    111     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    112     return parcel ? parcel->dataCapacity() : 0;
    113 }
    114 
    115 static void android_os_Parcel_setDataSize(JNIEnv* env, jclass clazz, jint nativePtr, jint size)
    116 {
    117     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    118     if (parcel != NULL) {
    119         const status_t err = parcel->setDataSize(size);
    120         if (err != NO_ERROR) {
    121             signalExceptionForError(env, clazz, err);
    122         }
    123     }
    124 }
    125 
    126 static void android_os_Parcel_setDataPosition(JNIEnv* env, jclass clazz, jint nativePtr, jint pos)
    127 {
    128     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    129     if (parcel != NULL) {
    130         parcel->setDataPosition(pos);
    131     }
    132 }
    133 
    134 static void android_os_Parcel_setDataCapacity(JNIEnv* env, jclass clazz, jint nativePtr, jint size)
    135 {
    136     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    137     if (parcel != NULL) {
    138         const status_t err = parcel->setDataCapacity(size);
    139         if (err != NO_ERROR) {
    140             signalExceptionForError(env, clazz, err);
    141         }
    142     }
    143 }
    144 
    145 static jboolean android_os_Parcel_pushAllowFds(JNIEnv* env, jclass clazz, jint nativePtr, jboolean allowFds)
    146 {
    147     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    148     jboolean ret = JNI_TRUE;
    149     if (parcel != NULL) {
    150         ret = (jboolean)parcel->pushAllowFds(allowFds);
    151     }
    152     return ret;
    153 }
    154 
    155 static void android_os_Parcel_restoreAllowFds(JNIEnv* env, jclass clazz, jint nativePtr, jboolean lastValue)
    156 {
    157     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    158     if (parcel != NULL) {
    159         parcel->restoreAllowFds((bool)lastValue);
    160     }
    161 }
    162 
    163 static void android_os_Parcel_writeNative(JNIEnv* env, jclass clazz, jint nativePtr, jobject data,
    164                                           jint offset, jint length)
    165 {
    166     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    167     if (parcel == NULL) {
    168         return;
    169     }
    170 
    171     const status_t err = parcel->writeInt32(length);
    172     if (err != NO_ERROR) {
    173         signalExceptionForError(env, clazz, err);
    174         return;
    175     }
    176 
    177     void* dest = parcel->writeInplace(length);
    178     if (dest == NULL) {
    179         signalExceptionForError(env, clazz, NO_MEMORY);
    180         return;
    181     }
    182 
    183     jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)data, 0);
    184     if (ar) {
    185         memcpy(dest, ar + offset, length);
    186         env->ReleasePrimitiveArrayCritical((jarray)data, ar, 0);
    187     }
    188 }
    189 
    190 static void android_os_Parcel_writeInt(JNIEnv* env, jclass clazz, jint nativePtr, jint val) {
    191     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    192     const status_t err = parcel->writeInt32(val);
    193     if (err != NO_ERROR) {
    194         signalExceptionForError(env, clazz, err);
    195     }
    196 }
    197 
    198 static void android_os_Parcel_writeLong(JNIEnv* env, jclass clazz, jint nativePtr, jlong val)
    199 {
    200     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    201     if (parcel != NULL) {
    202         const status_t err = parcel->writeInt64(val);
    203         if (err != NO_ERROR) {
    204             signalExceptionForError(env, clazz, err);
    205         }
    206     }
    207 }
    208 
    209 static void android_os_Parcel_writeFloat(JNIEnv* env, jclass clazz, jint nativePtr, jfloat val)
    210 {
    211     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    212     if (parcel != NULL) {
    213         const status_t err = parcel->writeFloat(val);
    214         if (err != NO_ERROR) {
    215             signalExceptionForError(env, clazz, err);
    216         }
    217     }
    218 }
    219 
    220 static void android_os_Parcel_writeDouble(JNIEnv* env, jclass clazz, jint nativePtr, jdouble val)
    221 {
    222     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    223     if (parcel != NULL) {
    224         const status_t err = parcel->writeDouble(val);
    225         if (err != NO_ERROR) {
    226             signalExceptionForError(env, clazz, err);
    227         }
    228     }
    229 }
    230 
    231 static void android_os_Parcel_writeString(JNIEnv* env, jclass clazz, jint nativePtr, jstring val)
    232 {
    233     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    234     if (parcel != NULL) {
    235         status_t err = NO_MEMORY;
    236         if (val) {
    237             const jchar* str = env->GetStringCritical(val, 0);
    238             if (str) {
    239                 err = parcel->writeString16(str, env->GetStringLength(val));
    240                 env->ReleaseStringCritical(val, str);
    241             }
    242         } else {
    243             err = parcel->writeString16(NULL, 0);
    244         }
    245         if (err != NO_ERROR) {
    246             signalExceptionForError(env, clazz, err);
    247         }
    248     }
    249 }
    250 
    251 static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jint nativePtr, jobject object)
    252 {
    253     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    254     if (parcel != NULL) {
    255         const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
    256         if (err != NO_ERROR) {
    257             signalExceptionForError(env, clazz, err);
    258         }
    259     }
    260 }
    261 
    262 static void android_os_Parcel_writeFileDescriptor(JNIEnv* env, jclass clazz, jint nativePtr, jobject object)
    263 {
    264     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    265     if (parcel != NULL) {
    266         const status_t err =
    267                 parcel->writeDupFileDescriptor(jniGetFDFromFileDescriptor(env, object));
    268         if (err != NO_ERROR) {
    269             signalExceptionForError(env, clazz, err);
    270         }
    271     }
    272 }
    273 
    274 static jbyteArray android_os_Parcel_createByteArray(JNIEnv* env, jclass clazz, jint nativePtr)
    275 {
    276     jbyteArray ret = NULL;
    277 
    278     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    279     if (parcel != NULL) {
    280         int32_t len = parcel->readInt32();
    281 
    282         // sanity check the stored length against the true data size
    283         if (len >= 0 && len <= (int32_t)parcel->dataAvail()) {
    284             ret = env->NewByteArray(len);
    285 
    286             if (ret != NULL) {
    287                 jbyte* a2 = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
    288                 if (a2) {
    289                     const void* data = parcel->readInplace(len);
    290                     memcpy(a2, data, len);
    291                     env->ReleasePrimitiveArrayCritical(ret, a2, 0);
    292                 }
    293             }
    294         }
    295     }
    296 
    297     return ret;
    298 }
    299 
    300 static jint android_os_Parcel_readInt(JNIEnv* env, jclass clazz, jint nativePtr)
    301 {
    302     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    303     if (parcel != NULL) {
    304         return parcel->readInt32();
    305     }
    306     return 0;
    307 }
    308 
    309 static jlong android_os_Parcel_readLong(JNIEnv* env, jclass clazz, jint nativePtr)
    310 {
    311     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    312     if (parcel != NULL) {
    313         return parcel->readInt64();
    314     }
    315     return 0;
    316 }
    317 
    318 static jfloat android_os_Parcel_readFloat(JNIEnv* env, jclass clazz, jint nativePtr)
    319 {
    320     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    321     if (parcel != NULL) {
    322         return parcel->readFloat();
    323     }
    324     return 0;
    325 }
    326 
    327 static jdouble android_os_Parcel_readDouble(JNIEnv* env, jclass clazz, jint nativePtr)
    328 {
    329     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    330     if (parcel != NULL) {
    331         return parcel->readDouble();
    332     }
    333     return 0;
    334 }
    335 
    336 static jstring android_os_Parcel_readString(JNIEnv* env, jclass clazz, jint nativePtr)
    337 {
    338     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    339     if (parcel != NULL) {
    340         size_t len;
    341         const char16_t* str = parcel->readString16Inplace(&len);
    342         if (str) {
    343             return env->NewString(str, len);
    344         }
    345         return NULL;
    346     }
    347     return NULL;
    348 }
    349 
    350 static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jint nativePtr)
    351 {
    352     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    353     if (parcel != NULL) {
    354         return javaObjectForIBinder(env, parcel->readStrongBinder());
    355     }
    356     return NULL;
    357 }
    358 
    359 static jobject android_os_Parcel_readFileDescriptor(JNIEnv* env, jclass clazz, jint nativePtr)
    360 {
    361     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    362     if (parcel != NULL) {
    363         int fd = parcel->readFileDescriptor();
    364         if (fd < 0) return NULL;
    365         fd = dup(fd);
    366         if (fd < 0) return NULL;
    367         return jniCreateFileDescriptor(env, fd);
    368     }
    369     return NULL;
    370 }
    371 
    372 static jobject android_os_Parcel_openFileDescriptor(JNIEnv* env, jclass clazz,
    373                                                     jstring name, jint mode)
    374 {
    375     if (name == NULL) {
    376         jniThrowNullPointerException(env, NULL);
    377         return NULL;
    378     }
    379     const jchar* str = env->GetStringCritical(name, 0);
    380     if (str == NULL) {
    381         // Whatever, whatever.
    382         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    383         return NULL;
    384     }
    385     String8 name8(str, env->GetStringLength(name));
    386     env->ReleaseStringCritical(name, str);
    387     int flags=0;
    388     switch (mode&0x30000000) {
    389         case 0:
    390         case 0x10000000:
    391             flags = O_RDONLY;
    392             break;
    393         case 0x20000000:
    394             flags = O_WRONLY;
    395             break;
    396         case 0x30000000:
    397             flags = O_RDWR;
    398             break;
    399     }
    400 
    401     if (mode&0x08000000) flags |= O_CREAT;
    402     if (mode&0x04000000) flags |= O_TRUNC;
    403     if (mode&0x02000000) flags |= O_APPEND;
    404 
    405     int realMode = S_IRWXU|S_IRWXG;
    406     if (mode&0x00000001) realMode |= S_IROTH;
    407     if (mode&0x00000002) realMode |= S_IWOTH;
    408 
    409     int fd = open(name8.string(), flags, realMode);
    410     if (fd < 0) {
    411         jniThrowException(env, "java/io/FileNotFoundException", strerror(errno));
    412         return NULL;
    413     }
    414     jobject object = jniCreateFileDescriptor(env, fd);
    415     if (object == NULL) {
    416         close(fd);
    417     }
    418     return object;
    419 }
    420 
    421 static jobject android_os_Parcel_dupFileDescriptor(JNIEnv* env, jclass clazz, jobject orig)
    422 {
    423     if (orig == NULL) {
    424         jniThrowNullPointerException(env, NULL);
    425         return NULL;
    426     }
    427     int origfd = jniGetFDFromFileDescriptor(env, orig);
    428     if (origfd < 0) {
    429         jniThrowException(env, "java/lang/IllegalArgumentException", "bad FileDescriptor");
    430         return NULL;
    431     }
    432 
    433     int fd = dup(origfd);
    434     if (fd < 0) {
    435         jniThrowIOException(env, errno);
    436         return NULL;
    437     }
    438     jobject object = jniCreateFileDescriptor(env, fd);
    439     if (object == NULL) {
    440         close(fd);
    441     }
    442     return object;
    443 }
    444 
    445 static void android_os_Parcel_closeFileDescriptor(JNIEnv* env, jclass clazz, jobject object)
    446 {
    447     if (object == NULL) {
    448         jniThrowNullPointerException(env, NULL);
    449         return;
    450     }
    451     int fd = jniGetFDFromFileDescriptor(env, object);
    452     if (fd >= 0) {
    453         jniSetFileDescriptorOfFD(env, object, -1);
    454         //ALOGI("Closing ParcelFileDescriptor %d\n", fd);
    455         close(fd);
    456     }
    457 }
    458 
    459 static void android_os_Parcel_clearFileDescriptor(JNIEnv* env, jclass clazz, jobject object)
    460 {
    461     if (object == NULL) {
    462         jniThrowNullPointerException(env, NULL);
    463         return;
    464     }
    465     int fd = jniGetFDFromFileDescriptor(env, object);
    466     if (fd >= 0) {
    467         jniSetFileDescriptorOfFD(env, object, -1);
    468     }
    469 }
    470 
    471 static jint android_os_Parcel_create(JNIEnv* env, jclass clazz)
    472 {
    473     Parcel* parcel = new Parcel();
    474     return reinterpret_cast<jint>(parcel);
    475 }
    476 
    477 static void android_os_Parcel_freeBuffer(JNIEnv* env, jclass clazz, jint nativePtr)
    478 {
    479     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    480     if (parcel != NULL) {
    481         parcel->freeData();
    482     }
    483 }
    484 
    485 static void android_os_Parcel_destroy(JNIEnv* env, jclass clazz, jint nativePtr)
    486 {
    487     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    488     delete parcel;
    489 }
    490 
    491 static jbyteArray android_os_Parcel_marshall(JNIEnv* env, jclass clazz, jint nativePtr)
    492 {
    493     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    494     if (parcel == NULL) {
    495        return NULL;
    496     }
    497 
    498     // do not marshall if there are binder objects in the parcel
    499     if (parcel->objectsCount())
    500     {
    501         jniThrowException(env, "java/lang/RuntimeException", "Tried to marshall a Parcel that contained Binder objects.");
    502         return NULL;
    503     }
    504 
    505     jbyteArray ret = env->NewByteArray(parcel->dataSize());
    506 
    507     if (ret != NULL)
    508     {
    509         jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
    510         if (array != NULL)
    511         {
    512             memcpy(array, parcel->data(), parcel->dataSize());
    513             env->ReleasePrimitiveArrayCritical(ret, array, 0);
    514         }
    515     }
    516 
    517     return ret;
    518 }
    519 
    520 static void android_os_Parcel_unmarshall(JNIEnv* env, jclass clazz, jint nativePtr,
    521                                          jbyteArray data, jint offset, jint length)
    522 {
    523     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    524     if (parcel == NULL || length < 0) {
    525        return;
    526     }
    527 
    528     jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(data, 0);
    529     if (array)
    530     {
    531         parcel->setDataSize(length);
    532         parcel->setDataPosition(0);
    533 
    534         void* raw = parcel->writeInplace(length);
    535         memcpy(raw, (array + offset), length);
    536 
    537         env->ReleasePrimitiveArrayCritical(data, array, 0);
    538     }
    539 }
    540 
    541 static void android_os_Parcel_appendFrom(JNIEnv* env, jclass clazz, jint thisNativePtr,
    542                                          jint otherNativePtr, jint offset, jint length)
    543 {
    544     Parcel* thisParcel = reinterpret_cast<Parcel*>(thisNativePtr);
    545     if (thisParcel == NULL) {
    546        return;
    547     }
    548     Parcel* otherParcel = reinterpret_cast<Parcel*>(otherNativePtr);
    549     if (otherParcel == NULL) {
    550        return;
    551     }
    552 
    553     status_t err = thisParcel->appendFrom(otherParcel, offset, length);
    554     if (err != NO_ERROR) {
    555         signalExceptionForError(env, clazz, err);
    556     }
    557 }
    558 
    559 static jboolean android_os_Parcel_hasFileDescriptors(JNIEnv* env, jclass clazz, jint nativePtr)
    560 {
    561     jboolean ret = JNI_FALSE;
    562     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    563     if (parcel != NULL) {
    564         if (parcel->hasFileDescriptors()) {
    565             ret = JNI_TRUE;
    566         }
    567     }
    568     return ret;
    569 }
    570 
    571 static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jclass clazz, jint nativePtr,
    572                                                   jstring name)
    573 {
    574     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    575     if (parcel != NULL) {
    576         // In the current implementation, the token is just the serialized interface name that
    577         // the caller expects to be invoking
    578         const jchar* str = env->GetStringCritical(name, 0);
    579         if (str != NULL) {
    580             parcel->writeInterfaceToken(String16(str, env->GetStringLength(name)));
    581             env->ReleaseStringCritical(name, str);
    582         }
    583     }
    584 }
    585 
    586 static void android_os_Parcel_enforceInterface(JNIEnv* env, jclass clazz, jint nativePtr, jstring name)
    587 {
    588     jboolean ret = JNI_FALSE;
    589 
    590     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    591     if (parcel != NULL) {
    592         const jchar* str = env->GetStringCritical(name, 0);
    593         if (str) {
    594             IPCThreadState* threadState = IPCThreadState::self();
    595             const int32_t oldPolicy = threadState->getStrictModePolicy();
    596             const bool isValid = parcel->enforceInterface(
    597                 String16(str, env->GetStringLength(name)),
    598                 threadState);
    599             env->ReleaseStringCritical(name, str);
    600             if (isValid) {
    601                 const int32_t newPolicy = threadState->getStrictModePolicy();
    602                 if (oldPolicy != newPolicy) {
    603                     // Need to keep the Java-level thread-local strict
    604                     // mode policy in sync for the libcore
    605                     // enforcements, which involves an upcall back
    606                     // into Java.  (We can't modify the
    607                     // Parcel.enforceInterface signature, as it's
    608                     // pseudo-public, and used via AIDL
    609                     // auto-generation...)
    610                     set_dalvik_blockguard_policy(env, newPolicy);
    611                 }
    612                 return;     // everything was correct -> return silently
    613             }
    614         }
    615     }
    616 
    617     // all error conditions wind up here
    618     jniThrowException(env, "java/lang/SecurityException",
    619             "Binder invocation to an incorrect interface");
    620 }
    621 
    622 // ----------------------------------------------------------------------------
    623 
    624 static const JNINativeMethod gParcelMethods[] = {
    625     {"nativeDataSize",            "(I)I", (void*)android_os_Parcel_dataSize},
    626     {"nativeDataAvail",           "(I)I", (void*)android_os_Parcel_dataAvail},
    627     {"nativeDataPosition",        "(I)I", (void*)android_os_Parcel_dataPosition},
    628     {"nativeDataCapacity",        "(I)I", (void*)android_os_Parcel_dataCapacity},
    629     {"nativeSetDataSize",         "(II)V", (void*)android_os_Parcel_setDataSize},
    630     {"nativeSetDataPosition",     "(II)V", (void*)android_os_Parcel_setDataPosition},
    631     {"nativeSetDataCapacity",     "(II)V", (void*)android_os_Parcel_setDataCapacity},
    632 
    633     {"nativePushAllowFds",        "(IZ)Z", (void*)android_os_Parcel_pushAllowFds},
    634     {"nativeRestoreAllowFds",     "(IZ)V", (void*)android_os_Parcel_restoreAllowFds},
    635 
    636     {"nativeWriteByteArray",      "(I[BII)V", (void*)android_os_Parcel_writeNative},
    637     {"nativeWriteInt",            "(II)V", (void*)android_os_Parcel_writeInt},
    638     {"nativeWriteLong",           "(IJ)V", (void*)android_os_Parcel_writeLong},
    639     {"nativeWriteFloat",          "(IF)V", (void*)android_os_Parcel_writeFloat},
    640     {"nativeWriteDouble",         "(ID)V", (void*)android_os_Parcel_writeDouble},
    641     {"nativeWriteString",         "(ILjava/lang/String;)V", (void*)android_os_Parcel_writeString},
    642     {"nativeWriteStrongBinder",   "(ILandroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder},
    643     {"nativeWriteFileDescriptor", "(ILjava/io/FileDescriptor;)V", (void*)android_os_Parcel_writeFileDescriptor},
    644 
    645     {"nativeCreateByteArray",     "(I)[B", (void*)android_os_Parcel_createByteArray},
    646     {"nativeReadInt",             "(I)I", (void*)android_os_Parcel_readInt},
    647     {"nativeReadLong",            "(I)J", (void*)android_os_Parcel_readLong},
    648     {"nativeReadFloat",           "(I)F", (void*)android_os_Parcel_readFloat},
    649     {"nativeReadDouble",          "(I)D", (void*)android_os_Parcel_readDouble},
    650     {"nativeReadString",          "(I)Ljava/lang/String;", (void*)android_os_Parcel_readString},
    651     {"nativeReadStrongBinder",    "(I)Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder},
    652     {"nativeReadFileDescriptor",  "(I)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_readFileDescriptor},
    653 
    654     {"openFileDescriptor",        "(Ljava/lang/String;I)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_openFileDescriptor},
    655     {"dupFileDescriptor",         "(Ljava/io/FileDescriptor;)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_dupFileDescriptor},
    656     {"closeFileDescriptor",       "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_closeFileDescriptor},
    657     {"clearFileDescriptor",       "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_clearFileDescriptor},
    658 
    659     {"nativeCreate",              "()I", (void*)android_os_Parcel_create},
    660     {"nativeFreeBuffer",          "(I)V", (void*)android_os_Parcel_freeBuffer},
    661     {"nativeDestroy",             "(I)V", (void*)android_os_Parcel_destroy},
    662 
    663     {"nativeMarshall",            "(I)[B", (void*)android_os_Parcel_marshall},
    664     {"nativeUnmarshall",          "(I[BII)V", (void*)android_os_Parcel_unmarshall},
    665     {"nativeAppendFrom",          "(IIII)V", (void*)android_os_Parcel_appendFrom},
    666     {"nativeHasFileDescriptors",  "(I)Z", (void*)android_os_Parcel_hasFileDescriptors},
    667     {"nativeWriteInterfaceToken", "(ILjava/lang/String;)V", (void*)android_os_Parcel_writeInterfaceToken},
    668     {"nativeEnforceInterface",    "(ILjava/lang/String;)V", (void*)android_os_Parcel_enforceInterface},
    669 };
    670 
    671 const char* const kParcelPathName = "android/os/Parcel";
    672 
    673 int register_android_os_Parcel(JNIEnv* env)
    674 {
    675     jclass clazz;
    676 
    677     clazz = env->FindClass(kParcelPathName);
    678     LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Parcel");
    679 
    680     gParcelOffsets.clazz = (jclass) env->NewGlobalRef(clazz);
    681     gParcelOffsets.mNativePtr = env->GetFieldID(clazz, "mNativePtr", "I");
    682     gParcelOffsets.obtain = env->GetStaticMethodID(clazz, "obtain",
    683                                                    "()Landroid/os/Parcel;");
    684     gParcelOffsets.recycle = env->GetMethodID(clazz, "recycle", "()V");
    685 
    686     return AndroidRuntime::registerNativeMethods(
    687         env, kParcelPathName,
    688         gParcelMethods, NELEM(gParcelMethods));
    689 }
    690 
    691 };
    692