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