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
61namespace android {
62
63static struct parcel_offsets_t
64{
65    jclass clazz;
66    jfieldID mNativePtr;
67    jmethodID obtain;
68    jmethodID recycle;
69} gParcelOffsets;
70
71Parcel* 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
83jobject createJavaParcelObject(JNIEnv* env)
84{
85    return env->CallStaticObjectMethod(gParcelOffsets.clazz, gParcelOffsets.obtain);
86}
87
88void recycleJavaParcelObject(JNIEnv* env, jobject parcelObj)
89{
90    env->CallVoidMethod(parcelObj, gParcelOffsets.recycle);
91}
92
93static jint android_os_Parcel_dataSize(jlong nativePtr)
94{
95    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
96    return parcel ? parcel->dataSize() : 0;
97}
98
99static jint android_os_Parcel_dataAvail(jlong nativePtr)
100{
101    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
102    return parcel ? parcel->dataAvail() : 0;
103}
104
105static jint android_os_Parcel_dataPosition(jlong nativePtr)
106{
107    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
108    return parcel ? parcel->dataPosition() : 0;
109}
110
111static jint android_os_Parcel_dataCapacity(jlong nativePtr)
112{
113    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
114    return parcel ? parcel->dataCapacity() : 0;
115}
116
117static 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
130static 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
138static 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
149static 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
159static 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
167static 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
194static 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
233static 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
243static 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
254static 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
265static 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
276static 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
298static 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
309static 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
323static 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
349static 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
371static 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
401static 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
410static 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
419static 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
428static 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
437static 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
451static 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
460static 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
473static 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
519static 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
543static 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
557static jlong android_os_Parcel_create(JNIEnv* env, jclass clazz)
558{
559    Parcel* parcel = new Parcel();
560    return reinterpret_cast<jlong>(parcel);
561}
562
563static 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
573static void android_os_Parcel_destroy(JNIEnv* env, jclass clazz, jlong nativePtr)
574{
575    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
576    delete parcel;
577}
578
579static 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
608static 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
630static 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
645static 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
664static 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
676static 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
693static 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
728static jlong android_os_Parcel_getGlobalAllocSize(JNIEnv* env, jclass clazz)
729{
730    return Parcel::getGlobalAllocSize();
731}
732
733static jlong android_os_Parcel_getGlobalAllocCount(JNIEnv* env, jclass clazz)
734{
735    return Parcel::getGlobalAllocCount();
736}
737
738static 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
749static 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
823const char* const kParcelPathName = "android/os/Parcel";
824
825int 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