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