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