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