blob: 858ec79addcc6653918dff136b7b9a8de8577fa1 [file] [log] [blame]
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -08001/*
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
60namespace android {
61
62static struct parcel_offsets_t
63{
Insun Kang89020972012-05-01 14:13:19 +090064 jclass clazz;
Jeff Sharkey047238c2012-03-07 16:51:38 -080065 jfieldID mNativePtr;
Insun Kang89020972012-05-01 14:13:19 +090066 jmethodID obtain;
67 jmethodID recycle;
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -080068} gParcelOffsets;
69
70Parcel* parcelForJavaObject(JNIEnv* env, jobject obj)
71{
72 if (obj) {
Jeff Sharkey047238c2012-03-07 16:51:38 -080073 Parcel* p = (Parcel*)env->GetIntField(obj, gParcelOffsets.mNativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -080074 if (p != NULL) {
75 return p;
76 }
77 jniThrowException(env, "java/lang/IllegalStateException", "Parcel has been finalized!");
78 }
79 return NULL;
80}
81
Insun Kang89020972012-05-01 14:13:19 +090082jobject createJavaParcelObject(JNIEnv* env)
83{
84 return env->CallStaticObjectMethod(gParcelOffsets.clazz, gParcelOffsets.obtain);
85}
86
87void recycleJavaParcelObject(JNIEnv* env, jobject parcelObj)
88{
89 env->CallVoidMethod(parcelObj, gParcelOffsets.recycle);
90}
91
Jeff Sharkey047238c2012-03-07 16:51:38 -080092static jint android_os_Parcel_dataSize(JNIEnv* env, jclass clazz, jint nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -080093{
Jeff Sharkey047238c2012-03-07 16:51:38 -080094 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -080095 return parcel ? parcel->dataSize() : 0;
96}
97
Jeff Sharkey047238c2012-03-07 16:51:38 -080098static jint android_os_Parcel_dataAvail(JNIEnv* env, jclass clazz, jint nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -080099{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800100 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800101 return parcel ? parcel->dataAvail() : 0;
102}
103
Jeff Sharkey047238c2012-03-07 16:51:38 -0800104static jint android_os_Parcel_dataPosition(JNIEnv* env, jclass clazz, jint nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800105{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800106 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800107 return parcel ? parcel->dataPosition() : 0;
108}
109
Jeff Sharkey047238c2012-03-07 16:51:38 -0800110static jint android_os_Parcel_dataCapacity(JNIEnv* env, jclass clazz, jint nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800111{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800112 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800113 return parcel ? parcel->dataCapacity() : 0;
114}
115
Jeff Sharkey047238c2012-03-07 16:51:38 -0800116static void android_os_Parcel_setDataSize(JNIEnv* env, jclass clazz, jint nativePtr, jint size)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800117{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800118 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800119 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
Jeff Sharkey047238c2012-03-07 16:51:38 -0800127static void android_os_Parcel_setDataPosition(JNIEnv* env, jclass clazz, jint nativePtr, jint pos)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800128{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800129 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800130 if (parcel != NULL) {
131 parcel->setDataPosition(pos);
132 }
133}
134
Jeff Sharkey047238c2012-03-07 16:51:38 -0800135static void android_os_Parcel_setDataCapacity(JNIEnv* env, jclass clazz, jint nativePtr, jint size)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800136{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800137 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800138 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
Jeff Sharkey047238c2012-03-07 16:51:38 -0800146static jboolean android_os_Parcel_pushAllowFds(JNIEnv* env, jclass clazz, jint nativePtr, jboolean allowFds)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800147{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800148 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800149 jboolean ret = JNI_TRUE;
150 if (parcel != NULL) {
151 ret = (jboolean)parcel->pushAllowFds(allowFds);
152 }
153 return ret;
154}
155
Jeff Sharkey047238c2012-03-07 16:51:38 -0800156static void android_os_Parcel_restoreAllowFds(JNIEnv* env, jclass clazz, jint nativePtr, jboolean lastValue)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800157{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800158 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800159 if (parcel != NULL) {
160 parcel->restoreAllowFds((bool)lastValue);
161 }
162}
163
Jeff Sharkey047238c2012-03-07 16:51:38 -0800164static void android_os_Parcel_writeNative(JNIEnv* env, jclass clazz, jint nativePtr, jobject data,
165 jint offset, jint length)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800166{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800167 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800168 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
Jeff Sharkey047238c2012-03-07 16:51:38 -0800191static 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);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800196 }
197}
198
Jeff Sharkey047238c2012-03-07 16:51:38 -0800199static void android_os_Parcel_writeLong(JNIEnv* env, jclass clazz, jint nativePtr, jlong val)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800200{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800201 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800202 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
Jeff Sharkey047238c2012-03-07 16:51:38 -0800210static void android_os_Parcel_writeFloat(JNIEnv* env, jclass clazz, jint nativePtr, jfloat val)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800211{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800212 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800213 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
Jeff Sharkey047238c2012-03-07 16:51:38 -0800221static void android_os_Parcel_writeDouble(JNIEnv* env, jclass clazz, jint nativePtr, jdouble val)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800222{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800223 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800224 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
Jeff Sharkey047238c2012-03-07 16:51:38 -0800232static void android_os_Parcel_writeString(JNIEnv* env, jclass clazz, jint nativePtr, jstring val)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800233{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800234 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800235 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
Jeff Sharkey047238c2012-03-07 16:51:38 -0800252static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jint nativePtr, jobject object)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800253{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800254 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800255 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
Jeff Sharkey047238c2012-03-07 16:51:38 -0800263static void android_os_Parcel_writeFileDescriptor(JNIEnv* env, jclass clazz, jint nativePtr, jobject object)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800264{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800265 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800266 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
Jeff Sharkey047238c2012-03-07 16:51:38 -0800275static jbyteArray android_os_Parcel_createByteArray(JNIEnv* env, jclass clazz, jint nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800276{
277 jbyteArray ret = NULL;
278
Jeff Sharkey047238c2012-03-07 16:51:38 -0800279 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800280 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
Jeff Sharkey047238c2012-03-07 16:51:38 -0800301static jint android_os_Parcel_readInt(JNIEnv* env, jclass clazz, jint nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800302{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800303 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800304 if (parcel != NULL) {
305 return parcel->readInt32();
306 }
307 return 0;
308}
309
Jeff Sharkey047238c2012-03-07 16:51:38 -0800310static jlong android_os_Parcel_readLong(JNIEnv* env, jclass clazz, jint nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800311{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800312 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800313 if (parcel != NULL) {
314 return parcel->readInt64();
315 }
316 return 0;
317}
318
Jeff Sharkey047238c2012-03-07 16:51:38 -0800319static jfloat android_os_Parcel_readFloat(JNIEnv* env, jclass clazz, jint nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800320{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800321 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800322 if (parcel != NULL) {
323 return parcel->readFloat();
324 }
325 return 0;
326}
327
Jeff Sharkey047238c2012-03-07 16:51:38 -0800328static jdouble android_os_Parcel_readDouble(JNIEnv* env, jclass clazz, jint nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800329{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800330 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800331 if (parcel != NULL) {
332 return parcel->readDouble();
333 }
334 return 0;
335}
336
Jeff Sharkey047238c2012-03-07 16:51:38 -0800337static jstring android_os_Parcel_readString(JNIEnv* env, jclass clazz, jint nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800338{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800339 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800340 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
Jeff Sharkey047238c2012-03-07 16:51:38 -0800351static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jint nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800352{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800353 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800354 if (parcel != NULL) {
355 return javaObjectForIBinder(env, parcel->readStrongBinder());
356 }
357 return NULL;
358}
359
Jeff Sharkey047238c2012-03-07 16:51:38 -0800360static jobject android_os_Parcel_readFileDescriptor(JNIEnv* env, jclass clazz, jint nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800361{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800362 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800363 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
Jeff Sharkey047238c2012-03-07 16:51:38 -0800373static jobject android_os_Parcel_openFileDescriptor(JNIEnv* env, jclass clazz,
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800374 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
Jeff Sharkey047238c2012-03-07 16:51:38 -0800422static jobject android_os_Parcel_dupFileDescriptor(JNIEnv* env, jclass clazz, jobject orig)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800423{
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
Jeff Sharkey047238c2012-03-07 16:51:38 -0800446static void android_os_Parcel_closeFileDescriptor(JNIEnv* env, jclass clazz, jobject object)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800447{
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
Jeff Sharkey047238c2012-03-07 16:51:38 -0800460static void android_os_Parcel_clearFileDescriptor(JNIEnv* env, jclass clazz, jobject object)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800461{
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
Jeff Sharkey047238c2012-03-07 16:51:38 -0800472static jint android_os_Parcel_create(JNIEnv* env, jclass clazz)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800473{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800474 Parcel* parcel = new Parcel();
475 return reinterpret_cast<jint>(parcel);
476}
477
478static 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();
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800483 }
484}
485
Jeff Sharkey047238c2012-03-07 16:51:38 -0800486static void android_os_Parcel_destroy(JNIEnv* env, jclass clazz, jint nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800487{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800488 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
489 delete parcel;
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800490}
491
Jeff Sharkey047238c2012-03-07 16:51:38 -0800492static jbyteArray android_os_Parcel_marshall(JNIEnv* env, jclass clazz, jint nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800493{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800494 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800495 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
Jeff Sharkey047238c2012-03-07 16:51:38 -0800521static void android_os_Parcel_unmarshall(JNIEnv* env, jclass clazz, jint nativePtr,
522 jbyteArray data, jint offset, jint length)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800523{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800524 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800525 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
Jeff Sharkey047238c2012-03-07 16:51:38 -0800542static void android_os_Parcel_appendFrom(JNIEnv* env, jclass clazz, jint thisNativePtr,
543 jint otherNativePtr, jint offset, jint length)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800544{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800545 Parcel* thisParcel = reinterpret_cast<Parcel*>(thisNativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800546 if (thisParcel == NULL) {
547 return;
548 }
Jeff Sharkey047238c2012-03-07 16:51:38 -0800549 Parcel* otherParcel = reinterpret_cast<Parcel*>(otherNativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800550 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
Jeff Sharkey047238c2012-03-07 16:51:38 -0800560static jboolean android_os_Parcel_hasFileDescriptors(JNIEnv* env, jclass clazz, jint nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800561{
562 jboolean ret = JNI_FALSE;
Jeff Sharkey047238c2012-03-07 16:51:38 -0800563 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800564 if (parcel != NULL) {
565 if (parcel->hasFileDescriptors()) {
566 ret = JNI_TRUE;
567 }
568 }
569 return ret;
570}
571
Jeff Sharkey047238c2012-03-07 16:51:38 -0800572static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jclass clazz, jint nativePtr,
573 jstring name)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800574{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800575 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800576 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
Jeff Sharkey047238c2012-03-07 16:51:38 -0800587static void android_os_Parcel_enforceInterface(JNIEnv* env, jclass clazz, jint nativePtr, jstring name)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800588{
589 jboolean ret = JNI_FALSE;
590
Jeff Sharkey047238c2012-03-07 16:51:38 -0800591 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800592 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
625static const JNINativeMethod gParcelMethods[] = {
Jeff Sharkey047238c2012-03-07 16:51:38 -0800626 {"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},
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800670};
671
672const char* const kParcelPathName = "android/os/Parcel";
673
674int 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
Insun Kang89020972012-05-01 14:13:19 +0900681 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");
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800686
687 return AndroidRuntime::registerNativeMethods(
688 env, kParcelPathName,
689 gParcelMethods, NELEM(gParcelMethods));
690}
691
692};