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