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