• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
parcelForJavaObject(JNIEnv * env,jobject obj)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 
createJavaParcelObject(JNIEnv * env)81 jobject createJavaParcelObject(JNIEnv* env)
82 {
83     return env->CallStaticObjectMethod(gParcelOffsets.clazz, gParcelOffsets.obtain);
84 }
85 
recycleJavaParcelObject(JNIEnv * env,jobject parcelObj)86 void recycleJavaParcelObject(JNIEnv* env, jobject parcelObj)
87 {
88     env->CallVoidMethod(parcelObj, gParcelOffsets.recycle);
89 }
90 
android_os_Parcel_dataSize(JNIEnv * env,jclass clazz,jlong nativePtr)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 
android_os_Parcel_dataAvail(JNIEnv * env,jclass clazz,jlong nativePtr)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 
android_os_Parcel_dataPosition(JNIEnv * env,jclass clazz,jlong nativePtr)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 
android_os_Parcel_dataCapacity(JNIEnv * env,jclass clazz,jlong nativePtr)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 
android_os_Parcel_setDataSize(JNIEnv * env,jclass clazz,jlong nativePtr,jint size)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 
android_os_Parcel_setDataPosition(JNIEnv * env,jclass clazz,jlong nativePtr,jint pos)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 
android_os_Parcel_setDataCapacity(JNIEnv * env,jclass clazz,jlong nativePtr,jint size)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 
android_os_Parcel_pushAllowFds(JNIEnv * env,jclass clazz,jlong nativePtr,jboolean allowFds)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 
android_os_Parcel_restoreAllowFds(JNIEnv * env,jclass clazz,jlong nativePtr,jboolean lastValue)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 
android_os_Parcel_writeNative(JNIEnv * env,jclass clazz,jlong nativePtr,jobject data,jint offset,jint length)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 
android_os_Parcel_writeBlob(JNIEnv * env,jclass clazz,jlong nativePtr,jobject data,jint offset,jint length)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 
android_os_Parcel_writeInt(JNIEnv * env,jclass clazz,jlong nativePtr,jint val)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 
android_os_Parcel_writeLong(JNIEnv * env,jclass clazz,jlong nativePtr,jlong val)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 
android_os_Parcel_writeFloat(JNIEnv * env,jclass clazz,jlong nativePtr,jfloat val)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 
android_os_Parcel_writeDouble(JNIEnv * env,jclass clazz,jlong nativePtr,jdouble val)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 
android_os_Parcel_writeString(JNIEnv * env,jclass clazz,jlong nativePtr,jstring val)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 
android_os_Parcel_writeStrongBinder(JNIEnv * env,jclass clazz,jlong nativePtr,jobject object)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 
android_os_Parcel_writeFileDescriptor(JNIEnv * env,jclass clazz,jlong nativePtr,jobject object)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 
android_os_Parcel_createByteArray(JNIEnv * env,jclass clazz,jlong nativePtr)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 
android_os_Parcel_readBlob(JNIEnv * env,jclass clazz,jlong nativePtr)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 
android_os_Parcel_readInt(JNIEnv * env,jclass clazz,jlong nativePtr)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 
android_os_Parcel_readLong(JNIEnv * env,jclass clazz,jlong nativePtr)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 
android_os_Parcel_readFloat(JNIEnv * env,jclass clazz,jlong nativePtr)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 
android_os_Parcel_readDouble(JNIEnv * env,jclass clazz,jlong nativePtr)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 
android_os_Parcel_readString(JNIEnv * env,jclass clazz,jlong nativePtr)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 
android_os_Parcel_readStrongBinder(JNIEnv * env,jclass clazz,jlong nativePtr)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 
android_os_Parcel_readFileDescriptor(JNIEnv * env,jclass clazz,jlong nativePtr)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 
android_os_Parcel_openFileDescriptor(JNIEnv * env,jclass clazz,jstring name,jint mode)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 
android_os_Parcel_dupFileDescriptor(JNIEnv * env,jclass clazz,jobject orig)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 
android_os_Parcel_closeFileDescriptor(JNIEnv * env,jclass clazz,jobject object)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 
android_os_Parcel_clearFileDescriptor(JNIEnv * env,jclass clazz,jobject object)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 
android_os_Parcel_create(JNIEnv * env,jclass clazz)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 
android_os_Parcel_freeBuffer(JNIEnv * env,jclass clazz,jlong nativePtr)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 
android_os_Parcel_destroy(JNIEnv * env,jclass clazz,jlong nativePtr)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 
android_os_Parcel_marshall(JNIEnv * env,jclass clazz,jlong nativePtr)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 
android_os_Parcel_unmarshall(JNIEnv * env,jclass clazz,jlong nativePtr,jbyteArray data,jint offset,jint length)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 
android_os_Parcel_appendFrom(JNIEnv * env,jclass clazz,jlong thisNativePtr,jlong otherNativePtr,jint offset,jint length)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 
android_os_Parcel_hasFileDescriptors(JNIEnv * env,jclass clazz,jlong nativePtr)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 
android_os_Parcel_writeInterfaceToken(JNIEnv * env,jclass clazz,jlong nativePtr,jstring name)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 
android_os_Parcel_enforceInterface(JNIEnv * env,jclass clazz,jlong nativePtr,jstring name)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 
android_os_Parcel_getGlobalAllocSize(JNIEnv * env,jclass clazz)691 static jlong android_os_Parcel_getGlobalAllocSize(JNIEnv* env, jclass clazz)
692 {
693     return Parcel::getGlobalAllocSize();
694 }
695 
android_os_Parcel_getGlobalAllocCount(JNIEnv * env,jclass clazz)696 static jlong android_os_Parcel_getGlobalAllocCount(JNIEnv* env, jclass clazz)
697 {
698     return Parcel::getGlobalAllocCount();
699 }
700 
701 // ----------------------------------------------------------------------------
702 
703 static 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 
755 const char* const kParcelPathName = "android/os/Parcel";
756 
register_android_os_Parcel(JNIEnv * env)757 int 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