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 <nativehelper/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 <binder/IInterface.h>
     32 #include <binder/IPCThreadState.h>
     33 #include <cutils/atomic.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 <nativehelper/ScopedUtfChars.h>
     45 #include <nativehelper/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(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(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(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(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(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(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(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_writeByteArray(JNIEnv* env, jclass clazz, jlong nativePtr,
    168                                              jobject data, 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 jboolean android_os_Parcel_readByteArray(JNIEnv* env, jclass clazz, jlong nativePtr,
    350                                                 jobject dest, jint destLen)
    351 {
    352     jboolean ret = JNI_FALSE;
    353     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    354     if (parcel == NULL) {
    355         return ret;
    356     }
    357 
    358     int32_t len = parcel->readInt32();
    359     if (len >= 0 && len <= (int32_t)parcel->dataAvail() && len == destLen) {
    360         jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)dest, 0);
    361         if (ar) {
    362             const void* data = parcel->readInplace(len);
    363             memcpy(ar, data, len);
    364             env->ReleasePrimitiveArrayCritical((jarray)dest, ar, 0);
    365             ret = JNI_TRUE;
    366         }
    367     }
    368     return ret;
    369 }
    370 
    371 static jbyteArray android_os_Parcel_readBlob(JNIEnv* env, jclass clazz, jlong nativePtr)
    372 {
    373     jbyteArray ret = NULL;
    374 
    375     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    376     if (parcel != NULL) {
    377         int32_t len = parcel->readInt32();
    378         if (len >= 0) {
    379             android::Parcel::ReadableBlob blob;
    380             android::status_t err = parcel->readBlob(len, &blob);
    381             if (err != NO_ERROR) {
    382                 signalExceptionForError(env, clazz, err);
    383                 return NULL;
    384             }
    385 
    386             ret = env->NewByteArray(len);
    387             if (ret != NULL) {
    388                 jbyte* a2 = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
    389                 if (a2) {
    390                     memcpy(a2, blob.data(), len);
    391                     env->ReleasePrimitiveArrayCritical(ret, a2, 0);
    392                 }
    393             }
    394             blob.release();
    395         }
    396     }
    397 
    398     return ret;
    399 }
    400 
    401 static jint android_os_Parcel_readInt(jlong nativePtr)
    402 {
    403     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    404     if (parcel != NULL) {
    405         return parcel->readInt32();
    406     }
    407     return 0;
    408 }
    409 
    410 static jlong android_os_Parcel_readLong(jlong nativePtr)
    411 {
    412     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    413     if (parcel != NULL) {
    414         return parcel->readInt64();
    415     }
    416     return 0;
    417 }
    418 
    419 static jfloat android_os_Parcel_readFloat(jlong nativePtr)
    420 {
    421     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    422     if (parcel != NULL) {
    423         return parcel->readFloat();
    424     }
    425     return 0;
    426 }
    427 
    428 static jdouble android_os_Parcel_readDouble(jlong nativePtr)
    429 {
    430     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    431     if (parcel != NULL) {
    432         return parcel->readDouble();
    433     }
    434     return 0;
    435 }
    436 
    437 static jstring android_os_Parcel_readString(JNIEnv* env, jclass clazz, jlong nativePtr)
    438 {
    439     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    440     if (parcel != NULL) {
    441         size_t len;
    442         const char16_t* str = parcel->readString16Inplace(&len);
    443         if (str) {
    444             return env->NewString(reinterpret_cast<const jchar*>(str), len);
    445         }
    446         return NULL;
    447     }
    448     return NULL;
    449 }
    450 
    451 static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)
    452 {
    453     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    454     if (parcel != NULL) {
    455         return javaObjectForIBinder(env, parcel->readStrongBinder());
    456     }
    457     return NULL;
    458 }
    459 
    460 static jobject android_os_Parcel_readFileDescriptor(JNIEnv* env, jclass clazz, jlong nativePtr)
    461 {
    462     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    463     if (parcel != NULL) {
    464         int fd = parcel->readFileDescriptor();
    465         if (fd < 0) return NULL;
    466         fd = dup(fd);
    467         if (fd < 0) return NULL;
    468         return jniCreateFileDescriptor(env, fd);
    469     }
    470     return NULL;
    471 }
    472 
    473 static jobject android_os_Parcel_openFileDescriptor(JNIEnv* env, jclass clazz,
    474                                                     jstring name, jint mode)
    475 {
    476     if (name == NULL) {
    477         jniThrowNullPointerException(env, NULL);
    478         return NULL;
    479     }
    480     ScopedUtfChars name8(env, name);
    481     if (name8.c_str() == NULL) {
    482         return NULL;
    483     }
    484 
    485     int flags=0;
    486     switch (mode&0x30000000) {
    487         case 0:
    488         case 0x10000000:
    489             flags = O_RDONLY;
    490             break;
    491         case 0x20000000:
    492             flags = O_WRONLY;
    493             break;
    494         case 0x30000000:
    495             flags = O_RDWR;
    496             break;
    497     }
    498 
    499     if (mode&0x08000000) flags |= O_CREAT;
    500     if (mode&0x04000000) flags |= O_TRUNC;
    501     if (mode&0x02000000) flags |= O_APPEND;
    502 
    503     int realMode = S_IRWXU|S_IRWXG;
    504     if (mode&0x00000001) realMode |= S_IROTH;
    505     if (mode&0x00000002) realMode |= S_IWOTH;
    506 
    507     int fd = open(name8.c_str(), flags, realMode);
    508     if (fd < 0) {
    509         jniThrowException(env, "java/io/FileNotFoundException", strerror(errno));
    510         return NULL;
    511     }
    512     jobject object = jniCreateFileDescriptor(env, fd);
    513     if (object == NULL) {
    514         close(fd);
    515     }
    516     return object;
    517 }
    518 
    519 static jobject android_os_Parcel_dupFileDescriptor(JNIEnv* env, jclass clazz, jobject orig)
    520 {
    521     if (orig == NULL) {
    522         jniThrowNullPointerException(env, NULL);
    523         return NULL;
    524     }
    525     int origfd = jniGetFDFromFileDescriptor(env, orig);
    526     if (origfd < 0) {
    527         jniThrowException(env, "java/lang/IllegalArgumentException", "bad FileDescriptor");
    528         return NULL;
    529     }
    530 
    531     int fd = dup(origfd);
    532     if (fd < 0) {
    533         jniThrowIOException(env, errno);
    534         return NULL;
    535     }
    536     jobject object = jniCreateFileDescriptor(env, fd);
    537     if (object == NULL) {
    538         close(fd);
    539     }
    540     return object;
    541 }
    542 
    543 static void android_os_Parcel_closeFileDescriptor(JNIEnv* env, jclass clazz, jobject object)
    544 {
    545     if (object == NULL) {
    546         jniThrowNullPointerException(env, NULL);
    547         return;
    548     }
    549     int fd = jniGetFDFromFileDescriptor(env, object);
    550     if (fd >= 0) {
    551         jniSetFileDescriptorOfFD(env, object, -1);
    552         //ALOGI("Closing ParcelFileDescriptor %d\n", fd);
    553         close(fd);
    554     }
    555 }
    556 
    557 static jlong android_os_Parcel_create(JNIEnv* env, jclass clazz)
    558 {
    559     Parcel* parcel = new Parcel();
    560     return reinterpret_cast<jlong>(parcel);
    561 }
    562 
    563 static jlong android_os_Parcel_freeBuffer(JNIEnv* env, jclass clazz, jlong nativePtr)
    564 {
    565     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    566     if (parcel != NULL) {
    567         parcel->freeData();
    568         return parcel->getOpenAshmemSize();
    569     }
    570     return 0;
    571 }
    572 
    573 static void android_os_Parcel_destroy(JNIEnv* env, jclass clazz, jlong nativePtr)
    574 {
    575     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    576     delete parcel;
    577 }
    578 
    579 static jbyteArray android_os_Parcel_marshall(JNIEnv* env, jclass clazz, jlong nativePtr)
    580 {
    581     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    582     if (parcel == NULL) {
    583        return NULL;
    584     }
    585 
    586     // do not marshall if there are binder objects in the parcel
    587     if (parcel->objectsCount())
    588     {
    589         jniThrowException(env, "java/lang/RuntimeException", "Tried to marshall a Parcel that contained Binder objects.");
    590         return NULL;
    591     }
    592 
    593     jbyteArray ret = env->NewByteArray(parcel->dataSize());
    594 
    595     if (ret != NULL)
    596     {
    597         jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
    598         if (array != NULL)
    599         {
    600             memcpy(array, parcel->data(), parcel->dataSize());
    601             env->ReleasePrimitiveArrayCritical(ret, array, 0);
    602         }
    603     }
    604 
    605     return ret;
    606 }
    607 
    608 static jlong android_os_Parcel_unmarshall(JNIEnv* env, jclass clazz, jlong nativePtr,
    609                                           jbyteArray data, jint offset, jint length)
    610 {
    611     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    612     if (parcel == NULL || length < 0) {
    613        return 0;
    614     }
    615 
    616     jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(data, 0);
    617     if (array)
    618     {
    619         parcel->setDataSize(length);
    620         parcel->setDataPosition(0);
    621 
    622         void* raw = parcel->writeInplace(length);
    623         memcpy(raw, (array + offset), length);
    624 
    625         env->ReleasePrimitiveArrayCritical(data, array, 0);
    626     }
    627     return parcel->getOpenAshmemSize();
    628 }
    629 
    630 static jint android_os_Parcel_compareData(JNIEnv* env, jclass clazz, jlong thisNativePtr,
    631                                           jlong otherNativePtr)
    632 {
    633     Parcel* thisParcel = reinterpret_cast<Parcel*>(thisNativePtr);
    634     if (thisParcel == NULL) {
    635        return 0;
    636     }
    637     Parcel* otherParcel = reinterpret_cast<Parcel*>(otherNativePtr);
    638     if (otherParcel == NULL) {
    639        return thisParcel->getOpenAshmemSize();
    640     }
    641 
    642     return thisParcel->compareData(*otherParcel);
    643 }
    644 
    645 static jlong android_os_Parcel_appendFrom(JNIEnv* env, jclass clazz, jlong thisNativePtr,
    646                                           jlong otherNativePtr, jint offset, jint length)
    647 {
    648     Parcel* thisParcel = reinterpret_cast<Parcel*>(thisNativePtr);
    649     if (thisParcel == NULL) {
    650        return 0;
    651     }
    652     Parcel* otherParcel = reinterpret_cast<Parcel*>(otherNativePtr);
    653     if (otherParcel == NULL) {
    654        return thisParcel->getOpenAshmemSize();
    655     }
    656 
    657     status_t err = thisParcel->appendFrom(otherParcel, offset, length);
    658     if (err != NO_ERROR) {
    659         signalExceptionForError(env, clazz, err);
    660     }
    661     return thisParcel->getOpenAshmemSize();
    662 }
    663 
    664 static jboolean android_os_Parcel_hasFileDescriptors(jlong nativePtr)
    665 {
    666     jboolean ret = JNI_FALSE;
    667     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    668     if (parcel != NULL) {
    669         if (parcel->hasFileDescriptors()) {
    670             ret = JNI_TRUE;
    671         }
    672     }
    673     return ret;
    674 }
    675 
    676 static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jclass clazz, jlong nativePtr,
    677                                                   jstring name)
    678 {
    679     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    680     if (parcel != NULL) {
    681         // In the current implementation, the token is just the serialized interface name that
    682         // the caller expects to be invoking
    683         const jchar* str = env->GetStringCritical(name, 0);
    684         if (str != NULL) {
    685             parcel->writeInterfaceToken(String16(
    686                   reinterpret_cast<const char16_t*>(str),
    687                   env->GetStringLength(name)));
    688             env->ReleaseStringCritical(name, str);
    689         }
    690     }
    691 }
    692 
    693 static void android_os_Parcel_enforceInterface(JNIEnv* env, jclass clazz, jlong nativePtr, jstring name)
    694 {
    695     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    696     if (parcel != NULL) {
    697         const jchar* str = env->GetStringCritical(name, 0);
    698         if (str) {
    699             IPCThreadState* threadState = IPCThreadState::self();
    700             const int32_t oldPolicy = threadState->getStrictModePolicy();
    701             const bool isValid = parcel->enforceInterface(
    702                 String16(reinterpret_cast<const char16_t*>(str),
    703                          env->GetStringLength(name)),
    704                 threadState);
    705             env->ReleaseStringCritical(name, str);
    706             if (isValid) {
    707                 const int32_t newPolicy = threadState->getStrictModePolicy();
    708                 if (oldPolicy != newPolicy) {
    709                     // Need to keep the Java-level thread-local strict
    710                     // mode policy in sync for the libcore
    711                     // enforcements, which involves an upcall back
    712                     // into Java.  (We can't modify the
    713                     // Parcel.enforceInterface signature, as it's
    714                     // pseudo-public, and used via AIDL
    715                     // auto-generation...)
    716                     set_dalvik_blockguard_policy(env, newPolicy);
    717                 }
    718                 return;     // everything was correct -> return silently
    719             }
    720         }
    721     }
    722 
    723     // all error conditions wind up here
    724     jniThrowException(env, "java/lang/SecurityException",
    725             "Binder invocation to an incorrect interface");
    726 }
    727 
    728 static jlong android_os_Parcel_getGlobalAllocSize(JNIEnv* env, jclass clazz)
    729 {
    730     return Parcel::getGlobalAllocSize();
    731 }
    732 
    733 static jlong android_os_Parcel_getGlobalAllocCount(JNIEnv* env, jclass clazz)
    734 {
    735     return Parcel::getGlobalAllocCount();
    736 }
    737 
    738 static jlong android_os_Parcel_getBlobAshmemSize(jlong nativePtr)
    739 {
    740     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    741     if (parcel != NULL) {
    742         return parcel->getBlobAshmemSize();
    743     }
    744     return 0;
    745 }
    746 
    747 // ----------------------------------------------------------------------------
    748 
    749 static const JNINativeMethod gParcelMethods[] = {
    750     // @CriticalNative
    751     {"nativeDataSize",            "(J)I", (void*)android_os_Parcel_dataSize},
    752     // @CriticalNative
    753     {"nativeDataAvail",           "(J)I", (void*)android_os_Parcel_dataAvail},
    754     // @CriticalNative
    755     {"nativeDataPosition",        "(J)I", (void*)android_os_Parcel_dataPosition},
    756     // @CriticalNative
    757     {"nativeDataCapacity",        "(J)I", (void*)android_os_Parcel_dataCapacity},
    758     // @FastNative
    759     {"nativeSetDataSize",         "(JI)J", (void*)android_os_Parcel_setDataSize},
    760     // @CriticalNative
    761     {"nativeSetDataPosition",     "(JI)V", (void*)android_os_Parcel_setDataPosition},
    762     // @FastNative
    763     {"nativeSetDataCapacity",     "(JI)V", (void*)android_os_Parcel_setDataCapacity},
    764 
    765     // @CriticalNative
    766     {"nativePushAllowFds",        "(JZ)Z", (void*)android_os_Parcel_pushAllowFds},
    767     // @CriticalNative
    768     {"nativeRestoreAllowFds",     "(JZ)V", (void*)android_os_Parcel_restoreAllowFds},
    769 
    770     {"nativeWriteByteArray",      "(J[BII)V", (void*)android_os_Parcel_writeByteArray},
    771     {"nativeWriteBlob",           "(J[BII)V", (void*)android_os_Parcel_writeBlob},
    772     // @FastNative
    773     {"nativeWriteInt",            "(JI)V", (void*)android_os_Parcel_writeInt},
    774     // @FastNative
    775     {"nativeWriteLong",           "(JJ)V", (void*)android_os_Parcel_writeLong},
    776     // @FastNative
    777     {"nativeWriteFloat",          "(JF)V", (void*)android_os_Parcel_writeFloat},
    778     // @FastNative
    779     {"nativeWriteDouble",         "(JD)V", (void*)android_os_Parcel_writeDouble},
    780     {"nativeWriteString",         "(JLjava/lang/String;)V", (void*)android_os_Parcel_writeString},
    781     {"nativeWriteStrongBinder",   "(JLandroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder},
    782     {"nativeWriteFileDescriptor", "(JLjava/io/FileDescriptor;)J", (void*)android_os_Parcel_writeFileDescriptor},
    783 
    784     {"nativeCreateByteArray",     "(J)[B", (void*)android_os_Parcel_createByteArray},
    785     {"nativeReadByteArray",       "(J[BI)Z", (void*)android_os_Parcel_readByteArray},
    786     {"nativeReadBlob",            "(J)[B", (void*)android_os_Parcel_readBlob},
    787     // @CriticalNative
    788     {"nativeReadInt",             "(J)I", (void*)android_os_Parcel_readInt},
    789     // @CriticalNative
    790     {"nativeReadLong",            "(J)J", (void*)android_os_Parcel_readLong},
    791     // @CriticalNative
    792     {"nativeReadFloat",           "(J)F", (void*)android_os_Parcel_readFloat},
    793     // @CriticalNative
    794     {"nativeReadDouble",          "(J)D", (void*)android_os_Parcel_readDouble},
    795     {"nativeReadString",          "(J)Ljava/lang/String;", (void*)android_os_Parcel_readString},
    796     {"nativeReadStrongBinder",    "(J)Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder},
    797     {"nativeReadFileDescriptor",  "(J)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_readFileDescriptor},
    798 
    799     {"openFileDescriptor",        "(Ljava/lang/String;I)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_openFileDescriptor},
    800     {"dupFileDescriptor",         "(Ljava/io/FileDescriptor;)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_dupFileDescriptor},
    801     {"closeFileDescriptor",       "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_closeFileDescriptor},
    802 
    803     {"nativeCreate",              "()J", (void*)android_os_Parcel_create},
    804     {"nativeFreeBuffer",          "(J)J", (void*)android_os_Parcel_freeBuffer},
    805     {"nativeDestroy",             "(J)V", (void*)android_os_Parcel_destroy},
    806 
    807     {"nativeMarshall",            "(J)[B", (void*)android_os_Parcel_marshall},
    808     {"nativeUnmarshall",          "(J[BII)J", (void*)android_os_Parcel_unmarshall},
    809     {"nativeCompareData",         "(JJ)I", (void*)android_os_Parcel_compareData},
    810     {"nativeAppendFrom",          "(JJII)J", (void*)android_os_Parcel_appendFrom},
    811     // @CriticalNative
    812     {"nativeHasFileDescriptors",  "(J)Z", (void*)android_os_Parcel_hasFileDescriptors},
    813     {"nativeWriteInterfaceToken", "(JLjava/lang/String;)V", (void*)android_os_Parcel_writeInterfaceToken},
    814     {"nativeEnforceInterface",    "(JLjava/lang/String;)V", (void*)android_os_Parcel_enforceInterface},
    815 
    816     {"getGlobalAllocSize",        "()J", (void*)android_os_Parcel_getGlobalAllocSize},
    817     {"getGlobalAllocCount",       "()J", (void*)android_os_Parcel_getGlobalAllocCount},
    818 
    819     // @CriticalNative
    820     {"nativeGetBlobAshmemSize",       "(J)J", (void*)android_os_Parcel_getBlobAshmemSize},
    821 };
    822 
    823 const char* const kParcelPathName = "android/os/Parcel";
    824 
    825 int register_android_os_Parcel(JNIEnv* env)
    826 {
    827     jclass clazz = FindClassOrDie(env, kParcelPathName);
    828 
    829     gParcelOffsets.clazz = MakeGlobalRefOrDie(env, clazz);
    830     gParcelOffsets.mNativePtr = GetFieldIDOrDie(env, clazz, "mNativePtr", "J");
    831     gParcelOffsets.obtain = GetStaticMethodIDOrDie(env, clazz, "obtain", "()Landroid/os/Parcel;");
    832     gParcelOffsets.recycle = GetMethodIDOrDie(env, clazz, "recycle", "()V");
    833 
    834     return RegisterMethodsOrDie(env, kParcelPathName, gParcelMethods, NELEM(gParcelMethods));
    835 }
    836 
    837 };
    838