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