blob: 8f7908a0e048c21565e5af455aa883876a8a1ed2 [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>
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -080038#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 <ScopedUtfChars.h>
45#include <ScopedLocalRef.h>
46
47#include <android_runtime/AndroidRuntime.h>
48
Andreas Gampe987f79f2014-11-18 17:29:46 -080049#include "core_jni_helpers.h"
50
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -080051//#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
61namespace android {
62
63static struct parcel_offsets_t
64{
Insun Kang89020972012-05-01 14:13:19 +090065 jclass clazz;
Jeff Sharkey047238c2012-03-07 16:51:38 -080066 jfieldID mNativePtr;
Insun Kang89020972012-05-01 14:13:19 +090067 jmethodID obtain;
68 jmethodID recycle;
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -080069} gParcelOffsets;
70
71Parcel* parcelForJavaObject(JNIEnv* env, jobject obj)
72{
73 if (obj) {
Ashok Bhat8ab665d2014-01-22 16:00:20 +000074 Parcel* p = (Parcel*)env->GetLongField(obj, gParcelOffsets.mNativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -080075 if (p != NULL) {
76 return p;
77 }
78 jniThrowException(env, "java/lang/IllegalStateException", "Parcel has been finalized!");
79 }
80 return NULL;
81}
82
Insun Kang89020972012-05-01 14:13:19 +090083jobject createJavaParcelObject(JNIEnv* env)
84{
85 return env->CallStaticObjectMethod(gParcelOffsets.clazz, gParcelOffsets.obtain);
86}
87
88void recycleJavaParcelObject(JNIEnv* env, jobject parcelObj)
89{
90 env->CallVoidMethod(parcelObj, gParcelOffsets.recycle);
91}
92
Ashok Bhat8ab665d2014-01-22 16:00:20 +000093static jint android_os_Parcel_dataSize(JNIEnv* env, jclass clazz, jlong nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -080094{
Jeff Sharkey047238c2012-03-07 16:51:38 -080095 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -080096 return parcel ? parcel->dataSize() : 0;
97}
98
Ashok Bhat8ab665d2014-01-22 16:00:20 +000099static jint android_os_Parcel_dataAvail(JNIEnv* env, jclass clazz, jlong nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800100{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800101 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800102 return parcel ? parcel->dataAvail() : 0;
103}
104
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000105static jint android_os_Parcel_dataPosition(JNIEnv* env, jclass clazz, jlong nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800106{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800107 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800108 return parcel ? parcel->dataPosition() : 0;
109}
110
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000111static jint android_os_Parcel_dataCapacity(JNIEnv* env, jclass clazz, jlong nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800112{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800113 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800114 return parcel ? parcel->dataCapacity() : 0;
115}
116
Adrian Roos04505652015-10-22 16:12:01 -0700117static jlong android_os_Parcel_setDataSize(JNIEnv* env, jclass clazz, jlong nativePtr, jint size)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800118{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800119 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800120 if (parcel != NULL) {
121 const status_t err = parcel->setDataSize(size);
122 if (err != NO_ERROR) {
123 signalExceptionForError(env, clazz, err);
124 }
Adrian Roos04505652015-10-22 16:12:01 -0700125 return parcel->getOpenAshmemSize();
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800126 }
Adrian Roos04505652015-10-22 16:12:01 -0700127 return 0;
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800128}
129
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000130static void android_os_Parcel_setDataPosition(JNIEnv* env, jclass clazz, jlong nativePtr, jint pos)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800131{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800132 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800133 if (parcel != NULL) {
134 parcel->setDataPosition(pos);
135 }
136}
137
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000138static void android_os_Parcel_setDataCapacity(JNIEnv* env, jclass clazz, jlong nativePtr, jint size)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800139{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800140 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800141 if (parcel != NULL) {
142 const status_t err = parcel->setDataCapacity(size);
143 if (err != NO_ERROR) {
144 signalExceptionForError(env, clazz, err);
145 }
146 }
147}
148
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000149static jboolean android_os_Parcel_pushAllowFds(JNIEnv* env, jclass clazz, jlong nativePtr, jboolean allowFds)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800150{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800151 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800152 jboolean ret = JNI_TRUE;
153 if (parcel != NULL) {
154 ret = (jboolean)parcel->pushAllowFds(allowFds);
155 }
156 return ret;
157}
158
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000159static void android_os_Parcel_restoreAllowFds(JNIEnv* env, jclass clazz, jlong nativePtr, jboolean lastValue)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800160{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800161 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800162 if (parcel != NULL) {
163 parcel->restoreAllowFds((bool)lastValue);
164 }
165}
166
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000167static void android_os_Parcel_writeNative(JNIEnv* env, jclass clazz, jlong nativePtr, jobject data,
Jeff Sharkey047238c2012-03-07 16:51:38 -0800168 jint offset, jint length)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800169{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800170 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800171 if (parcel == NULL) {
172 return;
173 }
174
175 const status_t err = parcel->writeInt32(length);
176 if (err != NO_ERROR) {
177 signalExceptionForError(env, clazz, err);
178 return;
179 }
180
181 void* dest = parcel->writeInplace(length);
182 if (dest == NULL) {
183 signalExceptionForError(env, clazz, NO_MEMORY);
184 return;
185 }
186
187 jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)data, 0);
188 if (ar) {
189 memcpy(dest, ar + offset, length);
190 env->ReleasePrimitiveArrayCritical((jarray)data, ar, 0);
191 }
192}
193
Sandeep Siddhartha90d7a3e2014-07-25 16:19:42 -0700194static void android_os_Parcel_writeBlob(JNIEnv* env, jclass clazz, jlong nativePtr, jobject data,
195 jint offset, jint length) {
196 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
197 if (parcel == NULL) {
198 return;
199 }
200
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700201 if (data == NULL) {
202 const status_t err = parcel->writeInt32(-1);
203 if (err != NO_ERROR) {
204 signalExceptionForError(env, clazz, err);
205 }
206 return;
207 }
208
Sandeep Siddhartha90d7a3e2014-07-25 16:19:42 -0700209 const status_t err = parcel->writeInt32(length);
210 if (err != NO_ERROR) {
211 signalExceptionForError(env, clazz, err);
212 return;
213 }
214
215 android::Parcel::WritableBlob blob;
Jeff Browna316c5d2015-06-05 15:14:06 -0700216 android::status_t err2 = parcel->writeBlob(length, false, &blob);
Sandeep Siddhartha90d7a3e2014-07-25 16:19:42 -0700217 if (err2 != NO_ERROR) {
218 signalExceptionForError(env, clazz, err2);
219 return;
220 }
221
222 jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)data, 0);
223 if (ar == NULL) {
224 memset(blob.data(), 0, length);
225 } else {
226 memcpy(blob.data(), ar + offset, length);
227 env->ReleasePrimitiveArrayCritical((jarray)data, ar, 0);
228 }
229
230 blob.release();
231}
232
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000233static void android_os_Parcel_writeInt(JNIEnv* env, jclass clazz, jlong nativePtr, jint val) {
Jeff Sharkey047238c2012-03-07 16:51:38 -0800234 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Brian Carlstrom849ea022015-06-23 18:02:12 -0700235 if (parcel != NULL) {
236 const status_t err = parcel->writeInt32(val);
237 if (err != NO_ERROR) {
238 signalExceptionForError(env, clazz, err);
239 }
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800240 }
241}
242
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000243static void android_os_Parcel_writeLong(JNIEnv* env, jclass clazz, jlong nativePtr, jlong val)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800244{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800245 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800246 if (parcel != NULL) {
247 const status_t err = parcel->writeInt64(val);
248 if (err != NO_ERROR) {
249 signalExceptionForError(env, clazz, err);
250 }
251 }
252}
253
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000254static void android_os_Parcel_writeFloat(JNIEnv* env, jclass clazz, jlong nativePtr, jfloat val)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800255{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800256 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800257 if (parcel != NULL) {
258 const status_t err = parcel->writeFloat(val);
259 if (err != NO_ERROR) {
260 signalExceptionForError(env, clazz, err);
261 }
262 }
263}
264
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000265static void android_os_Parcel_writeDouble(JNIEnv* env, jclass clazz, jlong nativePtr, jdouble val)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800266{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800267 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800268 if (parcel != NULL) {
269 const status_t err = parcel->writeDouble(val);
270 if (err != NO_ERROR) {
271 signalExceptionForError(env, clazz, err);
272 }
273 }
274}
275
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000276static void android_os_Parcel_writeString(JNIEnv* env, jclass clazz, jlong nativePtr, jstring val)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800277{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800278 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800279 if (parcel != NULL) {
280 status_t err = NO_MEMORY;
281 if (val) {
282 const jchar* str = env->GetStringCritical(val, 0);
283 if (str) {
Dan Albert66987492014-11-20 11:41:21 -0800284 err = parcel->writeString16(
285 reinterpret_cast<const char16_t*>(str),
286 env->GetStringLength(val));
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800287 env->ReleaseStringCritical(val, str);
288 }
289 } else {
290 err = parcel->writeString16(NULL, 0);
291 }
292 if (err != NO_ERROR) {
293 signalExceptionForError(env, clazz, err);
294 }
295 }
296}
297
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000298static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800299{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800300 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800301 if (parcel != NULL) {
302 const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
303 if (err != NO_ERROR) {
304 signalExceptionForError(env, clazz, err);
305 }
306 }
307}
308
Adrian Roos04505652015-10-22 16:12:01 -0700309static jlong android_os_Parcel_writeFileDescriptor(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800310{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800311 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800312 if (parcel != NULL) {
313 const status_t err =
314 parcel->writeDupFileDescriptor(jniGetFDFromFileDescriptor(env, object));
315 if (err != NO_ERROR) {
316 signalExceptionForError(env, clazz, err);
317 }
Adrian Roos04505652015-10-22 16:12:01 -0700318 return parcel->getOpenAshmemSize();
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800319 }
Adrian Roos04505652015-10-22 16:12:01 -0700320 return 0;
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800321}
322
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000323static jbyteArray android_os_Parcel_createByteArray(JNIEnv* env, jclass clazz, jlong nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800324{
325 jbyteArray ret = NULL;
326
Jeff Sharkey047238c2012-03-07 16:51:38 -0800327 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800328 if (parcel != NULL) {
329 int32_t len = parcel->readInt32();
330
331 // sanity check the stored length against the true data size
332 if (len >= 0 && len <= (int32_t)parcel->dataAvail()) {
333 ret = env->NewByteArray(len);
334
335 if (ret != NULL) {
336 jbyte* a2 = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
337 if (a2) {
338 const void* data = parcel->readInplace(len);
339 memcpy(a2, data, len);
340 env->ReleasePrimitiveArrayCritical(ret, a2, 0);
341 }
342 }
343 }
344 }
345
346 return ret;
347}
348
Sandeep Siddhartha90d7a3e2014-07-25 16:19:42 -0700349static jbyteArray android_os_Parcel_readBlob(JNIEnv* env, jclass clazz, jlong nativePtr)
350{
351 jbyteArray ret = NULL;
352
353 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
354 if (parcel != NULL) {
355 int32_t len = parcel->readInt32();
356 if (len >= 0) {
357 android::Parcel::ReadableBlob blob;
358 android::status_t err = parcel->readBlob(len, &blob);
359 if (err != NO_ERROR) {
360 signalExceptionForError(env, clazz, err);
361 return NULL;
362 }
363
364 ret = env->NewByteArray(len);
365 if (ret != NULL) {
366 jbyte* a2 = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
367 if (a2) {
368 memcpy(a2, blob.data(), len);
369 env->ReleasePrimitiveArrayCritical(ret, a2, 0);
370 }
371 }
372 blob.release();
373 }
374 }
375
376 return ret;
377}
378
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000379static jint android_os_Parcel_readInt(JNIEnv* env, jclass clazz, jlong nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800380{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800381 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800382 if (parcel != NULL) {
383 return parcel->readInt32();
384 }
385 return 0;
386}
387
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000388static jlong android_os_Parcel_readLong(JNIEnv* env, jclass clazz, jlong nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800389{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800390 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800391 if (parcel != NULL) {
392 return parcel->readInt64();
393 }
394 return 0;
395}
396
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000397static jfloat android_os_Parcel_readFloat(JNIEnv* env, jclass clazz, jlong nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800398{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800399 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800400 if (parcel != NULL) {
401 return parcel->readFloat();
402 }
403 return 0;
404}
405
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000406static jdouble android_os_Parcel_readDouble(JNIEnv* env, jclass clazz, jlong nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800407{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800408 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800409 if (parcel != NULL) {
410 return parcel->readDouble();
411 }
412 return 0;
413}
414
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000415static jstring android_os_Parcel_readString(JNIEnv* env, jclass clazz, jlong nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800416{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800417 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800418 if (parcel != NULL) {
419 size_t len;
420 const char16_t* str = parcel->readString16Inplace(&len);
421 if (str) {
Dan Albert66987492014-11-20 11:41:21 -0800422 return env->NewString(reinterpret_cast<const jchar*>(str), len);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800423 }
424 return NULL;
425 }
426 return NULL;
427}
428
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000429static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800430{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800431 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800432 if (parcel != NULL) {
433 return javaObjectForIBinder(env, parcel->readStrongBinder());
434 }
435 return NULL;
436}
437
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000438static jobject android_os_Parcel_readFileDescriptor(JNIEnv* env, jclass clazz, jlong nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800439{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800440 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800441 if (parcel != NULL) {
442 int fd = parcel->readFileDescriptor();
443 if (fd < 0) return NULL;
444 fd = dup(fd);
445 if (fd < 0) return NULL;
446 return jniCreateFileDescriptor(env, fd);
447 }
448 return NULL;
449}
450
Jeff Sharkey047238c2012-03-07 16:51:38 -0800451static jobject android_os_Parcel_openFileDescriptor(JNIEnv* env, jclass clazz,
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800452 jstring name, jint mode)
453{
454 if (name == NULL) {
455 jniThrowNullPointerException(env, NULL);
456 return NULL;
457 }
tao.peid4153032015-06-02 10:06:20 +0800458 ScopedUtfChars name8(env, name);
459 if (name8.c_str() == NULL) {
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800460 return NULL;
461 }
tao.peid4153032015-06-02 10:06:20 +0800462
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800463 int flags=0;
464 switch (mode&0x30000000) {
465 case 0:
466 case 0x10000000:
467 flags = O_RDONLY;
468 break;
469 case 0x20000000:
470 flags = O_WRONLY;
471 break;
472 case 0x30000000:
473 flags = O_RDWR;
474 break;
475 }
476
477 if (mode&0x08000000) flags |= O_CREAT;
478 if (mode&0x04000000) flags |= O_TRUNC;
479 if (mode&0x02000000) flags |= O_APPEND;
480
481 int realMode = S_IRWXU|S_IRWXG;
482 if (mode&0x00000001) realMode |= S_IROTH;
483 if (mode&0x00000002) realMode |= S_IWOTH;
484
tao.peid4153032015-06-02 10:06:20 +0800485 int fd = open(name8.c_str(), flags, realMode);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800486 if (fd < 0) {
487 jniThrowException(env, "java/io/FileNotFoundException", strerror(errno));
488 return NULL;
489 }
490 jobject object = jniCreateFileDescriptor(env, fd);
491 if (object == NULL) {
492 close(fd);
493 }
494 return object;
495}
496
Jeff Sharkey047238c2012-03-07 16:51:38 -0800497static jobject android_os_Parcel_dupFileDescriptor(JNIEnv* env, jclass clazz, jobject orig)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800498{
499 if (orig == NULL) {
500 jniThrowNullPointerException(env, NULL);
501 return NULL;
502 }
503 int origfd = jniGetFDFromFileDescriptor(env, orig);
504 if (origfd < 0) {
505 jniThrowException(env, "java/lang/IllegalArgumentException", "bad FileDescriptor");
506 return NULL;
507 }
508
509 int fd = dup(origfd);
510 if (fd < 0) {
511 jniThrowIOException(env, errno);
512 return NULL;
513 }
514 jobject object = jniCreateFileDescriptor(env, fd);
515 if (object == NULL) {
516 close(fd);
517 }
518 return object;
519}
520
Jeff Sharkey047238c2012-03-07 16:51:38 -0800521static void android_os_Parcel_closeFileDescriptor(JNIEnv* env, jclass clazz, jobject object)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800522{
523 if (object == NULL) {
524 jniThrowNullPointerException(env, NULL);
525 return;
526 }
527 int fd = jniGetFDFromFileDescriptor(env, object);
528 if (fd >= 0) {
529 jniSetFileDescriptorOfFD(env, object, -1);
530 //ALOGI("Closing ParcelFileDescriptor %d\n", fd);
531 close(fd);
532 }
533}
534
Jeff Sharkey047238c2012-03-07 16:51:38 -0800535static void android_os_Parcel_clearFileDescriptor(JNIEnv* env, jclass clazz, jobject object)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800536{
537 if (object == NULL) {
538 jniThrowNullPointerException(env, NULL);
539 return;
540 }
541 int fd = jniGetFDFromFileDescriptor(env, object);
542 if (fd >= 0) {
543 jniSetFileDescriptorOfFD(env, object, -1);
544 }
545}
546
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000547static jlong android_os_Parcel_create(JNIEnv* env, jclass clazz)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800548{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800549 Parcel* parcel = new Parcel();
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000550 return reinterpret_cast<jlong>(parcel);
Jeff Sharkey047238c2012-03-07 16:51:38 -0800551}
552
Adrian Roos04505652015-10-22 16:12:01 -0700553static jlong android_os_Parcel_freeBuffer(JNIEnv* env, jclass clazz, jlong nativePtr)
Jeff Sharkey047238c2012-03-07 16:51:38 -0800554{
555 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
556 if (parcel != NULL) {
557 parcel->freeData();
Adrian Roos04505652015-10-22 16:12:01 -0700558 return parcel->getOpenAshmemSize();
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800559 }
Adrian Roos04505652015-10-22 16:12:01 -0700560 return 0;
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800561}
562
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000563static void android_os_Parcel_destroy(JNIEnv* env, jclass clazz, jlong nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800564{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800565 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
566 delete parcel;
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800567}
568
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000569static jbyteArray android_os_Parcel_marshall(JNIEnv* env, jclass clazz, jlong nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800570{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800571 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800572 if (parcel == NULL) {
573 return NULL;
574 }
575
576 // do not marshall if there are binder objects in the parcel
577 if (parcel->objectsCount())
578 {
579 jniThrowException(env, "java/lang/RuntimeException", "Tried to marshall a Parcel that contained Binder objects.");
580 return NULL;
581 }
582
583 jbyteArray ret = env->NewByteArray(parcel->dataSize());
584
585 if (ret != NULL)
586 {
587 jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
588 if (array != NULL)
589 {
590 memcpy(array, parcel->data(), parcel->dataSize());
591 env->ReleasePrimitiveArrayCritical(ret, array, 0);
592 }
593 }
594
595 return ret;
596}
597
Adrian Roos04505652015-10-22 16:12:01 -0700598static jlong android_os_Parcel_unmarshall(JNIEnv* env, jclass clazz, jlong nativePtr,
599 jbyteArray data, jint offset, jint length)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800600{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800601 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800602 if (parcel == NULL || length < 0) {
Adrian Roos04505652015-10-22 16:12:01 -0700603 return 0;
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800604 }
605
606 jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(data, 0);
607 if (array)
608 {
609 parcel->setDataSize(length);
610 parcel->setDataPosition(0);
611
612 void* raw = parcel->writeInplace(length);
613 memcpy(raw, (array + offset), length);
614
615 env->ReleasePrimitiveArrayCritical(data, array, 0);
616 }
Adrian Roos04505652015-10-22 16:12:01 -0700617 return parcel->getOpenAshmemSize();
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800618}
619
Adrian Roos04505652015-10-22 16:12:01 -0700620static jlong android_os_Parcel_appendFrom(JNIEnv* env, jclass clazz, jlong thisNativePtr,
621 jlong otherNativePtr, jint offset, jint length)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800622{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800623 Parcel* thisParcel = reinterpret_cast<Parcel*>(thisNativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800624 if (thisParcel == NULL) {
Adrian Roos04505652015-10-22 16:12:01 -0700625 return 0;
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800626 }
Jeff Sharkey047238c2012-03-07 16:51:38 -0800627 Parcel* otherParcel = reinterpret_cast<Parcel*>(otherNativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800628 if (otherParcel == NULL) {
Adrian Roos04505652015-10-22 16:12:01 -0700629 return thisParcel->getOpenAshmemSize();
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800630 }
631
632 status_t err = thisParcel->appendFrom(otherParcel, offset, length);
633 if (err != NO_ERROR) {
634 signalExceptionForError(env, clazz, err);
635 }
Adrian Roos04505652015-10-22 16:12:01 -0700636 return thisParcel->getOpenAshmemSize();
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800637}
638
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000639static jboolean android_os_Parcel_hasFileDescriptors(JNIEnv* env, jclass clazz, jlong nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800640{
641 jboolean ret = JNI_FALSE;
Jeff Sharkey047238c2012-03-07 16:51:38 -0800642 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800643 if (parcel != NULL) {
644 if (parcel->hasFileDescriptors()) {
645 ret = JNI_TRUE;
646 }
647 }
648 return ret;
649}
650
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000651static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jclass clazz, jlong nativePtr,
Jeff Sharkey047238c2012-03-07 16:51:38 -0800652 jstring name)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800653{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800654 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800655 if (parcel != NULL) {
656 // In the current implementation, the token is just the serialized interface name that
657 // the caller expects to be invoking
658 const jchar* str = env->GetStringCritical(name, 0);
659 if (str != NULL) {
Dan Albert66987492014-11-20 11:41:21 -0800660 parcel->writeInterfaceToken(String16(
661 reinterpret_cast<const char16_t*>(str),
662 env->GetStringLength(name)));
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800663 env->ReleaseStringCritical(name, str);
664 }
665 }
666}
667
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000668static void android_os_Parcel_enforceInterface(JNIEnv* env, jclass clazz, jlong nativePtr, jstring name)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800669{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800670 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800671 if (parcel != NULL) {
672 const jchar* str = env->GetStringCritical(name, 0);
673 if (str) {
674 IPCThreadState* threadState = IPCThreadState::self();
675 const int32_t oldPolicy = threadState->getStrictModePolicy();
676 const bool isValid = parcel->enforceInterface(
Dan Albert66987492014-11-20 11:41:21 -0800677 String16(reinterpret_cast<const char16_t*>(str),
678 env->GetStringLength(name)),
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800679 threadState);
680 env->ReleaseStringCritical(name, str);
681 if (isValid) {
682 const int32_t newPolicy = threadState->getStrictModePolicy();
683 if (oldPolicy != newPolicy) {
684 // Need to keep the Java-level thread-local strict
685 // mode policy in sync for the libcore
686 // enforcements, which involves an upcall back
687 // into Java. (We can't modify the
688 // Parcel.enforceInterface signature, as it's
689 // pseudo-public, and used via AIDL
690 // auto-generation...)
691 set_dalvik_blockguard_policy(env, newPolicy);
692 }
693 return; // everything was correct -> return silently
694 }
695 }
696 }
697
698 // all error conditions wind up here
699 jniThrowException(env, "java/lang/SecurityException",
700 "Binder invocation to an incorrect interface");
701}
702
Dianne Hackbornfabb70b2014-11-11 12:22:36 -0800703static jlong android_os_Parcel_getGlobalAllocSize(JNIEnv* env, jclass clazz)
704{
705 return Parcel::getGlobalAllocSize();
706}
707
708static jlong android_os_Parcel_getGlobalAllocCount(JNIEnv* env, jclass clazz)
709{
710 return Parcel::getGlobalAllocCount();
711}
712
Dan Sandler5ce04302015-04-09 23:50:15 -0400713static jlong android_os_Parcel_getBlobAshmemSize(JNIEnv* env, jclass clazz, jlong nativePtr)
714{
715 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
716 if (parcel != NULL) {
717 return parcel->getBlobAshmemSize();
718 }
719 return 0;
720}
721
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800722// ----------------------------------------------------------------------------
723
724static const JNINativeMethod gParcelMethods[] = {
John Reck71207b52016-09-28 13:28:09 -0700725 // @FastNative
726 {"nativeDataSize", "(J)I", (void*)android_os_Parcel_dataSize},
727 // @FastNative
728 {"nativeDataAvail", "(J)I", (void*)android_os_Parcel_dataAvail},
729 // @FastNative
730 {"nativeDataPosition", "(J)I", (void*)android_os_Parcel_dataPosition},
731 // @FastNative
732 {"nativeDataCapacity", "(J)I", (void*)android_os_Parcel_dataCapacity},
733 // @FastNative
734 {"nativeSetDataSize", "(JI)J", (void*)android_os_Parcel_setDataSize},
735 // @FastNative
736 {"nativeSetDataPosition", "(JI)V", (void*)android_os_Parcel_setDataPosition},
737 // @FastNative
738 {"nativeSetDataCapacity", "(JI)V", (void*)android_os_Parcel_setDataCapacity},
Jeff Sharkey047238c2012-03-07 16:51:38 -0800739
John Reck71207b52016-09-28 13:28:09 -0700740 // @FastNative
741 {"nativePushAllowFds", "(JZ)Z", (void*)android_os_Parcel_pushAllowFds},
742 // @FastNative
743 {"nativeRestoreAllowFds", "(JZ)V", (void*)android_os_Parcel_restoreAllowFds},
Jeff Sharkey047238c2012-03-07 16:51:38 -0800744
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000745 {"nativeWriteByteArray", "(J[BII)V", (void*)android_os_Parcel_writeNative},
Sandeep Siddhartha90d7a3e2014-07-25 16:19:42 -0700746 {"nativeWriteBlob", "(J[BII)V", (void*)android_os_Parcel_writeBlob},
John Reck71207b52016-09-28 13:28:09 -0700747 // @FastNative
748 {"nativeWriteInt", "(JI)V", (void*)android_os_Parcel_writeInt},
749 // @FastNative
750 {"nativeWriteLong", "(JJ)V", (void*)android_os_Parcel_writeLong},
751 // @FastNative
752 {"nativeWriteFloat", "(JF)V", (void*)android_os_Parcel_writeFloat},
753 // @FastNative
754 {"nativeWriteDouble", "(JD)V", (void*)android_os_Parcel_writeDouble},
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000755 {"nativeWriteString", "(JLjava/lang/String;)V", (void*)android_os_Parcel_writeString},
756 {"nativeWriteStrongBinder", "(JLandroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder},
Adrian Roos04505652015-10-22 16:12:01 -0700757 {"nativeWriteFileDescriptor", "(JLjava/io/FileDescriptor;)J", (void*)android_os_Parcel_writeFileDescriptor},
Jeff Sharkey047238c2012-03-07 16:51:38 -0800758
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000759 {"nativeCreateByteArray", "(J)[B", (void*)android_os_Parcel_createByteArray},
Sandeep Siddhartha90d7a3e2014-07-25 16:19:42 -0700760 {"nativeReadBlob", "(J)[B", (void*)android_os_Parcel_readBlob},
John Reck71207b52016-09-28 13:28:09 -0700761 // @FastNative
762 {"nativeReadInt", "(J)I", (void*)android_os_Parcel_readInt},
763 // @FastNative
764 {"nativeReadLong", "(J)J", (void*)android_os_Parcel_readLong},
765 // @FastNative
766 {"nativeReadFloat", "(J)F", (void*)android_os_Parcel_readFloat},
767 // @FastNative
768 {"nativeReadDouble", "(J)D", (void*)android_os_Parcel_readDouble},
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000769 {"nativeReadString", "(J)Ljava/lang/String;", (void*)android_os_Parcel_readString},
770 {"nativeReadStrongBinder", "(J)Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder},
771 {"nativeReadFileDescriptor", "(J)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_readFileDescriptor},
Jeff Sharkey047238c2012-03-07 16:51:38 -0800772
773 {"openFileDescriptor", "(Ljava/lang/String;I)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_openFileDescriptor},
774 {"dupFileDescriptor", "(Ljava/io/FileDescriptor;)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_dupFileDescriptor},
775 {"closeFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_closeFileDescriptor},
776 {"clearFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_clearFileDescriptor},
777
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000778 {"nativeCreate", "()J", (void*)android_os_Parcel_create},
Adrian Roos04505652015-10-22 16:12:01 -0700779 {"nativeFreeBuffer", "(J)J", (void*)android_os_Parcel_freeBuffer},
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000780 {"nativeDestroy", "(J)V", (void*)android_os_Parcel_destroy},
Jeff Sharkey047238c2012-03-07 16:51:38 -0800781
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000782 {"nativeMarshall", "(J)[B", (void*)android_os_Parcel_marshall},
Adrian Roos04505652015-10-22 16:12:01 -0700783 {"nativeUnmarshall", "(J[BII)J", (void*)android_os_Parcel_unmarshall},
784 {"nativeAppendFrom", "(JJII)J", (void*)android_os_Parcel_appendFrom},
John Reck71207b52016-09-28 13:28:09 -0700785 // @FastNative
786 {"nativeHasFileDescriptors", "(J)Z", (void*)android_os_Parcel_hasFileDescriptors},
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000787 {"nativeWriteInterfaceToken", "(JLjava/lang/String;)V", (void*)android_os_Parcel_writeInterfaceToken},
788 {"nativeEnforceInterface", "(JLjava/lang/String;)V", (void*)android_os_Parcel_enforceInterface},
Dianne Hackbornfabb70b2014-11-11 12:22:36 -0800789
790 {"getGlobalAllocSize", "()J", (void*)android_os_Parcel_getGlobalAllocSize},
791 {"getGlobalAllocCount", "()J", (void*)android_os_Parcel_getGlobalAllocCount},
Dan Sandler5ce04302015-04-09 23:50:15 -0400792
Dan Sandleraa861662015-04-21 10:24:32 -0400793 {"nativeGetBlobAshmemSize", "(J)J", (void*)android_os_Parcel_getBlobAshmemSize},
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800794};
795
796const char* const kParcelPathName = "android/os/Parcel";
797
798int register_android_os_Parcel(JNIEnv* env)
799{
Andreas Gampe987f79f2014-11-18 17:29:46 -0800800 jclass clazz = FindClassOrDie(env, kParcelPathName);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800801
Andreas Gampe987f79f2014-11-18 17:29:46 -0800802 gParcelOffsets.clazz = MakeGlobalRefOrDie(env, clazz);
803 gParcelOffsets.mNativePtr = GetFieldIDOrDie(env, clazz, "mNativePtr", "J");
804 gParcelOffsets.obtain = GetStaticMethodIDOrDie(env, clazz, "obtain", "()Landroid/os/Parcel;");
805 gParcelOffsets.recycle = GetMethodIDOrDie(env, clazz, "recycle", "()V");
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800806
Andreas Gampe987f79f2014-11-18 17:29:46 -0800807 return RegisterMethodsOrDie(env, kParcelPathName, gParcelMethods, NELEM(gParcelMethods));
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800808}
809
810};