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