blob: 4f29c50274231974ef7a93d67c78a5e706e91bbc [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
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000117static void 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 }
125 }
126}
127
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000128static void android_os_Parcel_setDataPosition(JNIEnv* env, jclass clazz, jlong nativePtr, jint pos)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800129{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800130 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800131 if (parcel != NULL) {
132 parcel->setDataPosition(pos);
133 }
134}
135
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000136static void android_os_Parcel_setDataCapacity(JNIEnv* env, jclass clazz, jlong nativePtr, jint size)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800137{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800138 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800139 if (parcel != NULL) {
140 const status_t err = parcel->setDataCapacity(size);
141 if (err != NO_ERROR) {
142 signalExceptionForError(env, clazz, err);
143 }
144 }
145}
146
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000147static jboolean android_os_Parcel_pushAllowFds(JNIEnv* env, jclass clazz, jlong nativePtr, jboolean allowFds)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800148{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800149 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800150 jboolean ret = JNI_TRUE;
151 if (parcel != NULL) {
152 ret = (jboolean)parcel->pushAllowFds(allowFds);
153 }
154 return ret;
155}
156
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000157static void android_os_Parcel_restoreAllowFds(JNIEnv* env, jclass clazz, jlong nativePtr, jboolean lastValue)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800158{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800159 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800160 if (parcel != NULL) {
161 parcel->restoreAllowFds((bool)lastValue);
162 }
163}
164
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000165static void android_os_Parcel_writeNative(JNIEnv* env, jclass clazz, jlong nativePtr, jobject data,
Jeff Sharkey047238c2012-03-07 16:51:38 -0800166 jint offset, jint length)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800167{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800168 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800169 if (parcel == NULL) {
170 return;
171 }
172
173 const status_t err = parcel->writeInt32(length);
174 if (err != NO_ERROR) {
175 signalExceptionForError(env, clazz, err);
176 return;
177 }
178
179 void* dest = parcel->writeInplace(length);
180 if (dest == NULL) {
181 signalExceptionForError(env, clazz, NO_MEMORY);
182 return;
183 }
184
185 jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)data, 0);
186 if (ar) {
187 memcpy(dest, ar + offset, length);
188 env->ReleasePrimitiveArrayCritical((jarray)data, ar, 0);
189 }
190}
191
Sandeep Siddhartha90d7a3e2014-07-25 16:19:42 -0700192static void android_os_Parcel_writeBlob(JNIEnv* env, jclass clazz, jlong nativePtr, jobject data,
193 jint offset, jint length) {
194 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
195 if (parcel == NULL) {
196 return;
197 }
198
Sandeep Siddhartha39c12fa2014-07-25 18:37:29 -0700199 if (data == NULL) {
200 const status_t err = parcel->writeInt32(-1);
201 if (err != NO_ERROR) {
202 signalExceptionForError(env, clazz, err);
203 }
204 return;
205 }
206
Sandeep Siddhartha90d7a3e2014-07-25 16:19:42 -0700207 const status_t err = parcel->writeInt32(length);
208 if (err != NO_ERROR) {
209 signalExceptionForError(env, clazz, err);
210 return;
211 }
212
213 android::Parcel::WritableBlob blob;
214 android::status_t err2 = parcel->writeBlob(length, &blob);
215 if (err2 != NO_ERROR) {
216 signalExceptionForError(env, clazz, err2);
217 return;
218 }
219
220 jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)data, 0);
221 if (ar == NULL) {
222 memset(blob.data(), 0, length);
223 } else {
224 memcpy(blob.data(), ar + offset, length);
225 env->ReleasePrimitiveArrayCritical((jarray)data, ar, 0);
226 }
227
228 blob.release();
229}
230
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000231static void android_os_Parcel_writeInt(JNIEnv* env, jclass clazz, jlong nativePtr, jint val) {
Jeff Sharkey047238c2012-03-07 16:51:38 -0800232 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
233 const status_t err = parcel->writeInt32(val);
234 if (err != NO_ERROR) {
235 signalExceptionForError(env, clazz, err);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800236 }
237}
238
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000239static void android_os_Parcel_writeLong(JNIEnv* env, jclass clazz, jlong nativePtr, jlong val)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800240{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800241 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800242 if (parcel != NULL) {
243 const status_t err = parcel->writeInt64(val);
244 if (err != NO_ERROR) {
245 signalExceptionForError(env, clazz, err);
246 }
247 }
248}
249
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000250static void android_os_Parcel_writeFloat(JNIEnv* env, jclass clazz, jlong nativePtr, jfloat val)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800251{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800252 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800253 if (parcel != NULL) {
254 const status_t err = parcel->writeFloat(val);
255 if (err != NO_ERROR) {
256 signalExceptionForError(env, clazz, err);
257 }
258 }
259}
260
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000261static void android_os_Parcel_writeDouble(JNIEnv* env, jclass clazz, jlong nativePtr, jdouble val)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800262{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800263 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800264 if (parcel != NULL) {
265 const status_t err = parcel->writeDouble(val);
266 if (err != NO_ERROR) {
267 signalExceptionForError(env, clazz, err);
268 }
269 }
270}
271
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000272static void android_os_Parcel_writeString(JNIEnv* env, jclass clazz, jlong nativePtr, jstring val)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800273{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800274 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800275 if (parcel != NULL) {
276 status_t err = NO_MEMORY;
277 if (val) {
278 const jchar* str = env->GetStringCritical(val, 0);
279 if (str) {
Dan Albert66987492014-11-20 11:41:21 -0800280 err = parcel->writeString16(
281 reinterpret_cast<const char16_t*>(str),
282 env->GetStringLength(val));
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800283 env->ReleaseStringCritical(val, str);
284 }
285 } else {
286 err = parcel->writeString16(NULL, 0);
287 }
288 if (err != NO_ERROR) {
289 signalExceptionForError(env, clazz, err);
290 }
291 }
292}
293
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000294static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800295{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800296 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800297 if (parcel != NULL) {
298 const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
299 if (err != NO_ERROR) {
300 signalExceptionForError(env, clazz, err);
301 }
302 }
303}
304
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000305static void android_os_Parcel_writeFileDescriptor(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800306{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800307 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800308 if (parcel != NULL) {
309 const status_t err =
310 parcel->writeDupFileDescriptor(jniGetFDFromFileDescriptor(env, object));
311 if (err != NO_ERROR) {
312 signalExceptionForError(env, clazz, err);
313 }
314 }
315}
316
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000317static jbyteArray android_os_Parcel_createByteArray(JNIEnv* env, jclass clazz, jlong nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800318{
319 jbyteArray ret = NULL;
320
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 int32_t len = parcel->readInt32();
324
325 // sanity check the stored length against the true data size
326 if (len >= 0 && len <= (int32_t)parcel->dataAvail()) {
327 ret = env->NewByteArray(len);
328
329 if (ret != NULL) {
330 jbyte* a2 = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
331 if (a2) {
332 const void* data = parcel->readInplace(len);
333 memcpy(a2, data, len);
334 env->ReleasePrimitiveArrayCritical(ret, a2, 0);
335 }
336 }
337 }
338 }
339
340 return ret;
341}
342
Sandeep Siddhartha90d7a3e2014-07-25 16:19:42 -0700343static jbyteArray android_os_Parcel_readBlob(JNIEnv* env, jclass clazz, jlong nativePtr)
344{
345 jbyteArray ret = NULL;
346
347 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
348 if (parcel != NULL) {
349 int32_t len = parcel->readInt32();
350 if (len >= 0) {
351 android::Parcel::ReadableBlob blob;
352 android::status_t err = parcel->readBlob(len, &blob);
353 if (err != NO_ERROR) {
354 signalExceptionForError(env, clazz, err);
355 return NULL;
356 }
357
358 ret = env->NewByteArray(len);
359 if (ret != NULL) {
360 jbyte* a2 = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
361 if (a2) {
362 memcpy(a2, blob.data(), len);
363 env->ReleasePrimitiveArrayCritical(ret, a2, 0);
364 }
365 }
366 blob.release();
367 }
368 }
369
370 return ret;
371}
372
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000373static jint android_os_Parcel_readInt(JNIEnv* env, jclass clazz, jlong nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800374{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800375 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800376 if (parcel != NULL) {
377 return parcel->readInt32();
378 }
379 return 0;
380}
381
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000382static jlong android_os_Parcel_readLong(JNIEnv* env, jclass clazz, jlong nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800383{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800384 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800385 if (parcel != NULL) {
386 return parcel->readInt64();
387 }
388 return 0;
389}
390
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000391static jfloat android_os_Parcel_readFloat(JNIEnv* env, jclass clazz, jlong nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800392{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800393 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800394 if (parcel != NULL) {
395 return parcel->readFloat();
396 }
397 return 0;
398}
399
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000400static jdouble android_os_Parcel_readDouble(JNIEnv* env, jclass clazz, jlong nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800401{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800402 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800403 if (parcel != NULL) {
404 return parcel->readDouble();
405 }
406 return 0;
407}
408
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000409static jstring android_os_Parcel_readString(JNIEnv* env, jclass clazz, jlong nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800410{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800411 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800412 if (parcel != NULL) {
413 size_t len;
414 const char16_t* str = parcel->readString16Inplace(&len);
415 if (str) {
Dan Albert66987492014-11-20 11:41:21 -0800416 return env->NewString(reinterpret_cast<const jchar*>(str), len);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800417 }
418 return NULL;
419 }
420 return NULL;
421}
422
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000423static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800424{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800425 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800426 if (parcel != NULL) {
427 return javaObjectForIBinder(env, parcel->readStrongBinder());
428 }
429 return NULL;
430}
431
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000432static jobject android_os_Parcel_readFileDescriptor(JNIEnv* env, jclass clazz, jlong nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800433{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800434 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800435 if (parcel != NULL) {
436 int fd = parcel->readFileDescriptor();
437 if (fd < 0) return NULL;
438 fd = dup(fd);
439 if (fd < 0) return NULL;
440 return jniCreateFileDescriptor(env, fd);
441 }
442 return NULL;
443}
444
Jeff Sharkey047238c2012-03-07 16:51:38 -0800445static jobject android_os_Parcel_openFileDescriptor(JNIEnv* env, jclass clazz,
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800446 jstring name, jint mode)
447{
448 if (name == NULL) {
449 jniThrowNullPointerException(env, NULL);
450 return NULL;
451 }
452 const jchar* str = env->GetStringCritical(name, 0);
453 if (str == NULL) {
454 // Whatever, whatever.
455 jniThrowException(env, "java/lang/IllegalStateException", NULL);
456 return NULL;
457 }
Dan Albert66987492014-11-20 11:41:21 -0800458 String8 name8(reinterpret_cast<const char16_t*>(str),
459 env->GetStringLength(name));
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800460 env->ReleaseStringCritical(name, str);
461 int flags=0;
462 switch (mode&0x30000000) {
463 case 0:
464 case 0x10000000:
465 flags = O_RDONLY;
466 break;
467 case 0x20000000:
468 flags = O_WRONLY;
469 break;
470 case 0x30000000:
471 flags = O_RDWR;
472 break;
473 }
474
475 if (mode&0x08000000) flags |= O_CREAT;
476 if (mode&0x04000000) flags |= O_TRUNC;
477 if (mode&0x02000000) flags |= O_APPEND;
478
479 int realMode = S_IRWXU|S_IRWXG;
480 if (mode&0x00000001) realMode |= S_IROTH;
481 if (mode&0x00000002) realMode |= S_IWOTH;
482
483 int fd = open(name8.string(), flags, realMode);
484 if (fd < 0) {
485 jniThrowException(env, "java/io/FileNotFoundException", strerror(errno));
486 return NULL;
487 }
488 jobject object = jniCreateFileDescriptor(env, fd);
489 if (object == NULL) {
490 close(fd);
491 }
492 return object;
493}
494
Jeff Sharkey047238c2012-03-07 16:51:38 -0800495static jobject android_os_Parcel_dupFileDescriptor(JNIEnv* env, jclass clazz, jobject orig)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800496{
497 if (orig == NULL) {
498 jniThrowNullPointerException(env, NULL);
499 return NULL;
500 }
501 int origfd = jniGetFDFromFileDescriptor(env, orig);
502 if (origfd < 0) {
503 jniThrowException(env, "java/lang/IllegalArgumentException", "bad FileDescriptor");
504 return NULL;
505 }
506
507 int fd = dup(origfd);
508 if (fd < 0) {
509 jniThrowIOException(env, errno);
510 return NULL;
511 }
512 jobject object = jniCreateFileDescriptor(env, fd);
513 if (object == NULL) {
514 close(fd);
515 }
516 return object;
517}
518
Jeff Sharkey047238c2012-03-07 16:51:38 -0800519static void android_os_Parcel_closeFileDescriptor(JNIEnv* env, jclass clazz, jobject object)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800520{
521 if (object == NULL) {
522 jniThrowNullPointerException(env, NULL);
523 return;
524 }
525 int fd = jniGetFDFromFileDescriptor(env, object);
526 if (fd >= 0) {
527 jniSetFileDescriptorOfFD(env, object, -1);
528 //ALOGI("Closing ParcelFileDescriptor %d\n", fd);
529 close(fd);
530 }
531}
532
Jeff Sharkey047238c2012-03-07 16:51:38 -0800533static void android_os_Parcel_clearFileDescriptor(JNIEnv* env, jclass clazz, jobject object)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800534{
535 if (object == NULL) {
536 jniThrowNullPointerException(env, NULL);
537 return;
538 }
539 int fd = jniGetFDFromFileDescriptor(env, object);
540 if (fd >= 0) {
541 jniSetFileDescriptorOfFD(env, object, -1);
542 }
543}
544
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000545static jlong android_os_Parcel_create(JNIEnv* env, jclass clazz)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800546{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800547 Parcel* parcel = new Parcel();
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000548 return reinterpret_cast<jlong>(parcel);
Jeff Sharkey047238c2012-03-07 16:51:38 -0800549}
550
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000551static void android_os_Parcel_freeBuffer(JNIEnv* env, jclass clazz, jlong nativePtr)
Jeff Sharkey047238c2012-03-07 16:51:38 -0800552{
553 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
554 if (parcel != NULL) {
555 parcel->freeData();
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800556 }
557}
558
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000559static void android_os_Parcel_destroy(JNIEnv* env, jclass clazz, jlong nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800560{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800561 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
562 delete parcel;
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800563}
564
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000565static jbyteArray android_os_Parcel_marshall(JNIEnv* env, jclass clazz, jlong nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800566{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800567 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800568 if (parcel == NULL) {
569 return NULL;
570 }
571
572 // do not marshall if there are binder objects in the parcel
573 if (parcel->objectsCount())
574 {
575 jniThrowException(env, "java/lang/RuntimeException", "Tried to marshall a Parcel that contained Binder objects.");
576 return NULL;
577 }
578
579 jbyteArray ret = env->NewByteArray(parcel->dataSize());
580
581 if (ret != NULL)
582 {
583 jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
584 if (array != NULL)
585 {
586 memcpy(array, parcel->data(), parcel->dataSize());
587 env->ReleasePrimitiveArrayCritical(ret, array, 0);
588 }
589 }
590
591 return ret;
592}
593
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000594static void android_os_Parcel_unmarshall(JNIEnv* env, jclass clazz, jlong nativePtr,
Jeff Sharkey047238c2012-03-07 16:51:38 -0800595 jbyteArray data, jint offset, jint length)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800596{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800597 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800598 if (parcel == NULL || length < 0) {
599 return;
600 }
601
602 jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(data, 0);
603 if (array)
604 {
605 parcel->setDataSize(length);
606 parcel->setDataPosition(0);
607
608 void* raw = parcel->writeInplace(length);
609 memcpy(raw, (array + offset), length);
610
611 env->ReleasePrimitiveArrayCritical(data, array, 0);
612 }
613}
614
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000615static void android_os_Parcel_appendFrom(JNIEnv* env, jclass clazz, jlong thisNativePtr,
616 jlong otherNativePtr, jint offset, jint length)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800617{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800618 Parcel* thisParcel = reinterpret_cast<Parcel*>(thisNativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800619 if (thisParcel == NULL) {
620 return;
621 }
Jeff Sharkey047238c2012-03-07 16:51:38 -0800622 Parcel* otherParcel = reinterpret_cast<Parcel*>(otherNativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800623 if (otherParcel == NULL) {
624 return;
625 }
626
627 status_t err = thisParcel->appendFrom(otherParcel, offset, length);
628 if (err != NO_ERROR) {
629 signalExceptionForError(env, clazz, err);
630 }
631}
632
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000633static jboolean android_os_Parcel_hasFileDescriptors(JNIEnv* env, jclass clazz, jlong nativePtr)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800634{
635 jboolean ret = JNI_FALSE;
Jeff Sharkey047238c2012-03-07 16:51:38 -0800636 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800637 if (parcel != NULL) {
638 if (parcel->hasFileDescriptors()) {
639 ret = JNI_TRUE;
640 }
641 }
642 return ret;
643}
644
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000645static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jclass clazz, jlong nativePtr,
Jeff Sharkey047238c2012-03-07 16:51:38 -0800646 jstring name)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800647{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800648 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800649 if (parcel != NULL) {
650 // In the current implementation, the token is just the serialized interface name that
651 // the caller expects to be invoking
652 const jchar* str = env->GetStringCritical(name, 0);
653 if (str != NULL) {
Dan Albert66987492014-11-20 11:41:21 -0800654 parcel->writeInterfaceToken(String16(
655 reinterpret_cast<const char16_t*>(str),
656 env->GetStringLength(name)));
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800657 env->ReleaseStringCritical(name, str);
658 }
659 }
660}
661
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000662static void android_os_Parcel_enforceInterface(JNIEnv* env, jclass clazz, jlong nativePtr, jstring name)
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800663{
Jeff Sharkey047238c2012-03-07 16:51:38 -0800664 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800665 if (parcel != NULL) {
666 const jchar* str = env->GetStringCritical(name, 0);
667 if (str) {
668 IPCThreadState* threadState = IPCThreadState::self();
669 const int32_t oldPolicy = threadState->getStrictModePolicy();
670 const bool isValid = parcel->enforceInterface(
Dan Albert66987492014-11-20 11:41:21 -0800671 String16(reinterpret_cast<const char16_t*>(str),
672 env->GetStringLength(name)),
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800673 threadState);
674 env->ReleaseStringCritical(name, str);
675 if (isValid) {
676 const int32_t newPolicy = threadState->getStrictModePolicy();
677 if (oldPolicy != newPolicy) {
678 // Need to keep the Java-level thread-local strict
679 // mode policy in sync for the libcore
680 // enforcements, which involves an upcall back
681 // into Java. (We can't modify the
682 // Parcel.enforceInterface signature, as it's
683 // pseudo-public, and used via AIDL
684 // auto-generation...)
685 set_dalvik_blockguard_policy(env, newPolicy);
686 }
687 return; // everything was correct -> return silently
688 }
689 }
690 }
691
692 // all error conditions wind up here
693 jniThrowException(env, "java/lang/SecurityException",
694 "Binder invocation to an incorrect interface");
695}
696
Dianne Hackbornfabb70b2014-11-11 12:22:36 -0800697static jlong android_os_Parcel_getGlobalAllocSize(JNIEnv* env, jclass clazz)
698{
699 return Parcel::getGlobalAllocSize();
700}
701
702static jlong android_os_Parcel_getGlobalAllocCount(JNIEnv* env, jclass clazz)
703{
704 return Parcel::getGlobalAllocCount();
705}
706
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800707// ----------------------------------------------------------------------------
708
709static const JNINativeMethod gParcelMethods[] = {
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000710 {"nativeDataSize", "(J)I", (void*)android_os_Parcel_dataSize},
711 {"nativeDataAvail", "(J)I", (void*)android_os_Parcel_dataAvail},
712 {"nativeDataPosition", "(J)I", (void*)android_os_Parcel_dataPosition},
713 {"nativeDataCapacity", "(J)I", (void*)android_os_Parcel_dataCapacity},
714 {"nativeSetDataSize", "(JI)V", (void*)android_os_Parcel_setDataSize},
715 {"nativeSetDataPosition", "(JI)V", (void*)android_os_Parcel_setDataPosition},
716 {"nativeSetDataCapacity", "(JI)V", (void*)android_os_Parcel_setDataCapacity},
Jeff Sharkey047238c2012-03-07 16:51:38 -0800717
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000718 {"nativePushAllowFds", "(JZ)Z", (void*)android_os_Parcel_pushAllowFds},
719 {"nativeRestoreAllowFds", "(JZ)V", (void*)android_os_Parcel_restoreAllowFds},
Jeff Sharkey047238c2012-03-07 16:51:38 -0800720
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000721 {"nativeWriteByteArray", "(J[BII)V", (void*)android_os_Parcel_writeNative},
Sandeep Siddhartha90d7a3e2014-07-25 16:19:42 -0700722 {"nativeWriteBlob", "(J[BII)V", (void*)android_os_Parcel_writeBlob},
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000723 {"nativeWriteInt", "(JI)V", (void*)android_os_Parcel_writeInt},
724 {"nativeWriteLong", "(JJ)V", (void*)android_os_Parcel_writeLong},
725 {"nativeWriteFloat", "(JF)V", (void*)android_os_Parcel_writeFloat},
726 {"nativeWriteDouble", "(JD)V", (void*)android_os_Parcel_writeDouble},
727 {"nativeWriteString", "(JLjava/lang/String;)V", (void*)android_os_Parcel_writeString},
728 {"nativeWriteStrongBinder", "(JLandroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder},
729 {"nativeWriteFileDescriptor", "(JLjava/io/FileDescriptor;)V", (void*)android_os_Parcel_writeFileDescriptor},
Jeff Sharkey047238c2012-03-07 16:51:38 -0800730
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000731 {"nativeCreateByteArray", "(J)[B", (void*)android_os_Parcel_createByteArray},
Sandeep Siddhartha90d7a3e2014-07-25 16:19:42 -0700732 {"nativeReadBlob", "(J)[B", (void*)android_os_Parcel_readBlob},
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000733 {"nativeReadInt", "(J)I", (void*)android_os_Parcel_readInt},
734 {"nativeReadLong", "(J)J", (void*)android_os_Parcel_readLong},
735 {"nativeReadFloat", "(J)F", (void*)android_os_Parcel_readFloat},
736 {"nativeReadDouble", "(J)D", (void*)android_os_Parcel_readDouble},
737 {"nativeReadString", "(J)Ljava/lang/String;", (void*)android_os_Parcel_readString},
738 {"nativeReadStrongBinder", "(J)Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder},
739 {"nativeReadFileDescriptor", "(J)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_readFileDescriptor},
Jeff Sharkey047238c2012-03-07 16:51:38 -0800740
741 {"openFileDescriptor", "(Ljava/lang/String;I)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_openFileDescriptor},
742 {"dupFileDescriptor", "(Ljava/io/FileDescriptor;)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_dupFileDescriptor},
743 {"closeFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_closeFileDescriptor},
744 {"clearFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_clearFileDescriptor},
745
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000746 {"nativeCreate", "()J", (void*)android_os_Parcel_create},
747 {"nativeFreeBuffer", "(J)V", (void*)android_os_Parcel_freeBuffer},
748 {"nativeDestroy", "(J)V", (void*)android_os_Parcel_destroy},
Jeff Sharkey047238c2012-03-07 16:51:38 -0800749
Ashok Bhat8ab665d2014-01-22 16:00:20 +0000750 {"nativeMarshall", "(J)[B", (void*)android_os_Parcel_marshall},
751 {"nativeUnmarshall", "(J[BII)V", (void*)android_os_Parcel_unmarshall},
752 {"nativeAppendFrom", "(JJII)V", (void*)android_os_Parcel_appendFrom},
753 {"nativeHasFileDescriptors", "(J)Z", (void*)android_os_Parcel_hasFileDescriptors},
754 {"nativeWriteInterfaceToken", "(JLjava/lang/String;)V", (void*)android_os_Parcel_writeInterfaceToken},
755 {"nativeEnforceInterface", "(JLjava/lang/String;)V", (void*)android_os_Parcel_enforceInterface},
Dianne Hackbornfabb70b2014-11-11 12:22:36 -0800756
757 {"getGlobalAllocSize", "()J", (void*)android_os_Parcel_getGlobalAllocSize},
758 {"getGlobalAllocCount", "()J", (void*)android_os_Parcel_getGlobalAllocCount},
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800759};
760
761const char* const kParcelPathName = "android/os/Parcel";
762
763int register_android_os_Parcel(JNIEnv* env)
764{
Andreas Gampe987f79f2014-11-18 17:29:46 -0800765 jclass clazz = FindClassOrDie(env, kParcelPathName);
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800766
Andreas Gampe987f79f2014-11-18 17:29:46 -0800767 gParcelOffsets.clazz = MakeGlobalRefOrDie(env, clazz);
768 gParcelOffsets.mNativePtr = GetFieldIDOrDie(env, clazz, "mNativePtr", "J");
769 gParcelOffsets.obtain = GetStaticMethodIDOrDie(env, clazz, "obtain", "()Landroid/os/Parcel;");
770 gParcelOffsets.recycle = GetMethodIDOrDie(env, clazz, "recycle", "()V");
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800771
Andreas Gampe987f79f2014-11-18 17:29:46 -0800772 return RegisterMethodsOrDie(env, kParcelPathName, gParcelMethods, NELEM(gParcelMethods));
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -0800773}
774
775};