• 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 <nativehelper/JNIPlatformHelp.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_markSensitive(jlong nativePtr)93 static void android_os_Parcel_markSensitive(jlong nativePtr)
94 {
95     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
96     if (parcel) {
97         parcel->markSensitive();
98     }
99 }
100 
android_os_Parcel_markForBinder(JNIEnv * env,jclass clazz,jlong nativePtr,jobject binder)101 static void android_os_Parcel_markForBinder(JNIEnv* env, jclass clazz, jlong nativePtr,
102                                             jobject binder)
103 {
104     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
105     if (parcel) {
106         parcel->markForBinder(ibinderForJavaObject(env, binder));
107     }
108 }
109 
android_os_Parcel_dataSize(jlong nativePtr)110 static jint android_os_Parcel_dataSize(jlong nativePtr)
111 {
112     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
113     return parcel ? parcel->dataSize() : 0;
114 }
115 
android_os_Parcel_dataAvail(jlong nativePtr)116 static jint android_os_Parcel_dataAvail(jlong nativePtr)
117 {
118     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
119     return parcel ? parcel->dataAvail() : 0;
120 }
121 
android_os_Parcel_dataPosition(jlong nativePtr)122 static jint android_os_Parcel_dataPosition(jlong nativePtr)
123 {
124     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
125     return parcel ? parcel->dataPosition() : 0;
126 }
127 
android_os_Parcel_dataCapacity(jlong nativePtr)128 static jint android_os_Parcel_dataCapacity(jlong nativePtr)
129 {
130     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
131     return parcel ? parcel->dataCapacity() : 0;
132 }
133 
android_os_Parcel_setDataSize(JNIEnv * env,jclass clazz,jlong nativePtr,jint size)134 static void android_os_Parcel_setDataSize(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->setDataSize(size);
139         if (err != NO_ERROR) {
140             signalExceptionForError(env, clazz, err);
141         }
142     }
143 }
144 
android_os_Parcel_setDataPosition(jlong nativePtr,jint pos)145 static void android_os_Parcel_setDataPosition(jlong nativePtr, jint pos)
146 {
147     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
148     if (parcel != NULL) {
149         parcel->setDataPosition(pos);
150     }
151 }
152 
android_os_Parcel_setDataCapacity(JNIEnv * env,jclass clazz,jlong nativePtr,jint size)153 static void android_os_Parcel_setDataCapacity(JNIEnv* env, jclass clazz, jlong nativePtr, jint size)
154 {
155     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
156     if (parcel != NULL) {
157         const status_t err = parcel->setDataCapacity(size);
158         if (err != NO_ERROR) {
159             signalExceptionForError(env, clazz, err);
160         }
161     }
162 }
163 
android_os_Parcel_pushAllowFds(jlong nativePtr,jboolean allowFds)164 static jboolean android_os_Parcel_pushAllowFds(jlong nativePtr, jboolean allowFds)
165 {
166     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
167     jboolean ret = JNI_TRUE;
168     if (parcel != NULL) {
169         ret = (jboolean)parcel->pushAllowFds(allowFds);
170     }
171     return ret;
172 }
173 
android_os_Parcel_restoreAllowFds(jlong nativePtr,jboolean lastValue)174 static void android_os_Parcel_restoreAllowFds(jlong nativePtr, jboolean lastValue)
175 {
176     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
177     if (parcel != NULL) {
178         parcel->restoreAllowFds((bool)lastValue);
179     }
180 }
181 
android_os_Parcel_writeByteArray(JNIEnv * env,jclass clazz,jlong nativePtr,jobject data,jint offset,jint length)182 static void android_os_Parcel_writeByteArray(JNIEnv* env, jclass clazz, jlong nativePtr,
183                                              jobject data, jint offset, jint length)
184 {
185     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
186     if (parcel == NULL) {
187         return;
188     }
189 
190     const status_t err = parcel->writeInt32(length);
191     if (err != NO_ERROR) {
192         signalExceptionForError(env, clazz, err);
193         return;
194     }
195 
196     void* dest = parcel->writeInplace(length);
197     if (dest == NULL) {
198         signalExceptionForError(env, clazz, NO_MEMORY);
199         return;
200     }
201 
202     jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)data, 0);
203     if (ar) {
204         memcpy(dest, ar + offset, length);
205         env->ReleasePrimitiveArrayCritical((jarray)data, ar, 0);
206     }
207 }
208 
android_os_Parcel_writeBlob(JNIEnv * env,jclass clazz,jlong nativePtr,jobject data,jint offset,jint length)209 static void android_os_Parcel_writeBlob(JNIEnv* env, jclass clazz, jlong nativePtr, jobject data,
210                                         jint offset, jint length) {
211     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
212     if (parcel == NULL) {
213         return;
214     }
215 
216     if (data == NULL) {
217         const status_t err = parcel->writeInt32(-1);
218         if (err != NO_ERROR) {
219             signalExceptionForError(env, clazz, err);
220         }
221         return;
222     }
223 
224     const status_t err = parcel->writeInt32(length);
225     if (err != NO_ERROR) {
226         signalExceptionForError(env, clazz, err);
227         return;
228     }
229 
230     android::Parcel::WritableBlob blob;
231     android::status_t err2 = parcel->writeBlob(length, false, &blob);
232     if (err2 != NO_ERROR) {
233         signalExceptionForError(env, clazz, err2);
234         return;
235     }
236 
237     jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)data, 0);
238     if (ar == NULL) {
239         memset(blob.data(), 0, length);
240     } else {
241         memcpy(blob.data(), ar + offset, length);
242         env->ReleasePrimitiveArrayCritical((jarray)data, ar, 0);
243     }
244 
245     blob.release();
246 }
247 
android_os_Parcel_writeInt(jlong nativePtr,jint val)248 static int android_os_Parcel_writeInt(jlong nativePtr, jint val) {
249     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
250     return (parcel != NULL) ? parcel->writeInt32(val) : OK;
251 }
252 
android_os_Parcel_writeLong(jlong nativePtr,jlong val)253 static int android_os_Parcel_writeLong(jlong nativePtr, jlong val) {
254     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
255     return (parcel != NULL) ? parcel->writeInt64(val) : OK;
256 }
257 
android_os_Parcel_writeFloat(jlong nativePtr,jfloat val)258 static int android_os_Parcel_writeFloat(jlong nativePtr, jfloat val) {
259     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
260     return (parcel != NULL) ? parcel->writeFloat(val) : OK;
261 }
262 
android_os_Parcel_writeDouble(jlong nativePtr,jdouble val)263 static int android_os_Parcel_writeDouble(jlong nativePtr, jdouble val) {
264     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
265     return (parcel != NULL) ? parcel->writeDouble(val) : OK;
266 }
267 
android_os_Parcel_nativeSignalExceptionForError(JNIEnv * env,jclass clazz,jint err)268 static void android_os_Parcel_nativeSignalExceptionForError(JNIEnv* env, jclass clazz, jint err) {
269     signalExceptionForError(env, clazz, err);
270 }
271 
android_os_Parcel_writeString8(JNIEnv * env,jclass clazz,jlong nativePtr,jstring val)272 static void android_os_Parcel_writeString8(JNIEnv *env, jclass clazz, jlong nativePtr,
273         jstring val) {
274     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
275     if (parcel != nullptr) {
276         status_t err = NO_ERROR;
277         if (val) {
278             // NOTE: Keep this logic in sync with Parcel.cpp
279             const size_t len = env->GetStringLength(val);
280             const size_t allocLen = env->GetStringUTFLength(val);
281             err = parcel->writeInt32(allocLen);
282             char *data = reinterpret_cast<char*>(parcel->writeInplace(allocLen + sizeof(char)));
283             if (data != nullptr) {
284                 env->GetStringUTFRegion(val, 0, len, data);
285                 *(data + allocLen) = 0;
286             } else {
287                 err = NO_MEMORY;
288             }
289         } else {
290             err = parcel->writeString8(nullptr, 0);
291         }
292         if (err != NO_ERROR) {
293             signalExceptionForError(env, clazz, err);
294         }
295     }
296 }
297 
android_os_Parcel_writeString16(JNIEnv * env,jclass clazz,jlong nativePtr,jstring val)298 static void android_os_Parcel_writeString16(JNIEnv *env, jclass clazz, jlong nativePtr,
299         jstring val) {
300     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
301     if (parcel != nullptr) {
302         status_t err = NO_ERROR;
303         if (val) {
304             // NOTE: Keep this logic in sync with Parcel.cpp
305             const size_t len = env->GetStringLength(val);
306             const size_t allocLen = len * sizeof(char16_t);
307             err = parcel->writeInt32(len);
308             char *data = reinterpret_cast<char*>(parcel->writeInplace(allocLen + sizeof(char16_t)));
309             if (data != nullptr) {
310                 env->GetStringRegion(val, 0, len, reinterpret_cast<jchar*>(data));
311                 *reinterpret_cast<char16_t*>(data + allocLen) = 0;
312             } else {
313                 err = NO_MEMORY;
314             }
315         } else {
316             err = parcel->writeString16(nullptr, 0);
317         }
318         if (err != NO_ERROR) {
319             signalExceptionForError(env, clazz, err);
320         }
321     }
322 }
323 
android_os_Parcel_writeStrongBinder(JNIEnv * env,jclass clazz,jlong nativePtr,jobject object)324 static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
325 {
326     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
327     if (parcel != NULL) {
328         const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
329         if (err != NO_ERROR) {
330             signalExceptionForError(env, clazz, err);
331         }
332     }
333 }
334 
android_os_Parcel_writeFileDescriptor(JNIEnv * env,jclass clazz,jlong nativePtr,jobject object)335 static void android_os_Parcel_writeFileDescriptor(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
336 {
337     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
338     if (parcel != NULL) {
339         const status_t err =
340                 parcel->writeDupFileDescriptor(jniGetFDFromFileDescriptor(env, object));
341         if (err != NO_ERROR) {
342             signalExceptionForError(env, clazz, err);
343         }
344     }
345 }
346 
android_os_Parcel_createByteArray(JNIEnv * env,jclass clazz,jlong nativePtr)347 static jbyteArray android_os_Parcel_createByteArray(JNIEnv* env, jclass clazz, jlong nativePtr)
348 {
349     jbyteArray ret = NULL;
350 
351     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
352     if (parcel != NULL) {
353         int32_t len = parcel->readInt32();
354 
355         // Validate the stored length against the true data size
356         if (len >= 0 && len <= (int32_t)parcel->dataAvail()) {
357             ret = env->NewByteArray(len);
358 
359             if (ret != NULL) {
360                 jbyte* a2 = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
361                 if (a2) {
362                     const void* data = parcel->readInplace(len);
363                     if (data) {
364                         memcpy(a2, data, len);
365                     }
366                     env->ReleasePrimitiveArrayCritical(ret, a2, 0);
367                     if (!data) {
368                         ret = NULL;
369                     }
370                 }
371             }
372         }
373     }
374 
375     return ret;
376 }
377 
android_os_Parcel_readByteArray(JNIEnv * env,jclass clazz,jlong nativePtr,jobject dest,jint destLen)378 static jboolean android_os_Parcel_readByteArray(JNIEnv* env, jclass clazz, jlong nativePtr,
379                                                 jobject dest, jint destLen)
380 {
381     jboolean ret = JNI_FALSE;
382     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
383     if (parcel == NULL) {
384         return ret;
385     }
386 
387     int32_t len = parcel->readInt32();
388     if (len >= 0 && len <= (int32_t)parcel->dataAvail() && len == destLen) {
389         jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)dest, 0);
390         if (ar) {
391             const void* data = parcel->readInplace(len);
392             if (data) {
393                 memcpy(ar, data, len);
394                 ret = JNI_TRUE;
395             } else {
396                 ret = JNI_FALSE;
397             }
398 
399             env->ReleasePrimitiveArrayCritical((jarray)dest, ar, 0);
400         }
401     }
402     return ret;
403 }
404 
android_os_Parcel_readBlob(JNIEnv * env,jclass clazz,jlong nativePtr)405 static jbyteArray android_os_Parcel_readBlob(JNIEnv* env, jclass clazz, jlong nativePtr)
406 {
407     jbyteArray ret = NULL;
408 
409     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
410     if (parcel != NULL) {
411         int32_t len = parcel->readInt32();
412         if (len >= 0) {
413             android::Parcel::ReadableBlob blob;
414             android::status_t err = parcel->readBlob(len, &blob);
415             if (err != NO_ERROR) {
416                 signalExceptionForError(env, clazz, err);
417                 return NULL;
418             }
419 
420             ret = env->NewByteArray(len);
421             if (ret != NULL) {
422                 jbyte* a2 = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
423                 if (a2) {
424                     memcpy(a2, blob.data(), len);
425                     env->ReleasePrimitiveArrayCritical(ret, a2, 0);
426                 }
427             }
428             blob.release();
429         }
430     }
431 
432     return ret;
433 }
434 
android_os_Parcel_readInt(jlong nativePtr)435 static jint android_os_Parcel_readInt(jlong nativePtr)
436 {
437     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
438     if (parcel != NULL) {
439         return parcel->readInt32();
440     }
441     return 0;
442 }
443 
android_os_Parcel_readLong(jlong nativePtr)444 static jlong android_os_Parcel_readLong(jlong nativePtr)
445 {
446     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
447     if (parcel != NULL) {
448         return parcel->readInt64();
449     }
450     return 0;
451 }
452 
android_os_Parcel_readFloat(jlong nativePtr)453 static jfloat android_os_Parcel_readFloat(jlong nativePtr)
454 {
455     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
456     if (parcel != NULL) {
457         return parcel->readFloat();
458     }
459     return 0;
460 }
461 
android_os_Parcel_readDouble(jlong nativePtr)462 static jdouble android_os_Parcel_readDouble(jlong nativePtr)
463 {
464     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
465     if (parcel != NULL) {
466         return parcel->readDouble();
467     }
468     return 0;
469 }
470 
android_os_Parcel_readString8(JNIEnv * env,jclass clazz,jlong nativePtr)471 static jstring android_os_Parcel_readString8(JNIEnv* env, jclass clazz, jlong nativePtr)
472 {
473     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
474     if (parcel != NULL) {
475         size_t len;
476         const char* str = parcel->readString8Inplace(&len);
477         if (str) {
478             return env->NewStringUTF(str);
479         }
480         return NULL;
481     }
482     return NULL;
483 }
484 
android_os_Parcel_readString16(JNIEnv * env,jclass clazz,jlong nativePtr)485 static jstring android_os_Parcel_readString16(JNIEnv* env, jclass clazz, jlong nativePtr)
486 {
487     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
488     if (parcel != NULL) {
489         size_t len;
490         const char16_t* str = parcel->readString16Inplace(&len);
491         if (str) {
492             return env->NewString(reinterpret_cast<const jchar*>(str), len);
493         }
494         return NULL;
495     }
496     return NULL;
497 }
498 
android_os_Parcel_readStrongBinder(JNIEnv * env,jclass clazz,jlong nativePtr)499 static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)
500 {
501     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
502     if (parcel != NULL) {
503         return javaObjectForIBinder(env, parcel->readStrongBinder());
504     }
505     return NULL;
506 }
507 
android_os_Parcel_readFileDescriptor(JNIEnv * env,jclass clazz,jlong nativePtr)508 static jobject android_os_Parcel_readFileDescriptor(JNIEnv* env, jclass clazz, jlong nativePtr)
509 {
510     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
511     if (parcel != NULL) {
512         int fd = parcel->readFileDescriptor();
513         if (fd < 0) return NULL;
514         fd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
515         if (fd < 0) return NULL;
516         jobject jifd = jniCreateFileDescriptor(env, fd);
517         if (jifd == NULL) {
518             close(fd);
519         }
520         return jifd;
521     }
522     return NULL;
523 }
524 
android_os_Parcel_create(JNIEnv * env,jclass clazz)525 static jlong android_os_Parcel_create(JNIEnv* env, jclass clazz)
526 {
527     Parcel* parcel = new Parcel();
528     return reinterpret_cast<jlong>(parcel);
529 }
530 
android_os_Parcel_freeBuffer(JNIEnv * env,jclass clazz,jlong nativePtr)531 static void android_os_Parcel_freeBuffer(JNIEnv* env, jclass clazz, jlong nativePtr)
532 {
533     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
534     if (parcel != NULL) {
535         parcel->freeData();
536     }
537 }
538 
android_os_Parcel_destroy(JNIEnv * env,jclass clazz,jlong nativePtr)539 static void android_os_Parcel_destroy(JNIEnv* env, jclass clazz, jlong nativePtr)
540 {
541     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
542     delete parcel;
543 }
544 
android_os_Parcel_marshall(JNIEnv * env,jclass clazz,jlong nativePtr)545 static jbyteArray android_os_Parcel_marshall(JNIEnv* env, jclass clazz, jlong nativePtr)
546 {
547     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
548     if (parcel == NULL) {
549        return NULL;
550     }
551 
552     // do not marshall if there are binder objects in the parcel
553     if (parcel->objectsCount())
554     {
555         jniThrowException(env, "java/lang/RuntimeException", "Tried to marshall a Parcel that contained Binder objects.");
556         return NULL;
557     }
558 
559     jbyteArray ret = env->NewByteArray(parcel->dataSize());
560 
561     if (ret != NULL)
562     {
563         jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
564         if (array != NULL)
565         {
566             memcpy(array, parcel->data(), parcel->dataSize());
567             env->ReleasePrimitiveArrayCritical(ret, array, 0);
568         }
569     }
570 
571     return ret;
572 }
573 
android_os_Parcel_unmarshall(JNIEnv * env,jclass clazz,jlong nativePtr,jbyteArray data,jint offset,jint length)574 static void android_os_Parcel_unmarshall(JNIEnv* env, jclass clazz, jlong nativePtr,
575                                           jbyteArray data, jint offset, jint length)
576 {
577     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
578     if (parcel == NULL || length < 0) {
579        return;
580     }
581 
582     jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(data, 0);
583     if (array)
584     {
585         parcel->setDataSize(length);
586         parcel->setDataPosition(0);
587 
588         void* raw = parcel->writeInplace(length);
589         memcpy(raw, (array + offset), length);
590 
591         env->ReleasePrimitiveArrayCritical(data, array, 0);
592     }
593 }
594 
android_os_Parcel_compareData(JNIEnv * env,jclass clazz,jlong thisNativePtr,jlong otherNativePtr)595 static jint android_os_Parcel_compareData(JNIEnv* env, jclass clazz, jlong thisNativePtr,
596                                           jlong otherNativePtr)
597 {
598     Parcel* thisParcel = reinterpret_cast<Parcel*>(thisNativePtr);
599     LOG_ALWAYS_FATAL_IF(thisParcel == nullptr, "Should not be null");
600 
601     Parcel* otherParcel = reinterpret_cast<Parcel*>(otherNativePtr);
602     LOG_ALWAYS_FATAL_IF(otherParcel == nullptr, "Should not be null");
603 
604     return thisParcel->compareData(*otherParcel);
605 }
606 
android_os_Parcel_compareDataInRange(JNIEnv * env,jclass clazz,jlong thisNativePtr,jint thisOffset,jlong otherNativePtr,jint otherOffset,jint length)607 static jboolean android_os_Parcel_compareDataInRange(JNIEnv* env, jclass clazz, jlong thisNativePtr,
608                                                      jint thisOffset, jlong otherNativePtr,
609                                                      jint otherOffset, jint length) {
610     Parcel* thisParcel = reinterpret_cast<Parcel*>(thisNativePtr);
611     LOG_ALWAYS_FATAL_IF(thisParcel == nullptr, "Should not be null");
612 
613     Parcel* otherParcel = reinterpret_cast<Parcel*>(otherNativePtr);
614     LOG_ALWAYS_FATAL_IF(otherParcel == nullptr, "Should not be null");
615 
616     int result;
617     status_t err =
618             thisParcel->compareDataInRange(thisOffset, *otherParcel, otherOffset, length, &result);
619     if (err != NO_ERROR) {
620         signalExceptionForError(env, clazz, err);
621         return JNI_FALSE;
622     }
623     return (result == 0) ? JNI_TRUE : JNI_FALSE;
624 }
625 
android_os_Parcel_appendFrom(JNIEnv * env,jclass clazz,jlong thisNativePtr,jlong otherNativePtr,jint offset,jint length)626 static void android_os_Parcel_appendFrom(JNIEnv* env, jclass clazz, jlong thisNativePtr,
627                                           jlong otherNativePtr, jint offset, jint length)
628 {
629     Parcel* thisParcel = reinterpret_cast<Parcel*>(thisNativePtr);
630     if (thisParcel == NULL) {
631        return;
632     }
633     Parcel* otherParcel = reinterpret_cast<Parcel*>(otherNativePtr);
634     if (otherParcel == NULL) {
635        return;
636     }
637 
638     status_t err = thisParcel->appendFrom(otherParcel, offset, length);
639     if (err != NO_ERROR) {
640         signalExceptionForError(env, clazz, err);
641     }
642     return;
643 }
644 
android_os_Parcel_hasFileDescriptors(jlong nativePtr)645 static jboolean android_os_Parcel_hasFileDescriptors(jlong nativePtr)
646 {
647     jboolean ret = JNI_FALSE;
648     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
649     if (parcel != NULL) {
650         if (parcel->hasFileDescriptors()) {
651             ret = JNI_TRUE;
652         }
653     }
654     return ret;
655 }
656 
android_os_Parcel_hasFileDescriptorsInRange(JNIEnv * env,jclass clazz,jlong nativePtr,jint offset,jint length)657 static jboolean android_os_Parcel_hasFileDescriptorsInRange(JNIEnv* env, jclass clazz,
658                                                             jlong nativePtr, jint offset,
659                                                             jint length) {
660     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
661     if (parcel != NULL) {
662         bool result;
663         status_t err = parcel->hasFileDescriptorsInRange(offset, length, &result);
664         if (err != NO_ERROR) {
665             signalExceptionForError(env, clazz, err);
666             return JNI_FALSE;
667         }
668         return result ? JNI_TRUE : JNI_FALSE;
669     }
670     return JNI_FALSE;
671 }
672 
673 // String tries to allocate itself on the stack, within a known size, but will
674 // make a heap allocation if not.
675 template <size_t StackReserve>
676 class StackString {
677 public:
StackString(JNIEnv * env,jstring str)678     StackString(JNIEnv* env, jstring str) : mEnv(env), mJStr(str) {
679         LOG_ALWAYS_FATAL_IF(str == nullptr);
680         mSize = env->GetStringLength(str);
681         if (mSize > StackReserve) {
682             mStr = new jchar[mSize];
683         } else {
684             mStr = &mBuffer[0];
685         }
686         mEnv->GetStringRegion(str, 0, mSize, mStr);
687     }
~StackString()688     ~StackString() {
689         if (mStr != &mBuffer[0]) {
690             delete[] mStr;
691         }
692     }
str()693     const jchar* str() { return mStr; }
size()694     jsize size() { return mSize; }
695 
696 private:
697     JNIEnv* mEnv;
698     jstring mJStr;
699 
700     jchar mBuffer[StackReserve];
701     // pointer to &mBuffer[0] if string fits in mBuffer, otherwise owned
702     jchar* mStr;
703     jsize mSize;
704 };
705 
706 // This size is chosen to be longer than most interface descriptors.
707 // Ones longer than this will be allocated on the heap.
708 typedef StackString<64> InterfaceDescriptorString;
709 
android_os_Parcel_writeInterfaceToken(JNIEnv * env,jclass clazz,jlong nativePtr,jstring name)710 static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jclass clazz, jlong nativePtr,
711                                                   jstring name)
712 {
713     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
714     if (parcel != nullptr) {
715         InterfaceDescriptorString descriptor(env, name);
716         parcel->writeInterfaceToken(reinterpret_cast<const char16_t*>(descriptor.str()),
717                                     descriptor.size());
718     }
719 }
720 
android_os_Parcel_enforceInterface(JNIEnv * env,jclass clazz,jlong nativePtr,jstring name)721 static void android_os_Parcel_enforceInterface(JNIEnv* env, jclass clazz, jlong nativePtr, jstring name)
722 {
723     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
724     if (parcel != nullptr) {
725         InterfaceDescriptorString descriptor(env, name);
726         IPCThreadState* threadState = IPCThreadState::self();
727         const int32_t oldPolicy = threadState->getStrictModePolicy();
728         const bool isValid =
729                 parcel->enforceInterface(reinterpret_cast<const char16_t*>(descriptor.str()),
730                                          descriptor.size(), threadState);
731         if (isValid) {
732             const int32_t newPolicy = threadState->getStrictModePolicy();
733             if (oldPolicy != newPolicy) {
734                 // Need to keep the Java-level thread-local strict
735                 // mode policy in sync for the libcore
736                 // enforcements, which involves an upcall back
737                 // into Java.  (We can't modify the
738                 // Parcel.enforceInterface signature, as it's
739                 // pseudo-public, and used via AIDL
740                 // auto-generation...)
741                 set_dalvik_blockguard_policy(env, newPolicy);
742             }
743             return; // everything was correct -> return silently
744         }
745     }
746 
747     // all error conditions wind up here
748     jniThrowException(env, "java/lang/SecurityException",
749             "Binder invocation to an incorrect interface");
750 }
751 
android_os_Parcel_getGlobalAllocSize(JNIEnv * env,jclass clazz)752 static jlong android_os_Parcel_getGlobalAllocSize(JNIEnv* env, jclass clazz)
753 {
754     return Parcel::getGlobalAllocSize();
755 }
756 
android_os_Parcel_getGlobalAllocCount(JNIEnv * env,jclass clazz)757 static jlong android_os_Parcel_getGlobalAllocCount(JNIEnv* env, jclass clazz)
758 {
759     return Parcel::getGlobalAllocCount();
760 }
761 
android_os_Parcel_getOpenAshmemSize(jlong nativePtr)762 static jlong android_os_Parcel_getOpenAshmemSize(jlong nativePtr)
763 {
764     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
765     if (parcel != NULL) {
766         return parcel->getOpenAshmemSize();
767     }
768     return 0;
769 }
770 
android_os_Parcel_readCallingWorkSourceUid(jlong nativePtr)771 static jint android_os_Parcel_readCallingWorkSourceUid(jlong nativePtr)
772 {
773     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
774     if (parcel != NULL) {
775         return parcel->readCallingWorkSourceUid();
776     }
777     return IPCThreadState::kUnsetWorkSource;
778 }
779 
android_os_Parcel_replaceCallingWorkSourceUid(jlong nativePtr,jint uid)780 static jboolean android_os_Parcel_replaceCallingWorkSourceUid(jlong nativePtr, jint uid)
781 {
782     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
783     if (parcel != NULL) {
784         return parcel->replaceCallingWorkSourceUid(uid);
785     }
786     return false;
787 }
788 
789 // ----------------------------------------------------------------------------
790 
791 static const JNINativeMethod gParcelMethods[] = {
792     // @CriticalNative
793     {"nativeMarkSensitive",       "(J)V", (void*)android_os_Parcel_markSensitive},
794     // @FastNative
795     {"nativeMarkForBinder",       "(JLandroid/os/IBinder;)V", (void*)android_os_Parcel_markForBinder},
796     // @CriticalNative
797     {"nativeDataSize",            "(J)I", (void*)android_os_Parcel_dataSize},
798     // @CriticalNative
799     {"nativeDataAvail",           "(J)I", (void*)android_os_Parcel_dataAvail},
800     // @CriticalNative
801     {"nativeDataPosition",        "(J)I", (void*)android_os_Parcel_dataPosition},
802     // @CriticalNative
803     {"nativeDataCapacity",        "(J)I", (void*)android_os_Parcel_dataCapacity},
804     // @FastNative
805     {"nativeSetDataSize",         "(JI)V", (void*)android_os_Parcel_setDataSize},
806     // @CriticalNative
807     {"nativeSetDataPosition",     "(JI)V", (void*)android_os_Parcel_setDataPosition},
808     // @FastNative
809     {"nativeSetDataCapacity",     "(JI)V", (void*)android_os_Parcel_setDataCapacity},
810 
811     // @CriticalNative
812     {"nativePushAllowFds",        "(JZ)Z", (void*)android_os_Parcel_pushAllowFds},
813     // @CriticalNative
814     {"nativeRestoreAllowFds",     "(JZ)V", (void*)android_os_Parcel_restoreAllowFds},
815 
816     {"nativeWriteByteArray",      "(J[BII)V", (void*)android_os_Parcel_writeByteArray},
817     {"nativeWriteBlob",           "(J[BII)V", (void*)android_os_Parcel_writeBlob},
818     // @CriticalNative
819     {"nativeWriteInt",            "(JI)I", (void*)android_os_Parcel_writeInt},
820     // @CriticalNative
821     {"nativeWriteLong",           "(JJ)I", (void*)android_os_Parcel_writeLong},
822     // @CriticalNative
823     {"nativeWriteFloat",          "(JF)I", (void*)android_os_Parcel_writeFloat},
824     // @CriticalNative
825     {"nativeWriteDouble",         "(JD)I", (void*)android_os_Parcel_writeDouble},
826     {"nativeSignalExceptionForError", "(I)V", (void*)android_os_Parcel_nativeSignalExceptionForError},
827     // @FastNative
828     {"nativeWriteString8",        "(JLjava/lang/String;)V", (void*)android_os_Parcel_writeString8},
829     // @FastNative
830     {"nativeWriteString16",       "(JLjava/lang/String;)V", (void*)android_os_Parcel_writeString16},
831     // @FastNative
832     {"nativeWriteStrongBinder",   "(JLandroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder},
833     // @FastNative
834     {"nativeWriteFileDescriptor", "(JLjava/io/FileDescriptor;)V", (void*)android_os_Parcel_writeFileDescriptor},
835 
836     {"nativeCreateByteArray",     "(J)[B", (void*)android_os_Parcel_createByteArray},
837     {"nativeReadByteArray",       "(J[BI)Z", (void*)android_os_Parcel_readByteArray},
838     {"nativeReadBlob",            "(J)[B", (void*)android_os_Parcel_readBlob},
839     // @CriticalNative
840     {"nativeReadInt",             "(J)I", (void*)android_os_Parcel_readInt},
841     // @CriticalNative
842     {"nativeReadLong",            "(J)J", (void*)android_os_Parcel_readLong},
843     // @CriticalNative
844     {"nativeReadFloat",           "(J)F", (void*)android_os_Parcel_readFloat},
845     // @CriticalNative
846     {"nativeReadDouble",          "(J)D", (void*)android_os_Parcel_readDouble},
847     // @FastNative
848     {"nativeReadString8",         "(J)Ljava/lang/String;", (void*)android_os_Parcel_readString8},
849     // @FastNative
850     {"nativeReadString16",        "(J)Ljava/lang/String;", (void*)android_os_Parcel_readString16},
851     // @FastNative
852     {"nativeReadStrongBinder",    "(J)Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder},
853     // @FastNative
854     {"nativeReadFileDescriptor",  "(J)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_readFileDescriptor},
855 
856     {"nativeCreate",              "()J", (void*)android_os_Parcel_create},
857     {"nativeFreeBuffer",          "(J)V", (void*)android_os_Parcel_freeBuffer},
858     {"nativeDestroy",             "(J)V", (void*)android_os_Parcel_destroy},
859 
860     {"nativeMarshall",            "(J)[B", (void*)android_os_Parcel_marshall},
861     {"nativeUnmarshall",          "(J[BII)V", (void*)android_os_Parcel_unmarshall},
862     {"nativeCompareData",         "(JJ)I", (void*)android_os_Parcel_compareData},
863     {"nativeCompareDataInRange",  "(JIJII)Z", (void*)android_os_Parcel_compareDataInRange},
864     {"nativeAppendFrom",          "(JJII)V", (void*)android_os_Parcel_appendFrom},
865     // @CriticalNative
866     {"nativeHasFileDescriptors",  "(J)Z", (void*)android_os_Parcel_hasFileDescriptors},
867     {"nativeHasFileDescriptorsInRange",  "(JII)Z", (void*)android_os_Parcel_hasFileDescriptorsInRange},
868     {"nativeWriteInterfaceToken", "(JLjava/lang/String;)V", (void*)android_os_Parcel_writeInterfaceToken},
869     {"nativeEnforceInterface",    "(JLjava/lang/String;)V", (void*)android_os_Parcel_enforceInterface},
870 
871     {"getGlobalAllocSize",        "()J", (void*)android_os_Parcel_getGlobalAllocSize},
872     {"getGlobalAllocCount",       "()J", (void*)android_os_Parcel_getGlobalAllocCount},
873 
874     // @CriticalNative
875     {"nativeGetOpenAshmemSize",       "(J)J", (void*)android_os_Parcel_getOpenAshmemSize},
876 
877     // @CriticalNative
878     {"nativeReadCallingWorkSourceUid", "(J)I", (void*)android_os_Parcel_readCallingWorkSourceUid},
879     // @CriticalNative
880     {"nativeReplaceCallingWorkSourceUid", "(JI)Z", (void*)android_os_Parcel_replaceCallingWorkSourceUid},
881 };
882 
883 const char* const kParcelPathName = "android/os/Parcel";
884 
register_android_os_Parcel(JNIEnv * env)885 int register_android_os_Parcel(JNIEnv* env)
886 {
887     jclass clazz = FindClassOrDie(env, kParcelPathName);
888 
889     gParcelOffsets.clazz = MakeGlobalRefOrDie(env, clazz);
890     gParcelOffsets.mNativePtr = GetFieldIDOrDie(env, clazz, "mNativePtr", "J");
891     gParcelOffsets.obtain = GetStaticMethodIDOrDie(env, clazz, "obtain", "()Landroid/os/Parcel;");
892     gParcelOffsets.recycle = GetMethodIDOrDie(env, clazz, "recycle", "()V");
893 
894     return RegisterMethodsOrDie(env, kParcelPathName, gParcelMethods, NELEM(gParcelMethods));
895 }
896 
897 };
898