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/JNIPlatformHelp.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_markSensitive(jlong nativePtr)93 static void android_os_Parcel_markSensitive(jlong nativePtr)
94 {
95 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
96 if (parcel) {
97 parcel->markSensitive();
98 }
99 }
100
android_os_Parcel_markForBinder(JNIEnv * env,jclass clazz,jlong nativePtr,jobject binder)101 static void android_os_Parcel_markForBinder(JNIEnv* env, jclass clazz, jlong nativePtr,
102 jobject binder)
103 {
104 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
105 if (parcel) {
106 parcel->markForBinder(ibinderForJavaObject(env, binder));
107 }
108 }
109
android_os_Parcel_dataSize(jlong nativePtr)110 static jint android_os_Parcel_dataSize(jlong nativePtr)
111 {
112 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
113 return parcel ? parcel->dataSize() : 0;
114 }
115
android_os_Parcel_dataAvail(jlong nativePtr)116 static jint android_os_Parcel_dataAvail(jlong nativePtr)
117 {
118 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
119 return parcel ? parcel->dataAvail() : 0;
120 }
121
android_os_Parcel_dataPosition(jlong nativePtr)122 static jint android_os_Parcel_dataPosition(jlong nativePtr)
123 {
124 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
125 return parcel ? parcel->dataPosition() : 0;
126 }
127
android_os_Parcel_dataCapacity(jlong nativePtr)128 static jint android_os_Parcel_dataCapacity(jlong nativePtr)
129 {
130 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
131 return parcel ? parcel->dataCapacity() : 0;
132 }
133
android_os_Parcel_setDataSize(JNIEnv * env,jclass clazz,jlong nativePtr,jint size)134 static void android_os_Parcel_setDataSize(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->setDataSize(size);
139 if (err != NO_ERROR) {
140 signalExceptionForError(env, clazz, err);
141 }
142 }
143 }
144
android_os_Parcel_setDataPosition(jlong nativePtr,jint pos)145 static void android_os_Parcel_setDataPosition(jlong nativePtr, jint pos)
146 {
147 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
148 if (parcel != NULL) {
149 parcel->setDataPosition(pos);
150 }
151 }
152
android_os_Parcel_setDataCapacity(JNIEnv * env,jclass clazz,jlong nativePtr,jint size)153 static void android_os_Parcel_setDataCapacity(JNIEnv* env, jclass clazz, jlong nativePtr, jint size)
154 {
155 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
156 if (parcel != NULL) {
157 const status_t err = parcel->setDataCapacity(size);
158 if (err != NO_ERROR) {
159 signalExceptionForError(env, clazz, err);
160 }
161 }
162 }
163
android_os_Parcel_pushAllowFds(jlong nativePtr,jboolean allowFds)164 static jboolean android_os_Parcel_pushAllowFds(jlong nativePtr, jboolean allowFds)
165 {
166 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
167 jboolean ret = JNI_TRUE;
168 if (parcel != NULL) {
169 ret = (jboolean)parcel->pushAllowFds(allowFds);
170 }
171 return ret;
172 }
173
android_os_Parcel_restoreAllowFds(jlong nativePtr,jboolean lastValue)174 static void android_os_Parcel_restoreAllowFds(jlong nativePtr, jboolean lastValue)
175 {
176 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
177 if (parcel != NULL) {
178 parcel->restoreAllowFds((bool)lastValue);
179 }
180 }
181
android_os_Parcel_writeByteArray(JNIEnv * env,jclass clazz,jlong nativePtr,jobject data,jint offset,jint length)182 static void android_os_Parcel_writeByteArray(JNIEnv* env, jclass clazz, jlong nativePtr,
183 jobject data, jint offset, jint length)
184 {
185 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
186 if (parcel == NULL) {
187 return;
188 }
189
190 const status_t err = parcel->writeInt32(length);
191 if (err != NO_ERROR) {
192 signalExceptionForError(env, clazz, err);
193 return;
194 }
195
196 void* dest = parcel->writeInplace(length);
197 if (dest == NULL) {
198 signalExceptionForError(env, clazz, NO_MEMORY);
199 return;
200 }
201
202 jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)data, 0);
203 if (ar) {
204 memcpy(dest, ar + offset, length);
205 env->ReleasePrimitiveArrayCritical((jarray)data, ar, 0);
206 }
207 }
208
android_os_Parcel_writeBlob(JNIEnv * env,jclass clazz,jlong nativePtr,jobject data,jint offset,jint length)209 static void android_os_Parcel_writeBlob(JNIEnv* env, jclass clazz, jlong nativePtr, jobject data,
210 jint offset, jint length) {
211 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
212 if (parcel == NULL) {
213 return;
214 }
215
216 if (data == NULL) {
217 const status_t err = parcel->writeInt32(-1);
218 if (err != NO_ERROR) {
219 signalExceptionForError(env, clazz, err);
220 }
221 return;
222 }
223
224 const status_t err = parcel->writeInt32(length);
225 if (err != NO_ERROR) {
226 signalExceptionForError(env, clazz, err);
227 return;
228 }
229
230 android::Parcel::WritableBlob blob;
231 android::status_t err2 = parcel->writeBlob(length, false, &blob);
232 if (err2 != NO_ERROR) {
233 signalExceptionForError(env, clazz, err2);
234 return;
235 }
236
237 jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)data, 0);
238 if (ar == NULL) {
239 memset(blob.data(), 0, length);
240 } else {
241 memcpy(blob.data(), ar + offset, length);
242 env->ReleasePrimitiveArrayCritical((jarray)data, ar, 0);
243 }
244
245 blob.release();
246 }
247
android_os_Parcel_writeInt(jlong nativePtr,jint val)248 static int android_os_Parcel_writeInt(jlong nativePtr, jint val) {
249 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
250 return (parcel != NULL) ? parcel->writeInt32(val) : OK;
251 }
252
android_os_Parcel_writeLong(jlong nativePtr,jlong val)253 static int android_os_Parcel_writeLong(jlong nativePtr, jlong val) {
254 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
255 return (parcel != NULL) ? parcel->writeInt64(val) : OK;
256 }
257
android_os_Parcel_writeFloat(jlong nativePtr,jfloat val)258 static int android_os_Parcel_writeFloat(jlong nativePtr, jfloat val) {
259 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
260 return (parcel != NULL) ? parcel->writeFloat(val) : OK;
261 }
262
android_os_Parcel_writeDouble(jlong nativePtr,jdouble val)263 static int android_os_Parcel_writeDouble(jlong nativePtr, jdouble val) {
264 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
265 return (parcel != NULL) ? parcel->writeDouble(val) : OK;
266 }
267
android_os_Parcel_nativeSignalExceptionForError(JNIEnv * env,jclass clazz,jint err)268 static void android_os_Parcel_nativeSignalExceptionForError(JNIEnv* env, jclass clazz, jint err) {
269 signalExceptionForError(env, clazz, err);
270 }
271
android_os_Parcel_writeString8(JNIEnv * env,jclass clazz,jlong nativePtr,jstring val)272 static void android_os_Parcel_writeString8(JNIEnv *env, jclass clazz, jlong nativePtr,
273 jstring val) {
274 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
275 if (parcel != nullptr) {
276 status_t err = NO_ERROR;
277 if (val) {
278 // NOTE: Keep this logic in sync with Parcel.cpp
279 const size_t len = env->GetStringLength(val);
280 const size_t allocLen = env->GetStringUTFLength(val);
281 err = parcel->writeInt32(allocLen);
282 char *data = reinterpret_cast<char*>(parcel->writeInplace(allocLen + sizeof(char)));
283 if (data != nullptr) {
284 env->GetStringUTFRegion(val, 0, len, data);
285 *(data + allocLen) = 0;
286 } else {
287 err = NO_MEMORY;
288 }
289 } else {
290 err = parcel->writeString8(nullptr, 0);
291 }
292 if (err != NO_ERROR) {
293 signalExceptionForError(env, clazz, err);
294 }
295 }
296 }
297
android_os_Parcel_writeString16(JNIEnv * env,jclass clazz,jlong nativePtr,jstring val)298 static void android_os_Parcel_writeString16(JNIEnv *env, jclass clazz, jlong nativePtr,
299 jstring val) {
300 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
301 if (parcel != nullptr) {
302 status_t err = NO_ERROR;
303 if (val) {
304 // NOTE: Keep this logic in sync with Parcel.cpp
305 const size_t len = env->GetStringLength(val);
306 const size_t allocLen = len * sizeof(char16_t);
307 err = parcel->writeInt32(len);
308 char *data = reinterpret_cast<char*>(parcel->writeInplace(allocLen + sizeof(char16_t)));
309 if (data != nullptr) {
310 env->GetStringRegion(val, 0, len, reinterpret_cast<jchar*>(data));
311 *reinterpret_cast<char16_t*>(data + allocLen) = 0;
312 } else {
313 err = NO_MEMORY;
314 }
315 } else {
316 err = parcel->writeString16(nullptr, 0);
317 }
318 if (err != NO_ERROR) {
319 signalExceptionForError(env, clazz, err);
320 }
321 }
322 }
323
android_os_Parcel_writeStrongBinder(JNIEnv * env,jclass clazz,jlong nativePtr,jobject object)324 static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
325 {
326 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
327 if (parcel != NULL) {
328 const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
329 if (err != NO_ERROR) {
330 signalExceptionForError(env, clazz, err);
331 }
332 }
333 }
334
android_os_Parcel_writeFileDescriptor(JNIEnv * env,jclass clazz,jlong nativePtr,jobject object)335 static void android_os_Parcel_writeFileDescriptor(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
336 {
337 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
338 if (parcel != NULL) {
339 const status_t err =
340 parcel->writeDupFileDescriptor(jniGetFDFromFileDescriptor(env, object));
341 if (err != NO_ERROR) {
342 signalExceptionForError(env, clazz, err);
343 }
344 }
345 }
346
android_os_Parcel_createByteArray(JNIEnv * env,jclass clazz,jlong nativePtr)347 static jbyteArray android_os_Parcel_createByteArray(JNIEnv* env, jclass clazz, jlong nativePtr)
348 {
349 jbyteArray ret = NULL;
350
351 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
352 if (parcel != NULL) {
353 int32_t len = parcel->readInt32();
354
355 // Validate the stored length against the true data size
356 if (len >= 0 && len <= (int32_t)parcel->dataAvail()) {
357 ret = env->NewByteArray(len);
358
359 if (ret != NULL) {
360 jbyte* a2 = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
361 if (a2) {
362 const void* data = parcel->readInplace(len);
363 if (data) {
364 memcpy(a2, data, len);
365 }
366 env->ReleasePrimitiveArrayCritical(ret, a2, 0);
367 if (!data) {
368 ret = NULL;
369 }
370 }
371 }
372 }
373 }
374
375 return ret;
376 }
377
android_os_Parcel_readByteArray(JNIEnv * env,jclass clazz,jlong nativePtr,jobject dest,jint destLen)378 static jboolean android_os_Parcel_readByteArray(JNIEnv* env, jclass clazz, jlong nativePtr,
379 jobject dest, jint destLen)
380 {
381 jboolean ret = JNI_FALSE;
382 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
383 if (parcel == NULL) {
384 return ret;
385 }
386
387 int32_t len = parcel->readInt32();
388 if (len >= 0 && len <= (int32_t)parcel->dataAvail() && len == destLen) {
389 jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)dest, 0);
390 if (ar) {
391 const void* data = parcel->readInplace(len);
392 if (data) {
393 memcpy(ar, data, len);
394 ret = JNI_TRUE;
395 } else {
396 ret = JNI_FALSE;
397 }
398
399 env->ReleasePrimitiveArrayCritical((jarray)dest, ar, 0);
400 }
401 }
402 return ret;
403 }
404
android_os_Parcel_readBlob(JNIEnv * env,jclass clazz,jlong nativePtr)405 static jbyteArray android_os_Parcel_readBlob(JNIEnv* env, jclass clazz, jlong nativePtr)
406 {
407 jbyteArray ret = NULL;
408
409 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
410 if (parcel != NULL) {
411 int32_t len = parcel->readInt32();
412 if (len >= 0) {
413 android::Parcel::ReadableBlob blob;
414 android::status_t err = parcel->readBlob(len, &blob);
415 if (err != NO_ERROR) {
416 signalExceptionForError(env, clazz, err);
417 return NULL;
418 }
419
420 ret = env->NewByteArray(len);
421 if (ret != NULL) {
422 jbyte* a2 = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
423 if (a2) {
424 memcpy(a2, blob.data(), len);
425 env->ReleasePrimitiveArrayCritical(ret, a2, 0);
426 }
427 }
428 blob.release();
429 }
430 }
431
432 return ret;
433 }
434
android_os_Parcel_readInt(jlong nativePtr)435 static jint android_os_Parcel_readInt(jlong nativePtr)
436 {
437 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
438 if (parcel != NULL) {
439 return parcel->readInt32();
440 }
441 return 0;
442 }
443
android_os_Parcel_readLong(jlong nativePtr)444 static jlong android_os_Parcel_readLong(jlong nativePtr)
445 {
446 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
447 if (parcel != NULL) {
448 return parcel->readInt64();
449 }
450 return 0;
451 }
452
android_os_Parcel_readFloat(jlong nativePtr)453 static jfloat android_os_Parcel_readFloat(jlong nativePtr)
454 {
455 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
456 if (parcel != NULL) {
457 return parcel->readFloat();
458 }
459 return 0;
460 }
461
android_os_Parcel_readDouble(jlong nativePtr)462 static jdouble android_os_Parcel_readDouble(jlong nativePtr)
463 {
464 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
465 if (parcel != NULL) {
466 return parcel->readDouble();
467 }
468 return 0;
469 }
470
android_os_Parcel_readString8(JNIEnv * env,jclass clazz,jlong nativePtr)471 static jstring android_os_Parcel_readString8(JNIEnv* env, jclass clazz, jlong nativePtr)
472 {
473 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
474 if (parcel != NULL) {
475 size_t len;
476 const char* str = parcel->readString8Inplace(&len);
477 if (str) {
478 return env->NewStringUTF(str);
479 }
480 return NULL;
481 }
482 return NULL;
483 }
484
android_os_Parcel_readString16(JNIEnv * env,jclass clazz,jlong nativePtr)485 static jstring android_os_Parcel_readString16(JNIEnv* env, jclass clazz, jlong nativePtr)
486 {
487 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
488 if (parcel != NULL) {
489 size_t len;
490 const char16_t* str = parcel->readString16Inplace(&len);
491 if (str) {
492 return env->NewString(reinterpret_cast<const jchar*>(str), len);
493 }
494 return NULL;
495 }
496 return NULL;
497 }
498
android_os_Parcel_readStrongBinder(JNIEnv * env,jclass clazz,jlong nativePtr)499 static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)
500 {
501 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
502 if (parcel != NULL) {
503 return javaObjectForIBinder(env, parcel->readStrongBinder());
504 }
505 return NULL;
506 }
507
android_os_Parcel_readFileDescriptor(JNIEnv * env,jclass clazz,jlong nativePtr)508 static jobject android_os_Parcel_readFileDescriptor(JNIEnv* env, jclass clazz, jlong nativePtr)
509 {
510 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
511 if (parcel != NULL) {
512 int fd = parcel->readFileDescriptor();
513 if (fd < 0) return NULL;
514 fd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
515 if (fd < 0) return NULL;
516 jobject jifd = jniCreateFileDescriptor(env, fd);
517 if (jifd == NULL) {
518 close(fd);
519 }
520 return jifd;
521 }
522 return NULL;
523 }
524
android_os_Parcel_create(JNIEnv * env,jclass clazz)525 static jlong android_os_Parcel_create(JNIEnv* env, jclass clazz)
526 {
527 Parcel* parcel = new Parcel();
528 return reinterpret_cast<jlong>(parcel);
529 }
530
android_os_Parcel_freeBuffer(JNIEnv * env,jclass clazz,jlong nativePtr)531 static void android_os_Parcel_freeBuffer(JNIEnv* env, jclass clazz, jlong nativePtr)
532 {
533 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
534 if (parcel != NULL) {
535 parcel->freeData();
536 }
537 }
538
android_os_Parcel_destroy(JNIEnv * env,jclass clazz,jlong nativePtr)539 static void android_os_Parcel_destroy(JNIEnv* env, jclass clazz, jlong nativePtr)
540 {
541 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
542 delete parcel;
543 }
544
android_os_Parcel_marshall(JNIEnv * env,jclass clazz,jlong nativePtr)545 static jbyteArray android_os_Parcel_marshall(JNIEnv* env, jclass clazz, jlong nativePtr)
546 {
547 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
548 if (parcel == NULL) {
549 return NULL;
550 }
551
552 // do not marshall if there are binder objects in the parcel
553 if (parcel->objectsCount())
554 {
555 jniThrowException(env, "java/lang/RuntimeException", "Tried to marshall a Parcel that contained Binder objects.");
556 return NULL;
557 }
558
559 jbyteArray ret = env->NewByteArray(parcel->dataSize());
560
561 if (ret != NULL)
562 {
563 jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
564 if (array != NULL)
565 {
566 memcpy(array, parcel->data(), parcel->dataSize());
567 env->ReleasePrimitiveArrayCritical(ret, array, 0);
568 }
569 }
570
571 return ret;
572 }
573
android_os_Parcel_unmarshall(JNIEnv * env,jclass clazz,jlong nativePtr,jbyteArray data,jint offset,jint length)574 static void android_os_Parcel_unmarshall(JNIEnv* env, jclass clazz, jlong nativePtr,
575 jbyteArray data, jint offset, jint length)
576 {
577 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
578 if (parcel == NULL || length < 0) {
579 return;
580 }
581
582 jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(data, 0);
583 if (array)
584 {
585 parcel->setDataSize(length);
586 parcel->setDataPosition(0);
587
588 void* raw = parcel->writeInplace(length);
589 memcpy(raw, (array + offset), length);
590
591 env->ReleasePrimitiveArrayCritical(data, array, 0);
592 }
593 }
594
android_os_Parcel_compareData(JNIEnv * env,jclass clazz,jlong thisNativePtr,jlong otherNativePtr)595 static jint android_os_Parcel_compareData(JNIEnv* env, jclass clazz, jlong thisNativePtr,
596 jlong otherNativePtr)
597 {
598 Parcel* thisParcel = reinterpret_cast<Parcel*>(thisNativePtr);
599 LOG_ALWAYS_FATAL_IF(thisParcel == nullptr, "Should not be null");
600
601 Parcel* otherParcel = reinterpret_cast<Parcel*>(otherNativePtr);
602 LOG_ALWAYS_FATAL_IF(otherParcel == nullptr, "Should not be null");
603
604 return thisParcel->compareData(*otherParcel);
605 }
606
android_os_Parcel_compareDataInRange(JNIEnv * env,jclass clazz,jlong thisNativePtr,jint thisOffset,jlong otherNativePtr,jint otherOffset,jint length)607 static jboolean android_os_Parcel_compareDataInRange(JNIEnv* env, jclass clazz, jlong thisNativePtr,
608 jint thisOffset, jlong otherNativePtr,
609 jint otherOffset, jint length) {
610 Parcel* thisParcel = reinterpret_cast<Parcel*>(thisNativePtr);
611 LOG_ALWAYS_FATAL_IF(thisParcel == nullptr, "Should not be null");
612
613 Parcel* otherParcel = reinterpret_cast<Parcel*>(otherNativePtr);
614 LOG_ALWAYS_FATAL_IF(otherParcel == nullptr, "Should not be null");
615
616 int result;
617 status_t err =
618 thisParcel->compareDataInRange(thisOffset, *otherParcel, otherOffset, length, &result);
619 if (err != NO_ERROR) {
620 signalExceptionForError(env, clazz, err);
621 return JNI_FALSE;
622 }
623 return (result == 0) ? JNI_TRUE : JNI_FALSE;
624 }
625
android_os_Parcel_appendFrom(JNIEnv * env,jclass clazz,jlong thisNativePtr,jlong otherNativePtr,jint offset,jint length)626 static void android_os_Parcel_appendFrom(JNIEnv* env, jclass clazz, jlong thisNativePtr,
627 jlong otherNativePtr, jint offset, jint length)
628 {
629 Parcel* thisParcel = reinterpret_cast<Parcel*>(thisNativePtr);
630 if (thisParcel == NULL) {
631 return;
632 }
633 Parcel* otherParcel = reinterpret_cast<Parcel*>(otherNativePtr);
634 if (otherParcel == NULL) {
635 return;
636 }
637
638 status_t err = thisParcel->appendFrom(otherParcel, offset, length);
639 if (err != NO_ERROR) {
640 signalExceptionForError(env, clazz, err);
641 }
642 return;
643 }
644
android_os_Parcel_hasFileDescriptors(jlong nativePtr)645 static jboolean android_os_Parcel_hasFileDescriptors(jlong nativePtr)
646 {
647 jboolean ret = JNI_FALSE;
648 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
649 if (parcel != NULL) {
650 if (parcel->hasFileDescriptors()) {
651 ret = JNI_TRUE;
652 }
653 }
654 return ret;
655 }
656
android_os_Parcel_hasFileDescriptorsInRange(JNIEnv * env,jclass clazz,jlong nativePtr,jint offset,jint length)657 static jboolean android_os_Parcel_hasFileDescriptorsInRange(JNIEnv* env, jclass clazz,
658 jlong nativePtr, jint offset,
659 jint length) {
660 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
661 if (parcel != NULL) {
662 bool result;
663 status_t err = parcel->hasFileDescriptorsInRange(offset, length, &result);
664 if (err != NO_ERROR) {
665 signalExceptionForError(env, clazz, err);
666 return JNI_FALSE;
667 }
668 return result ? JNI_TRUE : JNI_FALSE;
669 }
670 return JNI_FALSE;
671 }
672
673 // String tries to allocate itself on the stack, within a known size, but will
674 // make a heap allocation if not.
675 template <size_t StackReserve>
676 class StackString {
677 public:
StackString(JNIEnv * env,jstring str)678 StackString(JNIEnv* env, jstring str) : mEnv(env), mJStr(str) {
679 LOG_ALWAYS_FATAL_IF(str == nullptr);
680 mSize = env->GetStringLength(str);
681 if (mSize > StackReserve) {
682 mStr = new jchar[mSize];
683 } else {
684 mStr = &mBuffer[0];
685 }
686 mEnv->GetStringRegion(str, 0, mSize, mStr);
687 }
~StackString()688 ~StackString() {
689 if (mStr != &mBuffer[0]) {
690 delete[] mStr;
691 }
692 }
str()693 const jchar* str() { return mStr; }
size()694 jsize size() { return mSize; }
695
696 private:
697 JNIEnv* mEnv;
698 jstring mJStr;
699
700 jchar mBuffer[StackReserve];
701 // pointer to &mBuffer[0] if string fits in mBuffer, otherwise owned
702 jchar* mStr;
703 jsize mSize;
704 };
705
706 // This size is chosen to be longer than most interface descriptors.
707 // Ones longer than this will be allocated on the heap.
708 typedef StackString<64> InterfaceDescriptorString;
709
android_os_Parcel_writeInterfaceToken(JNIEnv * env,jclass clazz,jlong nativePtr,jstring name)710 static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jclass clazz, jlong nativePtr,
711 jstring name)
712 {
713 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
714 if (parcel != nullptr) {
715 InterfaceDescriptorString descriptor(env, name);
716 parcel->writeInterfaceToken(reinterpret_cast<const char16_t*>(descriptor.str()),
717 descriptor.size());
718 }
719 }
720
android_os_Parcel_enforceInterface(JNIEnv * env,jclass clazz,jlong nativePtr,jstring name)721 static void android_os_Parcel_enforceInterface(JNIEnv* env, jclass clazz, jlong nativePtr, jstring name)
722 {
723 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
724 if (parcel != nullptr) {
725 InterfaceDescriptorString descriptor(env, name);
726 IPCThreadState* threadState = IPCThreadState::self();
727 const int32_t oldPolicy = threadState->getStrictModePolicy();
728 const bool isValid =
729 parcel->enforceInterface(reinterpret_cast<const char16_t*>(descriptor.str()),
730 descriptor.size(), threadState);
731 if (isValid) {
732 const int32_t newPolicy = threadState->getStrictModePolicy();
733 if (oldPolicy != newPolicy) {
734 // Need to keep the Java-level thread-local strict
735 // mode policy in sync for the libcore
736 // enforcements, which involves an upcall back
737 // into Java. (We can't modify the
738 // Parcel.enforceInterface signature, as it's
739 // pseudo-public, and used via AIDL
740 // auto-generation...)
741 set_dalvik_blockguard_policy(env, newPolicy);
742 }
743 return; // everything was correct -> return silently
744 }
745 }
746
747 // all error conditions wind up here
748 jniThrowException(env, "java/lang/SecurityException",
749 "Binder invocation to an incorrect interface");
750 }
751
android_os_Parcel_getGlobalAllocSize(JNIEnv * env,jclass clazz)752 static jlong android_os_Parcel_getGlobalAllocSize(JNIEnv* env, jclass clazz)
753 {
754 return Parcel::getGlobalAllocSize();
755 }
756
android_os_Parcel_getGlobalAllocCount(JNIEnv * env,jclass clazz)757 static jlong android_os_Parcel_getGlobalAllocCount(JNIEnv* env, jclass clazz)
758 {
759 return Parcel::getGlobalAllocCount();
760 }
761
android_os_Parcel_getOpenAshmemSize(jlong nativePtr)762 static jlong android_os_Parcel_getOpenAshmemSize(jlong nativePtr)
763 {
764 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
765 if (parcel != NULL) {
766 return parcel->getOpenAshmemSize();
767 }
768 return 0;
769 }
770
android_os_Parcel_readCallingWorkSourceUid(jlong nativePtr)771 static jint android_os_Parcel_readCallingWorkSourceUid(jlong nativePtr)
772 {
773 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
774 if (parcel != NULL) {
775 return parcel->readCallingWorkSourceUid();
776 }
777 return IPCThreadState::kUnsetWorkSource;
778 }
779
android_os_Parcel_replaceCallingWorkSourceUid(jlong nativePtr,jint uid)780 static jboolean android_os_Parcel_replaceCallingWorkSourceUid(jlong nativePtr, jint uid)
781 {
782 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
783 if (parcel != NULL) {
784 return parcel->replaceCallingWorkSourceUid(uid);
785 }
786 return false;
787 }
788
789 // ----------------------------------------------------------------------------
790
791 static const JNINativeMethod gParcelMethods[] = {
792 // @CriticalNative
793 {"nativeMarkSensitive", "(J)V", (void*)android_os_Parcel_markSensitive},
794 // @FastNative
795 {"nativeMarkForBinder", "(JLandroid/os/IBinder;)V", (void*)android_os_Parcel_markForBinder},
796 // @CriticalNative
797 {"nativeDataSize", "(J)I", (void*)android_os_Parcel_dataSize},
798 // @CriticalNative
799 {"nativeDataAvail", "(J)I", (void*)android_os_Parcel_dataAvail},
800 // @CriticalNative
801 {"nativeDataPosition", "(J)I", (void*)android_os_Parcel_dataPosition},
802 // @CriticalNative
803 {"nativeDataCapacity", "(J)I", (void*)android_os_Parcel_dataCapacity},
804 // @FastNative
805 {"nativeSetDataSize", "(JI)V", (void*)android_os_Parcel_setDataSize},
806 // @CriticalNative
807 {"nativeSetDataPosition", "(JI)V", (void*)android_os_Parcel_setDataPosition},
808 // @FastNative
809 {"nativeSetDataCapacity", "(JI)V", (void*)android_os_Parcel_setDataCapacity},
810
811 // @CriticalNative
812 {"nativePushAllowFds", "(JZ)Z", (void*)android_os_Parcel_pushAllowFds},
813 // @CriticalNative
814 {"nativeRestoreAllowFds", "(JZ)V", (void*)android_os_Parcel_restoreAllowFds},
815
816 {"nativeWriteByteArray", "(J[BII)V", (void*)android_os_Parcel_writeByteArray},
817 {"nativeWriteBlob", "(J[BII)V", (void*)android_os_Parcel_writeBlob},
818 // @CriticalNative
819 {"nativeWriteInt", "(JI)I", (void*)android_os_Parcel_writeInt},
820 // @CriticalNative
821 {"nativeWriteLong", "(JJ)I", (void*)android_os_Parcel_writeLong},
822 // @CriticalNative
823 {"nativeWriteFloat", "(JF)I", (void*)android_os_Parcel_writeFloat},
824 // @CriticalNative
825 {"nativeWriteDouble", "(JD)I", (void*)android_os_Parcel_writeDouble},
826 {"nativeSignalExceptionForError", "(I)V", (void*)android_os_Parcel_nativeSignalExceptionForError},
827 // @FastNative
828 {"nativeWriteString8", "(JLjava/lang/String;)V", (void*)android_os_Parcel_writeString8},
829 // @FastNative
830 {"nativeWriteString16", "(JLjava/lang/String;)V", (void*)android_os_Parcel_writeString16},
831 // @FastNative
832 {"nativeWriteStrongBinder", "(JLandroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder},
833 // @FastNative
834 {"nativeWriteFileDescriptor", "(JLjava/io/FileDescriptor;)V", (void*)android_os_Parcel_writeFileDescriptor},
835
836 {"nativeCreateByteArray", "(J)[B", (void*)android_os_Parcel_createByteArray},
837 {"nativeReadByteArray", "(J[BI)Z", (void*)android_os_Parcel_readByteArray},
838 {"nativeReadBlob", "(J)[B", (void*)android_os_Parcel_readBlob},
839 // @CriticalNative
840 {"nativeReadInt", "(J)I", (void*)android_os_Parcel_readInt},
841 // @CriticalNative
842 {"nativeReadLong", "(J)J", (void*)android_os_Parcel_readLong},
843 // @CriticalNative
844 {"nativeReadFloat", "(J)F", (void*)android_os_Parcel_readFloat},
845 // @CriticalNative
846 {"nativeReadDouble", "(J)D", (void*)android_os_Parcel_readDouble},
847 // @FastNative
848 {"nativeReadString8", "(J)Ljava/lang/String;", (void*)android_os_Parcel_readString8},
849 // @FastNative
850 {"nativeReadString16", "(J)Ljava/lang/String;", (void*)android_os_Parcel_readString16},
851 // @FastNative
852 {"nativeReadStrongBinder", "(J)Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder},
853 // @FastNative
854 {"nativeReadFileDescriptor", "(J)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_readFileDescriptor},
855
856 {"nativeCreate", "()J", (void*)android_os_Parcel_create},
857 {"nativeFreeBuffer", "(J)V", (void*)android_os_Parcel_freeBuffer},
858 {"nativeDestroy", "(J)V", (void*)android_os_Parcel_destroy},
859
860 {"nativeMarshall", "(J)[B", (void*)android_os_Parcel_marshall},
861 {"nativeUnmarshall", "(J[BII)V", (void*)android_os_Parcel_unmarshall},
862 {"nativeCompareData", "(JJ)I", (void*)android_os_Parcel_compareData},
863 {"nativeCompareDataInRange", "(JIJII)Z", (void*)android_os_Parcel_compareDataInRange},
864 {"nativeAppendFrom", "(JJII)V", (void*)android_os_Parcel_appendFrom},
865 // @CriticalNative
866 {"nativeHasFileDescriptors", "(J)Z", (void*)android_os_Parcel_hasFileDescriptors},
867 {"nativeHasFileDescriptorsInRange", "(JII)Z", (void*)android_os_Parcel_hasFileDescriptorsInRange},
868 {"nativeWriteInterfaceToken", "(JLjava/lang/String;)V", (void*)android_os_Parcel_writeInterfaceToken},
869 {"nativeEnforceInterface", "(JLjava/lang/String;)V", (void*)android_os_Parcel_enforceInterface},
870
871 {"getGlobalAllocSize", "()J", (void*)android_os_Parcel_getGlobalAllocSize},
872 {"getGlobalAllocCount", "()J", (void*)android_os_Parcel_getGlobalAllocCount},
873
874 // @CriticalNative
875 {"nativeGetOpenAshmemSize", "(J)J", (void*)android_os_Parcel_getOpenAshmemSize},
876
877 // @CriticalNative
878 {"nativeReadCallingWorkSourceUid", "(J)I", (void*)android_os_Parcel_readCallingWorkSourceUid},
879 // @CriticalNative
880 {"nativeReplaceCallingWorkSourceUid", "(JI)Z", (void*)android_os_Parcel_replaceCallingWorkSourceUid},
881 };
882
883 const char* const kParcelPathName = "android/os/Parcel";
884
register_android_os_Parcel(JNIEnv * env)885 int register_android_os_Parcel(JNIEnv* env)
886 {
887 jclass clazz = FindClassOrDie(env, kParcelPathName);
888
889 gParcelOffsets.clazz = MakeGlobalRefOrDie(env, clazz);
890 gParcelOffsets.mNativePtr = GetFieldIDOrDie(env, clazz, "mNativePtr", "J");
891 gParcelOffsets.obtain = GetStaticMethodIDOrDie(env, clazz, "obtain", "()Landroid/os/Parcel;");
892 gParcelOffsets.recycle = GetMethodIDOrDie(env, clazz, "recycle", "()V");
893
894 return RegisterMethodsOrDie(env, kParcelPathName, gParcelMethods, NELEM(gParcelMethods));
895 }
896
897 };
898