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