• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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