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