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