• 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/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_writeString8(JNIEnv * env,jclass clazz,jlong nativePtr,jstring val)276 static void android_os_Parcel_writeString8(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 size_t len = env->GetStringUTFLength(val);
283             const char* str = env->GetStringUTFChars(val, 0);
284             if (str) {
285                 err = parcel->writeString8(str, len);
286                 env->ReleaseStringUTFChars(val, str);
287             }
288         } else {
289             err = parcel->writeString8(NULL, 0);
290         }
291         if (err != NO_ERROR) {
292             signalExceptionForError(env, clazz, err);
293         }
294     }
295 }
296 
android_os_Parcel_writeString16(JNIEnv * env,jclass clazz,jlong nativePtr,jstring val)297 static void android_os_Parcel_writeString16(JNIEnv* env, jclass clazz, jlong nativePtr, jstring val)
298 {
299     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
300     if (parcel != NULL) {
301         status_t err = NO_MEMORY;
302         if (val) {
303             const jchar* str = env->GetStringCritical(val, 0);
304             if (str) {
305                 err = parcel->writeString16(
306                     reinterpret_cast<const char16_t*>(str),
307                     env->GetStringLength(val));
308                 env->ReleaseStringCritical(val, str);
309             }
310         } else {
311             err = parcel->writeString16(NULL, 0);
312         }
313         if (err != NO_ERROR) {
314             signalExceptionForError(env, clazz, err);
315         }
316     }
317 }
318 
android_os_Parcel_writeStrongBinder(JNIEnv * env,jclass clazz,jlong nativePtr,jobject object)319 static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
320 {
321     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
322     if (parcel != NULL) {
323         const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
324         if (err != NO_ERROR) {
325             signalExceptionForError(env, clazz, err);
326         }
327     }
328 }
329 
android_os_Parcel_writeFileDescriptor(JNIEnv * env,jclass clazz,jlong nativePtr,jobject object)330 static jlong android_os_Parcel_writeFileDescriptor(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
331 {
332     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
333     if (parcel != NULL) {
334         const status_t err =
335                 parcel->writeDupFileDescriptor(jniGetFDFromFileDescriptor(env, object));
336         if (err != NO_ERROR) {
337             signalExceptionForError(env, clazz, err);
338         }
339         return parcel->getOpenAshmemSize();
340     }
341     return 0;
342 }
343 
android_os_Parcel_createByteArray(JNIEnv * env,jclass clazz,jlong nativePtr)344 static jbyteArray android_os_Parcel_createByteArray(JNIEnv* env, jclass clazz, jlong nativePtr)
345 {
346     jbyteArray ret = NULL;
347 
348     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
349     if (parcel != NULL) {
350         int32_t len = parcel->readInt32();
351 
352         // sanity check the stored length against the true data size
353         if (len >= 0 && len <= (int32_t)parcel->dataAvail()) {
354             ret = env->NewByteArray(len);
355 
356             if (ret != NULL) {
357                 jbyte* a2 = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
358                 if (a2) {
359                     const void* data = parcel->readInplace(len);
360                     if (data) {
361                         memcpy(a2, data, len);
362                     }
363                     env->ReleasePrimitiveArrayCritical(ret, a2, 0);
364                     if (!data) {
365                         ret = NULL;
366                     }
367                 }
368             }
369         }
370     }
371 
372     return ret;
373 }
374 
android_os_Parcel_readByteArray(JNIEnv * env,jclass clazz,jlong nativePtr,jobject dest,jint destLen)375 static jboolean android_os_Parcel_readByteArray(JNIEnv* env, jclass clazz, jlong nativePtr,
376                                                 jobject dest, jint destLen)
377 {
378     jboolean ret = JNI_FALSE;
379     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
380     if (parcel == NULL) {
381         return ret;
382     }
383 
384     int32_t len = parcel->readInt32();
385     if (len >= 0 && len <= (int32_t)parcel->dataAvail() && len == destLen) {
386         jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)dest, 0);
387         if (ar) {
388             const void* data = parcel->readInplace(len);
389             if (data) {
390                 memcpy(ar, data, len);
391                 ret = JNI_TRUE;
392             } else {
393                 ret = JNI_FALSE;
394             }
395 
396             env->ReleasePrimitiveArrayCritical((jarray)dest, ar, 0);
397         }
398     }
399     return ret;
400 }
401 
android_os_Parcel_readBlob(JNIEnv * env,jclass clazz,jlong nativePtr)402 static jbyteArray android_os_Parcel_readBlob(JNIEnv* env, jclass clazz, jlong nativePtr)
403 {
404     jbyteArray ret = NULL;
405 
406     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
407     if (parcel != NULL) {
408         int32_t len = parcel->readInt32();
409         if (len >= 0) {
410             android::Parcel::ReadableBlob blob;
411             android::status_t err = parcel->readBlob(len, &blob);
412             if (err != NO_ERROR) {
413                 signalExceptionForError(env, clazz, err);
414                 return NULL;
415             }
416 
417             ret = env->NewByteArray(len);
418             if (ret != NULL) {
419                 jbyte* a2 = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
420                 if (a2) {
421                     memcpy(a2, blob.data(), len);
422                     env->ReleasePrimitiveArrayCritical(ret, a2, 0);
423                 }
424             }
425             blob.release();
426         }
427     }
428 
429     return ret;
430 }
431 
android_os_Parcel_readInt(jlong nativePtr)432 static jint android_os_Parcel_readInt(jlong nativePtr)
433 {
434     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
435     if (parcel != NULL) {
436         return parcel->readInt32();
437     }
438     return 0;
439 }
440 
android_os_Parcel_readLong(jlong nativePtr)441 static jlong android_os_Parcel_readLong(jlong nativePtr)
442 {
443     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
444     if (parcel != NULL) {
445         return parcel->readInt64();
446     }
447     return 0;
448 }
449 
android_os_Parcel_readFloat(jlong nativePtr)450 static jfloat android_os_Parcel_readFloat(jlong nativePtr)
451 {
452     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
453     if (parcel != NULL) {
454         return parcel->readFloat();
455     }
456     return 0;
457 }
458 
android_os_Parcel_readDouble(jlong nativePtr)459 static jdouble android_os_Parcel_readDouble(jlong nativePtr)
460 {
461     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
462     if (parcel != NULL) {
463         return parcel->readDouble();
464     }
465     return 0;
466 }
467 
android_os_Parcel_readString8(JNIEnv * env,jclass clazz,jlong nativePtr)468 static jstring android_os_Parcel_readString8(JNIEnv* env, jclass clazz, jlong nativePtr)
469 {
470     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
471     if (parcel != NULL) {
472         size_t len;
473         const char* str = parcel->readString8Inplace(&len);
474         if (str) {
475             return env->NewStringUTF(str);
476         }
477         return NULL;
478     }
479     return NULL;
480 }
481 
android_os_Parcel_readString16(JNIEnv * env,jclass clazz,jlong nativePtr)482 static jstring android_os_Parcel_readString16(JNIEnv* env, jclass clazz, jlong nativePtr)
483 {
484     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
485     if (parcel != NULL) {
486         size_t len;
487         const char16_t* str = parcel->readString16Inplace(&len);
488         if (str) {
489             return env->NewString(reinterpret_cast<const jchar*>(str), len);
490         }
491         return NULL;
492     }
493     return NULL;
494 }
495 
android_os_Parcel_readStrongBinder(JNIEnv * env,jclass clazz,jlong nativePtr)496 static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)
497 {
498     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
499     if (parcel != NULL) {
500         return javaObjectForIBinder(env, parcel->readStrongBinder());
501     }
502     return NULL;
503 }
504 
android_os_Parcel_readFileDescriptor(JNIEnv * env,jclass clazz,jlong nativePtr)505 static jobject android_os_Parcel_readFileDescriptor(JNIEnv* env, jclass clazz, jlong nativePtr)
506 {
507     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
508     if (parcel != NULL) {
509         int fd = parcel->readFileDescriptor();
510         if (fd < 0) return NULL;
511         fd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
512         if (fd < 0) return NULL;
513         return jniCreateFileDescriptor(env, fd);
514     }
515     return NULL;
516 }
517 
android_os_Parcel_create(JNIEnv * env,jclass clazz)518 static jlong android_os_Parcel_create(JNIEnv* env, jclass clazz)
519 {
520     Parcel* parcel = new Parcel();
521     return reinterpret_cast<jlong>(parcel);
522 }
523 
android_os_Parcel_freeBuffer(JNIEnv * env,jclass clazz,jlong nativePtr)524 static jlong android_os_Parcel_freeBuffer(JNIEnv* env, jclass clazz, jlong nativePtr)
525 {
526     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
527     if (parcel != NULL) {
528         parcel->freeData();
529         return parcel->getOpenAshmemSize();
530     }
531     return 0;
532 }
533 
android_os_Parcel_destroy(JNIEnv * env,jclass clazz,jlong nativePtr)534 static void android_os_Parcel_destroy(JNIEnv* env, jclass clazz, jlong nativePtr)
535 {
536     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
537     delete parcel;
538 }
539 
android_os_Parcel_marshall(JNIEnv * env,jclass clazz,jlong nativePtr)540 static jbyteArray android_os_Parcel_marshall(JNIEnv* env, jclass clazz, jlong nativePtr)
541 {
542     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
543     if (parcel == NULL) {
544        return NULL;
545     }
546 
547     // do not marshall if there are binder objects in the parcel
548     if (parcel->objectsCount())
549     {
550         jniThrowException(env, "java/lang/RuntimeException", "Tried to marshall a Parcel that contained Binder objects.");
551         return NULL;
552     }
553 
554     jbyteArray ret = env->NewByteArray(parcel->dataSize());
555 
556     if (ret != NULL)
557     {
558         jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
559         if (array != NULL)
560         {
561             memcpy(array, parcel->data(), parcel->dataSize());
562             env->ReleasePrimitiveArrayCritical(ret, array, 0);
563         }
564     }
565 
566     return ret;
567 }
568 
android_os_Parcel_unmarshall(JNIEnv * env,jclass clazz,jlong nativePtr,jbyteArray data,jint offset,jint length)569 static jlong android_os_Parcel_unmarshall(JNIEnv* env, jclass clazz, jlong nativePtr,
570                                           jbyteArray data, jint offset, jint length)
571 {
572     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
573     if (parcel == NULL || length < 0) {
574        return 0;
575     }
576 
577     jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(data, 0);
578     if (array)
579     {
580         parcel->setDataSize(length);
581         parcel->setDataPosition(0);
582 
583         void* raw = parcel->writeInplace(length);
584         memcpy(raw, (array + offset), length);
585 
586         env->ReleasePrimitiveArrayCritical(data, array, 0);
587     }
588     return parcel->getOpenAshmemSize();
589 }
590 
android_os_Parcel_compareData(JNIEnv * env,jclass clazz,jlong thisNativePtr,jlong otherNativePtr)591 static jint android_os_Parcel_compareData(JNIEnv* env, jclass clazz, jlong thisNativePtr,
592                                           jlong otherNativePtr)
593 {
594     Parcel* thisParcel = reinterpret_cast<Parcel*>(thisNativePtr);
595     if (thisParcel == NULL) {
596        return 0;
597     }
598     Parcel* otherParcel = reinterpret_cast<Parcel*>(otherNativePtr);
599     if (otherParcel == NULL) {
600        return thisParcel->getOpenAshmemSize();
601     }
602 
603     return thisParcel->compareData(*otherParcel);
604 }
605 
android_os_Parcel_appendFrom(JNIEnv * env,jclass clazz,jlong thisNativePtr,jlong otherNativePtr,jint offset,jint length)606 static jlong android_os_Parcel_appendFrom(JNIEnv* env, jclass clazz, jlong thisNativePtr,
607                                           jlong otherNativePtr, jint offset, jint length)
608 {
609     Parcel* thisParcel = reinterpret_cast<Parcel*>(thisNativePtr);
610     if (thisParcel == NULL) {
611        return 0;
612     }
613     Parcel* otherParcel = reinterpret_cast<Parcel*>(otherNativePtr);
614     if (otherParcel == NULL) {
615        return thisParcel->getOpenAshmemSize();
616     }
617 
618     status_t err = thisParcel->appendFrom(otherParcel, offset, length);
619     if (err != NO_ERROR) {
620         signalExceptionForError(env, clazz, err);
621     }
622     return thisParcel->getOpenAshmemSize();
623 }
624 
android_os_Parcel_hasFileDescriptors(jlong nativePtr)625 static jboolean android_os_Parcel_hasFileDescriptors(jlong nativePtr)
626 {
627     jboolean ret = JNI_FALSE;
628     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
629     if (parcel != NULL) {
630         if (parcel->hasFileDescriptors()) {
631             ret = JNI_TRUE;
632         }
633     }
634     return ret;
635 }
636 
android_os_Parcel_writeInterfaceToken(JNIEnv * env,jclass clazz,jlong nativePtr,jstring name)637 static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jclass clazz, jlong nativePtr,
638                                                   jstring name)
639 {
640     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
641     if (parcel != NULL) {
642         // In the current implementation, the token is just the serialized interface name that
643         // the caller expects to be invoking
644         const jchar* str = env->GetStringCritical(name, 0);
645         if (str != NULL) {
646             parcel->writeInterfaceToken(String16(
647                   reinterpret_cast<const char16_t*>(str),
648                   env->GetStringLength(name)));
649             env->ReleaseStringCritical(name, str);
650         }
651     }
652 }
653 
android_os_Parcel_enforceInterface(JNIEnv * env,jclass clazz,jlong nativePtr,jstring name)654 static void android_os_Parcel_enforceInterface(JNIEnv* env, jclass clazz, jlong nativePtr, jstring name)
655 {
656     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
657     if (parcel != NULL) {
658         const jchar* str = env->GetStringCritical(name, 0);
659         if (str) {
660             IPCThreadState* threadState = IPCThreadState::self();
661             const int32_t oldPolicy = threadState->getStrictModePolicy();
662             const bool isValid = parcel->enforceInterface(
663                 String16(reinterpret_cast<const char16_t*>(str),
664                          env->GetStringLength(name)),
665                 threadState);
666             env->ReleaseStringCritical(name, str);
667             if (isValid) {
668                 const int32_t newPolicy = threadState->getStrictModePolicy();
669                 if (oldPolicy != newPolicy) {
670                     // Need to keep the Java-level thread-local strict
671                     // mode policy in sync for the libcore
672                     // enforcements, which involves an upcall back
673                     // into Java.  (We can't modify the
674                     // Parcel.enforceInterface signature, as it's
675                     // pseudo-public, and used via AIDL
676                     // auto-generation...)
677                     set_dalvik_blockguard_policy(env, newPolicy);
678                 }
679                 return;     // everything was correct -> return silently
680             }
681         }
682     }
683 
684     // all error conditions wind up here
685     jniThrowException(env, "java/lang/SecurityException",
686             "Binder invocation to an incorrect interface");
687 }
688 
android_os_Parcel_getGlobalAllocSize(JNIEnv * env,jclass clazz)689 static jlong android_os_Parcel_getGlobalAllocSize(JNIEnv* env, jclass clazz)
690 {
691     return Parcel::getGlobalAllocSize();
692 }
693 
android_os_Parcel_getGlobalAllocCount(JNIEnv * env,jclass clazz)694 static jlong android_os_Parcel_getGlobalAllocCount(JNIEnv* env, jclass clazz)
695 {
696     return Parcel::getGlobalAllocCount();
697 }
698 
android_os_Parcel_getBlobAshmemSize(jlong nativePtr)699 static jlong android_os_Parcel_getBlobAshmemSize(jlong nativePtr)
700 {
701     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
702     if (parcel != NULL) {
703         return parcel->getBlobAshmemSize();
704     }
705     return 0;
706 }
707 
android_os_Parcel_readCallingWorkSourceUid(jlong nativePtr)708 static jint android_os_Parcel_readCallingWorkSourceUid(jlong nativePtr)
709 {
710     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
711     if (parcel != NULL) {
712         return parcel->readCallingWorkSourceUid();
713     }
714     return IPCThreadState::kUnsetWorkSource;
715 }
716 
android_os_Parcel_replaceCallingWorkSourceUid(jlong nativePtr,jint uid)717 static jboolean android_os_Parcel_replaceCallingWorkSourceUid(jlong nativePtr, jint uid)
718 {
719     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
720     if (parcel != NULL) {
721         return parcel->replaceCallingWorkSourceUid(uid);
722     }
723     return false;
724 }
725 
726 // ----------------------------------------------------------------------------
727 
728 static const JNINativeMethod gParcelMethods[] = {
729     // @CriticalNative
730     {"nativeDataSize",            "(J)I", (void*)android_os_Parcel_dataSize},
731     // @CriticalNative
732     {"nativeDataAvail",           "(J)I", (void*)android_os_Parcel_dataAvail},
733     // @CriticalNative
734     {"nativeDataPosition",        "(J)I", (void*)android_os_Parcel_dataPosition},
735     // @CriticalNative
736     {"nativeDataCapacity",        "(J)I", (void*)android_os_Parcel_dataCapacity},
737     // @FastNative
738     {"nativeSetDataSize",         "(JI)J", (void*)android_os_Parcel_setDataSize},
739     // @CriticalNative
740     {"nativeSetDataPosition",     "(JI)V", (void*)android_os_Parcel_setDataPosition},
741     // @FastNative
742     {"nativeSetDataCapacity",     "(JI)V", (void*)android_os_Parcel_setDataCapacity},
743 
744     // @CriticalNative
745     {"nativePushAllowFds",        "(JZ)Z", (void*)android_os_Parcel_pushAllowFds},
746     // @CriticalNative
747     {"nativeRestoreAllowFds",     "(JZ)V", (void*)android_os_Parcel_restoreAllowFds},
748 
749     {"nativeWriteByteArray",      "(J[BII)V", (void*)android_os_Parcel_writeByteArray},
750     {"nativeWriteBlob",           "(J[BII)V", (void*)android_os_Parcel_writeBlob},
751     // @FastNative
752     {"nativeWriteInt",            "(JI)V", (void*)android_os_Parcel_writeInt},
753     // @FastNative
754     {"nativeWriteLong",           "(JJ)V", (void*)android_os_Parcel_writeLong},
755     // @FastNative
756     {"nativeWriteFloat",          "(JF)V", (void*)android_os_Parcel_writeFloat},
757     // @FastNative
758     {"nativeWriteDouble",         "(JD)V", (void*)android_os_Parcel_writeDouble},
759     // @FastNative
760     {"nativeWriteString8",        "(JLjava/lang/String;)V", (void*)android_os_Parcel_writeString8},
761     // @FastNative
762     {"nativeWriteString16",       "(JLjava/lang/String;)V", (void*)android_os_Parcel_writeString16},
763     // @FastNative
764     {"nativeWriteStrongBinder",   "(JLandroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder},
765     // @FastNative
766     {"nativeWriteFileDescriptor", "(JLjava/io/FileDescriptor;)J", (void*)android_os_Parcel_writeFileDescriptor},
767 
768     {"nativeCreateByteArray",     "(J)[B", (void*)android_os_Parcel_createByteArray},
769     {"nativeReadByteArray",       "(J[BI)Z", (void*)android_os_Parcel_readByteArray},
770     {"nativeReadBlob",            "(J)[B", (void*)android_os_Parcel_readBlob},
771     // @CriticalNative
772     {"nativeReadInt",             "(J)I", (void*)android_os_Parcel_readInt},
773     // @CriticalNative
774     {"nativeReadLong",            "(J)J", (void*)android_os_Parcel_readLong},
775     // @CriticalNative
776     {"nativeReadFloat",           "(J)F", (void*)android_os_Parcel_readFloat},
777     // @CriticalNative
778     {"nativeReadDouble",          "(J)D", (void*)android_os_Parcel_readDouble},
779     // @FastNative
780     {"nativeReadString8",         "(J)Ljava/lang/String;", (void*)android_os_Parcel_readString8},
781     // @FastNative
782     {"nativeReadString16",        "(J)Ljava/lang/String;", (void*)android_os_Parcel_readString16},
783     // @FastNative
784     {"nativeReadStrongBinder",    "(J)Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder},
785     // @FastNative
786     {"nativeReadFileDescriptor",  "(J)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_readFileDescriptor},
787 
788     {"nativeCreate",              "()J", (void*)android_os_Parcel_create},
789     {"nativeFreeBuffer",          "(J)J", (void*)android_os_Parcel_freeBuffer},
790     {"nativeDestroy",             "(J)V", (void*)android_os_Parcel_destroy},
791 
792     {"nativeMarshall",            "(J)[B", (void*)android_os_Parcel_marshall},
793     {"nativeUnmarshall",          "(J[BII)J", (void*)android_os_Parcel_unmarshall},
794     {"nativeCompareData",         "(JJ)I", (void*)android_os_Parcel_compareData},
795     {"nativeAppendFrom",          "(JJII)J", (void*)android_os_Parcel_appendFrom},
796     // @CriticalNative
797     {"nativeHasFileDescriptors",  "(J)Z", (void*)android_os_Parcel_hasFileDescriptors},
798     {"nativeWriteInterfaceToken", "(JLjava/lang/String;)V", (void*)android_os_Parcel_writeInterfaceToken},
799     {"nativeEnforceInterface",    "(JLjava/lang/String;)V", (void*)android_os_Parcel_enforceInterface},
800 
801     {"getGlobalAllocSize",        "()J", (void*)android_os_Parcel_getGlobalAllocSize},
802     {"getGlobalAllocCount",       "()J", (void*)android_os_Parcel_getGlobalAllocCount},
803 
804     // @CriticalNative
805     {"nativeGetBlobAshmemSize",       "(J)J", (void*)android_os_Parcel_getBlobAshmemSize},
806 
807     // @CriticalNative
808     {"nativeReadCallingWorkSourceUid", "(J)I", (void*)android_os_Parcel_readCallingWorkSourceUid},
809     // @CriticalNative
810     {"nativeReplaceCallingWorkSourceUid", "(JI)Z", (void*)android_os_Parcel_replaceCallingWorkSourceUid},
811 };
812 
813 const char* const kParcelPathName = "android/os/Parcel";
814 
register_android_os_Parcel(JNIEnv * env)815 int register_android_os_Parcel(JNIEnv* env)
816 {
817     jclass clazz = FindClassOrDie(env, kParcelPathName);
818 
819     gParcelOffsets.clazz = MakeGlobalRefOrDie(env, clazz);
820     gParcelOffsets.mNativePtr = GetFieldIDOrDie(env, clazz, "mNativePtr", "J");
821     gParcelOffsets.obtain = GetStaticMethodIDOrDie(env, clazz, "obtain", "()Landroid/os/Parcel;");
822     gParcelOffsets.recycle = GetMethodIDOrDie(env, clazz, "recycle", "()V");
823 
824     return RegisterMethodsOrDie(env, kParcelPathName, gParcelMethods, NELEM(gParcelMethods));
825 }
826 
827 };
828