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