OSDN Git Service

am bb5a1848: am 8730092a: Merge "docs: Added API highlights for Google Play services...
[android-x86/frameworks-base.git] / core / jni / android_os_Parcel.cpp
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
59 namespace android {
60
61 static struct parcel_offsets_t
62 {
63     jclass clazz;
64     jfieldID mNativePtr;
65     jmethodID obtain;
66     jmethodID recycle;
67 } gParcelOffsets;
68
69 Parcel* 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
81 jobject createJavaParcelObject(JNIEnv* env)
82 {
83     return env->CallStaticObjectMethod(gParcelOffsets.clazz, gParcelOffsets.obtain);
84 }
85
86 void recycleJavaParcelObject(JNIEnv* env, jobject parcelObj)
87 {
88     env->CallVoidMethod(parcelObj, gParcelOffsets.recycle);
89 }
90
91 static 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
97 static 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
103 static 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
109 static 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
115 static 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
126 static 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
134 static 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
145 static 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
155 static 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
163 static 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
190 static 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
229 static 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
237 static 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
248 static 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
259 static 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
270 static 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
290 static 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
301 static 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
313 static 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
339 static 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
369 static 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
378 static 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
387 static 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
396 static 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
405 static 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
419 static 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
428 static 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
441 static 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
490 static 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
514 static 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
528 static 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
540 static jlong android_os_Parcel_create(JNIEnv* env, jclass clazz)
541 {
542     Parcel* parcel = new Parcel();
543     return reinterpret_cast<jlong>(parcel);
544 }
545
546 static 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
554 static void android_os_Parcel_destroy(JNIEnv* env, jclass clazz, jlong nativePtr)
555 {
556     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
557     delete parcel;
558 }
559
560 static 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
589 static 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
610 static 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
628 static 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
640 static 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
655 static 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
691 // ----------------------------------------------------------------------------
692
693 static const JNINativeMethod gParcelMethods[] = {
694     {"nativeDataSize",            "(J)I", (void*)android_os_Parcel_dataSize},
695     {"nativeDataAvail",           "(J)I", (void*)android_os_Parcel_dataAvail},
696     {"nativeDataPosition",        "(J)I", (void*)android_os_Parcel_dataPosition},
697     {"nativeDataCapacity",        "(J)I", (void*)android_os_Parcel_dataCapacity},
698     {"nativeSetDataSize",         "(JI)V", (void*)android_os_Parcel_setDataSize},
699     {"nativeSetDataPosition",     "(JI)V", (void*)android_os_Parcel_setDataPosition},
700     {"nativeSetDataCapacity",     "(JI)V", (void*)android_os_Parcel_setDataCapacity},
701
702     {"nativePushAllowFds",        "(JZ)Z", (void*)android_os_Parcel_pushAllowFds},
703     {"nativeRestoreAllowFds",     "(JZ)V", (void*)android_os_Parcel_restoreAllowFds},
704
705     {"nativeWriteByteArray",      "(J[BII)V", (void*)android_os_Parcel_writeNative},
706     {"nativeWriteBlob",           "(J[BII)V", (void*)android_os_Parcel_writeBlob},
707     {"nativeWriteInt",            "(JI)V", (void*)android_os_Parcel_writeInt},
708     {"nativeWriteLong",           "(JJ)V", (void*)android_os_Parcel_writeLong},
709     {"nativeWriteFloat",          "(JF)V", (void*)android_os_Parcel_writeFloat},
710     {"nativeWriteDouble",         "(JD)V", (void*)android_os_Parcel_writeDouble},
711     {"nativeWriteString",         "(JLjava/lang/String;)V", (void*)android_os_Parcel_writeString},
712     {"nativeWriteStrongBinder",   "(JLandroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder},
713     {"nativeWriteFileDescriptor", "(JLjava/io/FileDescriptor;)V", (void*)android_os_Parcel_writeFileDescriptor},
714
715     {"nativeCreateByteArray",     "(J)[B", (void*)android_os_Parcel_createByteArray},
716     {"nativeReadBlob",            "(J)[B", (void*)android_os_Parcel_readBlob},
717     {"nativeReadInt",             "(J)I", (void*)android_os_Parcel_readInt},
718     {"nativeReadLong",            "(J)J", (void*)android_os_Parcel_readLong},
719     {"nativeReadFloat",           "(J)F", (void*)android_os_Parcel_readFloat},
720     {"nativeReadDouble",          "(J)D", (void*)android_os_Parcel_readDouble},
721     {"nativeReadString",          "(J)Ljava/lang/String;", (void*)android_os_Parcel_readString},
722     {"nativeReadStrongBinder",    "(J)Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder},
723     {"nativeReadFileDescriptor",  "(J)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_readFileDescriptor},
724
725     {"openFileDescriptor",        "(Ljava/lang/String;I)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_openFileDescriptor},
726     {"dupFileDescriptor",         "(Ljava/io/FileDescriptor;)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_dupFileDescriptor},
727     {"closeFileDescriptor",       "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_closeFileDescriptor},
728     {"clearFileDescriptor",       "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_clearFileDescriptor},
729
730     {"nativeCreate",              "()J", (void*)android_os_Parcel_create},
731     {"nativeFreeBuffer",          "(J)V", (void*)android_os_Parcel_freeBuffer},
732     {"nativeDestroy",             "(J)V", (void*)android_os_Parcel_destroy},
733
734     {"nativeMarshall",            "(J)[B", (void*)android_os_Parcel_marshall},
735     {"nativeUnmarshall",          "(J[BII)V", (void*)android_os_Parcel_unmarshall},
736     {"nativeAppendFrom",          "(JJII)V", (void*)android_os_Parcel_appendFrom},
737     {"nativeHasFileDescriptors",  "(J)Z", (void*)android_os_Parcel_hasFileDescriptors},
738     {"nativeWriteInterfaceToken", "(JLjava/lang/String;)V", (void*)android_os_Parcel_writeInterfaceToken},
739     {"nativeEnforceInterface",    "(JLjava/lang/String;)V", (void*)android_os_Parcel_enforceInterface},
740 };
741
742 const char* const kParcelPathName = "android/os/Parcel";
743
744 int register_android_os_Parcel(JNIEnv* env)
745 {
746     jclass clazz;
747
748     clazz = env->FindClass(kParcelPathName);
749     LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Parcel");
750
751     gParcelOffsets.clazz = (jclass) env->NewGlobalRef(clazz);
752     gParcelOffsets.mNativePtr = env->GetFieldID(clazz, "mNativePtr", "J");
753     gParcelOffsets.obtain = env->GetStaticMethodID(clazz, "obtain",
754                                                    "()Landroid/os/Parcel;");
755     gParcelOffsets.recycle = env->GetMethodID(clazz, "recycle", "()V");
756
757     return AndroidRuntime::registerNativeMethods(
758         env, kParcelPathName,
759         gParcelMethods, NELEM(gParcelMethods));
760 }
761
762 };