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