summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Sharkey <jsharkey@android.com>2012-03-06 18:26:19 -0800
committerJeff Sharkey <jsharkey@android.com>2012-03-08 16:06:30 -0800
commitd84e1ce0b535128f03416145554fb405f9fade3e (patch)
tree545922d1256d7b320dd07b236955a902320f9d9c
parent21b4d6b7a5959b567355aae032bd76500c148e54 (diff)
downloadframeworks_base-d84e1ce0b535128f03416145554fb405f9fade3e.zip
frameworks_base-d84e1ce0b535128f03416145554fb405f9fade3e.tar.gz
frameworks_base-d84e1ce0b535128f03416145554fb405f9fade3e.tar.bz2
Split Parcel JNI details away from Binder.
This is purely a refactoring, with no change to the underlying functionality. Change-Id: I41b59f14e57d1cc144274a01f77658d99a1bfe02
-rw-r--r--core/jni/Android.mk1
-rw-r--r--core/jni/AndroidRuntime.cpp2
-rw-r--r--core/jni/android/graphics/Bitmap.cpp1
-rw-r--r--core/jni/android/graphics/Region.cpp1
-rw-r--r--core/jni/android_database_CursorWindow.cpp1
-rw-r--r--core/jni/android_os_Parcel.cpp701
-rw-r--r--core/jni/android_os_Parcel.h27
-rw-r--r--core/jni/android_util_Binder.cpp676
-rw-r--r--core/jni/android_util_Binder.h14
-rw-r--r--core/jni/android_view_InputChannel.cpp1
-rw-r--r--core/jni/android_view_MotionEvent.cpp1
-rw-r--r--media/jni/android_media_MediaPlayer.cpp1
12 files changed, 767 insertions, 660 deletions
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index c389cf7..642988b 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -64,6 +64,7 @@ LOCAL_SRC_FILES:= \
android_os_MemoryFile.cpp \
android_os_MessageQueue.cpp \
android_os_ParcelFileDescriptor.cpp \
+ android_os_Parcel.cpp \
android_os_Power.cpp \
android_os_StatFs.cpp \
android_os_SystemClock.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 3067e75..de9fd33 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -130,6 +130,7 @@ extern int register_android_nio_utils(JNIEnv* env);
extern int register_android_text_format_Time(JNIEnv* env);
extern int register_android_os_Debug(JNIEnv* env);
extern int register_android_os_MessageQueue(JNIEnv* env);
+extern int register_android_os_Parcel(JNIEnv* env);
extern int register_android_os_ParcelFileDescriptor(JNIEnv *env);
extern int register_android_os_Power(JNIEnv *env);
extern int register_android_os_StatFs(JNIEnv *env);
@@ -1094,6 +1095,7 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_os_Process),
REG_JNI(register_android_os_SystemProperties),
REG_JNI(register_android_os_Binder),
+ REG_JNI(register_android_os_Parcel),
REG_JNI(register_android_view_Display),
REG_JNI(register_android_view_DisplayEventReceiver),
REG_JNI(register_android_nio_utils),
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index d1d3b78..5e73a5f 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -7,6 +7,7 @@
#include "SkUnPreMultiply.h"
#include <binder/Parcel.h>
+#include "android_os_Parcel.h"
#include "android_util_Binder.h"
#include "android_nio_utils.h"
#include "CreateJavaOutputStreamAdaptor.h"
diff --git a/core/jni/android/graphics/Region.cpp b/core/jni/android/graphics/Region.cpp
index 5c6ebdf..866d223 100644
--- a/core/jni/android/graphics/Region.cpp
+++ b/core/jni/android/graphics/Region.cpp
@@ -19,6 +19,7 @@
#include "GraphicsJNI.h"
#include <binder/Parcel.h>
+#include "android_os_Parcel.h"
#include "android_util_Binder.h"
#include <jni.h>
diff --git a/core/jni/android_database_CursorWindow.cpp b/core/jni/android_database_CursorWindow.cpp
index 579d6ad..ea02f53 100644
--- a/core/jni/android_database_CursorWindow.cpp
+++ b/core/jni/android_database_CursorWindow.cpp
@@ -31,6 +31,7 @@
#include <unistd.h>
#include <androidfw/CursorWindow.h>
+#include "android_os_Parcel.h"
#include "android_util_Binder.h"
#include "android_database_SQLiteCommon.h"
diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp
new file mode 100644
index 0000000..8a99049
--- /dev/null
+++ b/core/jni/android_os_Parcel.cpp
@@ -0,0 +1,701 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Parcel"
+//#define LOG_NDEBUG 0
+
+#include "android_os_Parcel.h"
+#include "android_util_Binder.h"
+
+#include "JNIHelp.h"
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <utils/Atomic.h>
+#include <binder/IInterface.h>
+#include <binder/IPCThreadState.h>
+#include <utils/Log.h>
+#include <utils/SystemClock.h>
+#include <utils/List.h>
+#include <utils/KeyedVector.h>
+#include <cutils/logger.h>
+#include <binder/Parcel.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
+#include <utils/threads.h>
+#include <utils/String8.h>
+
+#include <ScopedUtfChars.h>
+#include <ScopedLocalRef.h>
+
+#include <android_runtime/AndroidRuntime.h>
+
+//#undef ALOGV
+//#define ALOGV(...) fprintf(stderr, __VA_ARGS__)
+
+#define DEBUG_DEATH 0
+#if DEBUG_DEATH
+#define LOGDEATH ALOGD
+#else
+#define LOGDEATH ALOGV
+#endif
+
+namespace android {
+
+static struct parcel_offsets_t
+{
+ jfieldID mObject;
+ jfieldID mOwnObject;
+} gParcelOffsets;
+
+Parcel* parcelForJavaObject(JNIEnv* env, jobject obj)
+{
+ if (obj) {
+ Parcel* p = (Parcel*)env->GetIntField(obj, gParcelOffsets.mObject);
+ if (p != NULL) {
+ return p;
+ }
+ jniThrowException(env, "java/lang/IllegalStateException", "Parcel has been finalized!");
+ }
+ return NULL;
+}
+
+static jint android_os_Parcel_dataSize(JNIEnv* env, jobject clazz)
+{
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ return parcel ? parcel->dataSize() : 0;
+}
+
+static jint android_os_Parcel_dataAvail(JNIEnv* env, jobject clazz)
+{
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ return parcel ? parcel->dataAvail() : 0;
+}
+
+static jint android_os_Parcel_dataPosition(JNIEnv* env, jobject clazz)
+{
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ return parcel ? parcel->dataPosition() : 0;
+}
+
+static jint android_os_Parcel_dataCapacity(JNIEnv* env, jobject clazz)
+{
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ return parcel ? parcel->dataCapacity() : 0;
+}
+
+static void android_os_Parcel_setDataSize(JNIEnv* env, jobject clazz, jint size)
+{
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ if (parcel != NULL) {
+ const status_t err = parcel->setDataSize(size);
+ if (err != NO_ERROR) {
+ signalExceptionForError(env, clazz, err);
+ }
+ }
+}
+
+static void android_os_Parcel_setDataPosition(JNIEnv* env, jobject clazz, jint pos)
+{
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ if (parcel != NULL) {
+ parcel->setDataPosition(pos);
+ }
+}
+
+static void android_os_Parcel_setDataCapacity(JNIEnv* env, jobject clazz, jint size)
+{
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ if (parcel != NULL) {
+ const status_t err = parcel->setDataCapacity(size);
+ if (err != NO_ERROR) {
+ signalExceptionForError(env, clazz, err);
+ }
+ }
+}
+
+static jboolean android_os_Parcel_pushAllowFds(JNIEnv* env, jobject clazz, jboolean allowFds)
+{
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ jboolean ret = JNI_TRUE;
+ if (parcel != NULL) {
+ ret = (jboolean)parcel->pushAllowFds(allowFds);
+ }
+ return ret;
+}
+
+static void android_os_Parcel_restoreAllowFds(JNIEnv* env, jobject clazz, jboolean lastValue)
+{
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ if (parcel != NULL) {
+ parcel->restoreAllowFds((bool)lastValue);
+ }
+}
+
+static void android_os_Parcel_writeNative(JNIEnv* env, jobject clazz,
+ jobject data, jint offset,
+ jint length)
+{
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ if (parcel == NULL) {
+ return;
+ }
+
+ const status_t err = parcel->writeInt32(length);
+ if (err != NO_ERROR) {
+ signalExceptionForError(env, clazz, err);
+ return;
+ }
+
+ void* dest = parcel->writeInplace(length);
+ if (dest == NULL) {
+ signalExceptionForError(env, clazz, NO_MEMORY);
+ return;
+ }
+
+ jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)data, 0);
+ if (ar) {
+ memcpy(dest, ar + offset, length);
+ env->ReleasePrimitiveArrayCritical((jarray)data, ar, 0);
+ }
+}
+
+
+static void android_os_Parcel_writeInt(JNIEnv* env, jobject clazz, jint val)
+{
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ if (parcel != NULL) {
+ const status_t err = parcel->writeInt32(val);
+ if (err != NO_ERROR) {
+ signalExceptionForError(env, clazz, err);
+ }
+ }
+}
+
+static void android_os_Parcel_writeLong(JNIEnv* env, jobject clazz, jlong val)
+{
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ if (parcel != NULL) {
+ const status_t err = parcel->writeInt64(val);
+ if (err != NO_ERROR) {
+ signalExceptionForError(env, clazz, err);
+ }
+ }
+}
+
+static void android_os_Parcel_writeFloat(JNIEnv* env, jobject clazz, jfloat val)
+{
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ if (parcel != NULL) {
+ const status_t err = parcel->writeFloat(val);
+ if (err != NO_ERROR) {
+ signalExceptionForError(env, clazz, err);
+ }
+ }
+}
+
+static void android_os_Parcel_writeDouble(JNIEnv* env, jobject clazz, jdouble val)
+{
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ if (parcel != NULL) {
+ const status_t err = parcel->writeDouble(val);
+ if (err != NO_ERROR) {
+ signalExceptionForError(env, clazz, err);
+ }
+ }
+}
+
+static void android_os_Parcel_writeString(JNIEnv* env, jobject clazz, jstring val)
+{
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ if (parcel != NULL) {
+ status_t err = NO_MEMORY;
+ if (val) {
+ const jchar* str = env->GetStringCritical(val, 0);
+ if (str) {
+ err = parcel->writeString16(str, env->GetStringLength(val));
+ env->ReleaseStringCritical(val, str);
+ }
+ } else {
+ err = parcel->writeString16(NULL, 0);
+ }
+ if (err != NO_ERROR) {
+ signalExceptionForError(env, clazz, err);
+ }
+ }
+}
+
+static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jobject clazz, jobject object)
+{
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ if (parcel != NULL) {
+ const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
+ if (err != NO_ERROR) {
+ signalExceptionForError(env, clazz, err);
+ }
+ }
+}
+
+static void android_os_Parcel_writeFileDescriptor(JNIEnv* env, jobject clazz, jobject object)
+{
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ if (parcel != NULL) {
+ const status_t err =
+ parcel->writeDupFileDescriptor(jniGetFDFromFileDescriptor(env, object));
+ if (err != NO_ERROR) {
+ signalExceptionForError(env, clazz, err);
+ }
+ }
+}
+
+static jbyteArray android_os_Parcel_createByteArray(JNIEnv* env, jobject clazz)
+{
+ jbyteArray ret = NULL;
+
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ if (parcel != NULL) {
+ int32_t len = parcel->readInt32();
+
+ // sanity check the stored length against the true data size
+ if (len >= 0 && len <= (int32_t)parcel->dataAvail()) {
+ ret = env->NewByteArray(len);
+
+ if (ret != NULL) {
+ jbyte* a2 = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
+ if (a2) {
+ const void* data = parcel->readInplace(len);
+ memcpy(a2, data, len);
+ env->ReleasePrimitiveArrayCritical(ret, a2, 0);
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+static jint android_os_Parcel_readInt(JNIEnv* env, jobject clazz)
+{
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ if (parcel != NULL) {
+ return parcel->readInt32();
+ }
+ return 0;
+}
+
+static jlong android_os_Parcel_readLong(JNIEnv* env, jobject clazz)
+{
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ if (parcel != NULL) {
+ return parcel->readInt64();
+ }
+ return 0;
+}
+
+static jfloat android_os_Parcel_readFloat(JNIEnv* env, jobject clazz)
+{
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ if (parcel != NULL) {
+ return parcel->readFloat();
+ }
+ return 0;
+}
+
+static jdouble android_os_Parcel_readDouble(JNIEnv* env, jobject clazz)
+{
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ if (parcel != NULL) {
+ return parcel->readDouble();
+ }
+ return 0;
+}
+
+static jstring android_os_Parcel_readString(JNIEnv* env, jobject clazz)
+{
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ if (parcel != NULL) {
+ size_t len;
+ const char16_t* str = parcel->readString16Inplace(&len);
+ if (str) {
+ return env->NewString(str, len);
+ }
+ return NULL;
+ }
+ return NULL;
+}
+
+static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jobject clazz)
+{
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ if (parcel != NULL) {
+ return javaObjectForIBinder(env, parcel->readStrongBinder());
+ }
+ return NULL;
+}
+
+static jobject android_os_Parcel_readFileDescriptor(JNIEnv* env, jobject clazz)
+{
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ if (parcel != NULL) {
+ int fd = parcel->readFileDescriptor();
+ if (fd < 0) return NULL;
+ fd = dup(fd);
+ if (fd < 0) return NULL;
+ return jniCreateFileDescriptor(env, fd);
+ }
+ return NULL;
+}
+
+static jobject android_os_Parcel_openFileDescriptor(JNIEnv* env, jobject clazz,
+ jstring name, jint mode)
+{
+ if (name == NULL) {
+ jniThrowNullPointerException(env, NULL);
+ return NULL;
+ }
+ const jchar* str = env->GetStringCritical(name, 0);
+ if (str == NULL) {
+ // Whatever, whatever.
+ jniThrowException(env, "java/lang/IllegalStateException", NULL);
+ return NULL;
+ }
+ String8 name8(str, env->GetStringLength(name));
+ env->ReleaseStringCritical(name, str);
+ int flags=0;
+ switch (mode&0x30000000) {
+ case 0:
+ case 0x10000000:
+ flags = O_RDONLY;
+ break;
+ case 0x20000000:
+ flags = O_WRONLY;
+ break;
+ case 0x30000000:
+ flags = O_RDWR;
+ break;
+ }
+
+ if (mode&0x08000000) flags |= O_CREAT;
+ if (mode&0x04000000) flags |= O_TRUNC;
+ if (mode&0x02000000) flags |= O_APPEND;
+
+ int realMode = S_IRWXU|S_IRWXG;
+ if (mode&0x00000001) realMode |= S_IROTH;
+ if (mode&0x00000002) realMode |= S_IWOTH;
+
+ int fd = open(name8.string(), flags, realMode);
+ if (fd < 0) {
+ jniThrowException(env, "java/io/FileNotFoundException", strerror(errno));
+ return NULL;
+ }
+ jobject object = jniCreateFileDescriptor(env, fd);
+ if (object == NULL) {
+ close(fd);
+ }
+ return object;
+}
+
+static jobject android_os_Parcel_dupFileDescriptor(JNIEnv* env, jobject clazz, jobject orig)
+{
+ if (orig == NULL) {
+ jniThrowNullPointerException(env, NULL);
+ return NULL;
+ }
+ int origfd = jniGetFDFromFileDescriptor(env, orig);
+ if (origfd < 0) {
+ jniThrowException(env, "java/lang/IllegalArgumentException", "bad FileDescriptor");
+ return NULL;
+ }
+
+ int fd = dup(origfd);
+ if (fd < 0) {
+ jniThrowIOException(env, errno);
+ return NULL;
+ }
+ jobject object = jniCreateFileDescriptor(env, fd);
+ if (object == NULL) {
+ close(fd);
+ }
+ return object;
+}
+
+static void android_os_Parcel_closeFileDescriptor(JNIEnv* env, jobject clazz, jobject object)
+{
+ if (object == NULL) {
+ jniThrowNullPointerException(env, NULL);
+ return;
+ }
+ int fd = jniGetFDFromFileDescriptor(env, object);
+ if (fd >= 0) {
+ jniSetFileDescriptorOfFD(env, object, -1);
+ //ALOGI("Closing ParcelFileDescriptor %d\n", fd);
+ close(fd);
+ }
+}
+
+static void android_os_Parcel_clearFileDescriptor(JNIEnv* env, jobject clazz, jobject object)
+{
+ if (object == NULL) {
+ jniThrowNullPointerException(env, NULL);
+ return;
+ }
+ int fd = jniGetFDFromFileDescriptor(env, object);
+ if (fd >= 0) {
+ jniSetFileDescriptorOfFD(env, object, -1);
+ }
+}
+
+static void android_os_Parcel_freeBuffer(JNIEnv* env, jobject clazz)
+{
+ int32_t own = env->GetIntField(clazz, gParcelOffsets.mOwnObject);
+ if (own) {
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ if (parcel != NULL) {
+ //ALOGI("Parcel.freeBuffer() called for C++ Parcel %p\n", parcel);
+ parcel->freeData();
+ }
+ }
+}
+
+static void android_os_Parcel_init(JNIEnv* env, jobject clazz, jint parcelInt)
+{
+ Parcel* parcel = (Parcel*)parcelInt;
+ int own = 0;
+ if (!parcel) {
+ //ALOGI("Initializing obj %p: creating new Parcel\n", clazz);
+ own = 1;
+ parcel = new Parcel;
+ } else {
+ //ALOGI("Initializing obj %p: given existing Parcel %p\n", clazz, parcel);
+ }
+ if (parcel == NULL) {
+ jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+ return;
+ }
+ //ALOGI("Initializing obj %p from C++ Parcel %p, own=%d\n", clazz, parcel, own);
+ env->SetIntField(clazz, gParcelOffsets.mOwnObject, own);
+ env->SetIntField(clazz, gParcelOffsets.mObject, (int)parcel);
+}
+
+static void android_os_Parcel_destroy(JNIEnv* env, jobject clazz)
+{
+ int32_t own = env->GetIntField(clazz, gParcelOffsets.mOwnObject);
+ if (own) {
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ env->SetIntField(clazz, gParcelOffsets.mObject, 0);
+ //ALOGI("Destroying obj %p: deleting C++ Parcel %p\n", clazz, parcel);
+ delete parcel;
+ } else {
+ env->SetIntField(clazz, gParcelOffsets.mObject, 0);
+ //ALOGI("Destroying obj %p: leaving C++ Parcel %p\n", clazz);
+ }
+}
+
+static jbyteArray android_os_Parcel_marshall(JNIEnv* env, jobject clazz)
+{
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ if (parcel == NULL) {
+ return NULL;
+ }
+
+ // do not marshall if there are binder objects in the parcel
+ if (parcel->objectsCount())
+ {
+ jniThrowException(env, "java/lang/RuntimeException", "Tried to marshall a Parcel that contained Binder objects.");
+ return NULL;
+ }
+
+ jbyteArray ret = env->NewByteArray(parcel->dataSize());
+
+ if (ret != NULL)
+ {
+ jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
+ if (array != NULL)
+ {
+ memcpy(array, parcel->data(), parcel->dataSize());
+ env->ReleasePrimitiveArrayCritical(ret, array, 0);
+ }
+ }
+
+ return ret;
+}
+
+static void android_os_Parcel_unmarshall(JNIEnv* env, jobject clazz, jbyteArray data, jint offset, jint length)
+{
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ if (parcel == NULL || length < 0) {
+ return;
+ }
+
+ jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(data, 0);
+ if (array)
+ {
+ parcel->setDataSize(length);
+ parcel->setDataPosition(0);
+
+ void* raw = parcel->writeInplace(length);
+ memcpy(raw, (array + offset), length);
+
+ env->ReleasePrimitiveArrayCritical(data, array, 0);
+ }
+}
+
+static void android_os_Parcel_appendFrom(JNIEnv* env, jobject clazz, jobject parcel, jint offset, jint length)
+{
+ Parcel* thisParcel = parcelForJavaObject(env, clazz);
+ if (thisParcel == NULL) {
+ return;
+ }
+ Parcel* otherParcel = parcelForJavaObject(env, parcel);
+ if (otherParcel == NULL) {
+ return;
+ }
+
+ status_t err = thisParcel->appendFrom(otherParcel, offset, length);
+ if (err != NO_ERROR) {
+ signalExceptionForError(env, clazz, err);
+ }
+}
+
+static jboolean android_os_Parcel_hasFileDescriptors(JNIEnv* env, jobject clazz)
+{
+ jboolean ret = JNI_FALSE;
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ if (parcel != NULL) {
+ if (parcel->hasFileDescriptors()) {
+ ret = JNI_TRUE;
+ }
+ }
+ return ret;
+}
+
+static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jobject clazz, jstring name)
+{
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ if (parcel != NULL) {
+ // In the current implementation, the token is just the serialized interface name that
+ // the caller expects to be invoking
+ const jchar* str = env->GetStringCritical(name, 0);
+ if (str != NULL) {
+ parcel->writeInterfaceToken(String16(str, env->GetStringLength(name)));
+ env->ReleaseStringCritical(name, str);
+ }
+ }
+}
+
+static void android_os_Parcel_enforceInterface(JNIEnv* env, jobject clazz, jstring name)
+{
+ jboolean ret = JNI_FALSE;
+
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ if (parcel != NULL) {
+ const jchar* str = env->GetStringCritical(name, 0);
+ if (str) {
+ IPCThreadState* threadState = IPCThreadState::self();
+ const int32_t oldPolicy = threadState->getStrictModePolicy();
+ const bool isValid = parcel->enforceInterface(
+ String16(str, env->GetStringLength(name)),
+ threadState);
+ env->ReleaseStringCritical(name, str);
+ if (isValid) {
+ const int32_t newPolicy = threadState->getStrictModePolicy();
+ if (oldPolicy != newPolicy) {
+ // Need to keep the Java-level thread-local strict
+ // mode policy in sync for the libcore
+ // enforcements, which involves an upcall back
+ // into Java. (We can't modify the
+ // Parcel.enforceInterface signature, as it's
+ // pseudo-public, and used via AIDL
+ // auto-generation...)
+ set_dalvik_blockguard_policy(env, newPolicy);
+ }
+ return; // everything was correct -> return silently
+ }
+ }
+ }
+
+ // all error conditions wind up here
+ jniThrowException(env, "java/lang/SecurityException",
+ "Binder invocation to an incorrect interface");
+}
+
+// ----------------------------------------------------------------------------
+
+static const JNINativeMethod gParcelMethods[] = {
+ {"dataSize", "()I", (void*)android_os_Parcel_dataSize},
+ {"dataAvail", "()I", (void*)android_os_Parcel_dataAvail},
+ {"dataPosition", "()I", (void*)android_os_Parcel_dataPosition},
+ {"dataCapacity", "()I", (void*)android_os_Parcel_dataCapacity},
+ {"setDataSize", "(I)V", (void*)android_os_Parcel_setDataSize},
+ {"setDataPosition", "(I)V", (void*)android_os_Parcel_setDataPosition},
+ {"setDataCapacity", "(I)V", (void*)android_os_Parcel_setDataCapacity},
+ {"pushAllowFds", "(Z)Z", (void*)android_os_Parcel_pushAllowFds},
+ {"restoreAllowFds", "(Z)V", (void*)android_os_Parcel_restoreAllowFds},
+ {"writeNative", "([BII)V", (void*)android_os_Parcel_writeNative},
+ {"writeInt", "(I)V", (void*)android_os_Parcel_writeInt},
+ {"writeLong", "(J)V", (void*)android_os_Parcel_writeLong},
+ {"writeFloat", "(F)V", (void*)android_os_Parcel_writeFloat},
+ {"writeDouble", "(D)V", (void*)android_os_Parcel_writeDouble},
+ {"writeString", "(Ljava/lang/String;)V", (void*)android_os_Parcel_writeString},
+ {"writeStrongBinder", "(Landroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder},
+ {"writeFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_writeFileDescriptor},
+ {"createByteArray", "()[B", (void*)android_os_Parcel_createByteArray},
+ {"readInt", "()I", (void*)android_os_Parcel_readInt},
+ {"readLong", "()J", (void*)android_os_Parcel_readLong},
+ {"readFloat", "()F", (void*)android_os_Parcel_readFloat},
+ {"readDouble", "()D", (void*)android_os_Parcel_readDouble},
+ {"readString", "()Ljava/lang/String;", (void*)android_os_Parcel_readString},
+ {"readStrongBinder", "()Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder},
+ {"internalReadFileDescriptor", "()Ljava/io/FileDescriptor;", (void*)android_os_Parcel_readFileDescriptor},
+ {"openFileDescriptor", "(Ljava/lang/String;I)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_openFileDescriptor},
+ {"dupFileDescriptor", "(Ljava/io/FileDescriptor;)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_dupFileDescriptor},
+ {"closeFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_closeFileDescriptor},
+ {"clearFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_clearFileDescriptor},
+ {"freeBuffer", "()V", (void*)android_os_Parcel_freeBuffer},
+ {"init", "(I)V", (void*)android_os_Parcel_init},
+ {"destroy", "()V", (void*)android_os_Parcel_destroy},
+ {"marshall", "()[B", (void*)android_os_Parcel_marshall},
+ {"unmarshall", "([BII)V", (void*)android_os_Parcel_unmarshall},
+ {"appendFrom", "(Landroid/os/Parcel;II)V", (void*)android_os_Parcel_appendFrom},
+ {"hasFileDescriptors", "()Z", (void*)android_os_Parcel_hasFileDescriptors},
+ {"writeInterfaceToken", "(Ljava/lang/String;)V", (void*)android_os_Parcel_writeInterfaceToken},
+ {"enforceInterface", "(Ljava/lang/String;)V", (void*)android_os_Parcel_enforceInterface},
+};
+
+const char* const kParcelPathName = "android/os/Parcel";
+
+int register_android_os_Parcel(JNIEnv* env)
+{
+ jclass clazz;
+
+ clazz = env->FindClass(kParcelPathName);
+ LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Parcel");
+
+ gParcelOffsets.mObject
+ = env->GetFieldID(clazz, "mObject", "I");
+ gParcelOffsets.mOwnObject
+ = env->GetFieldID(clazz, "mOwnObject", "I");
+
+ return AndroidRuntime::registerNativeMethods(
+ env, kParcelPathName,
+ gParcelMethods, NELEM(gParcelMethods));
+}
+
+};
diff --git a/core/jni/android_os_Parcel.h b/core/jni/android_os_Parcel.h
new file mode 100644
index 0000000..65f3819
--- /dev/null
+++ b/core/jni/android_os_Parcel.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <binder/IBinder.h>
+
+#include "jni.h"
+
+namespace android {
+
+// Conversion from Java Parcel Object to C++ Parcel instance.
+// Note: does not type checking; must guarantee jobject is a Java Parcel
+extern Parcel* parcelForJavaObject(JNIEnv* env, jobject obj);
+
+}
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index e00970a..0f99fb2 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -17,7 +17,9 @@
#define LOG_TAG "JavaBinder"
//#define LOG_NDEBUG 0
+#include "android_os_Parcel.h"
#include "android_util_Binder.h"
+
#include "JNIHelp.h"
#include <fcntl.h>
@@ -127,12 +129,6 @@ static struct class_offsets_t
// ----------------------------------------------------------------------------
-static struct parcel_offsets_t
-{
- jfieldID mObject;
- jfieldID mOwnObject;
-} gParcelOffsets;
-
static struct log_offsets_t
{
// Class state.
@@ -232,15 +228,6 @@ bail:
env->DeleteLocalRef(msgstr);
}
-static void set_dalvik_blockguard_policy(JNIEnv* env, jint strict_policy)
-{
- // Call back into android.os.StrictMode#onBinderStrictModePolicyChange
- // to sync our state back to it. See the comments in StrictMode.java.
- env->CallStaticVoidMethod(gStrictModeCallbackOffsets.mClass,
- gStrictModeCallbackOffsets.mCallback,
- strict_policy);
-}
-
class JavaBBinderHolder;
class JavaBBinder : public BBinder
@@ -634,26 +621,23 @@ sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
return NULL;
}
-Parcel* parcelForJavaObject(JNIEnv* env, jobject obj)
-{
- if (obj) {
- Parcel* p = (Parcel*)env->GetIntField(obj, gParcelOffsets.mObject);
- if (p != NULL) {
- return p;
- }
- jniThrowException(env, "java/lang/IllegalStateException", "Parcel has been finalized!");
- }
- return NULL;
-}
-
jobject newParcelFileDescriptor(JNIEnv* env, jobject fileDesc)
{
return env->NewObject(
gParcelFileDescriptorOffsets.mClass, gParcelFileDescriptorOffsets.mConstructor, fileDesc);
}
-static void signalExceptionForError(JNIEnv* env, jobject obj, status_t err,
- bool canThrowRemoteException = false)
+void set_dalvik_blockguard_policy(JNIEnv* env, jint strict_policy)
+{
+ // Call back into android.os.StrictMode#onBinderStrictModePolicyChange
+ // to sync our state back to it. See the comments in StrictMode.java.
+ env->CallStaticVoidMethod(gStrictModeCallbackOffsets.mClass,
+ gStrictModeCallbackOffsets.mCallback,
+ strict_policy);
+}
+
+void signalExceptionForError(JNIEnv* env, jobject obj, status_t err,
+ bool canThrowRemoteException)
{
switch (err) {
case UNKNOWN_ERROR:
@@ -1273,612 +1257,15 @@ static int int_register_android_os_BinderProxy(JNIEnv* env)
// ****************************************************************************
// ****************************************************************************
-static jint android_os_Parcel_dataSize(JNIEnv* env, jobject clazz)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- return parcel ? parcel->dataSize() : 0;
-}
-
-static jint android_os_Parcel_dataAvail(JNIEnv* env, jobject clazz)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- return parcel ? parcel->dataAvail() : 0;
-}
-
-static jint android_os_Parcel_dataPosition(JNIEnv* env, jobject clazz)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- return parcel ? parcel->dataPosition() : 0;
-}
-
-static jint android_os_Parcel_dataCapacity(JNIEnv* env, jobject clazz)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- return parcel ? parcel->dataCapacity() : 0;
-}
-
-static void android_os_Parcel_setDataSize(JNIEnv* env, jobject clazz, jint size)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- const status_t err = parcel->setDataSize(size);
- if (err != NO_ERROR) {
- signalExceptionForError(env, clazz, err);
- }
- }
-}
-
-static void android_os_Parcel_setDataPosition(JNIEnv* env, jobject clazz, jint pos)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- parcel->setDataPosition(pos);
- }
-}
-
-static void android_os_Parcel_setDataCapacity(JNIEnv* env, jobject clazz, jint size)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- const status_t err = parcel->setDataCapacity(size);
- if (err != NO_ERROR) {
- signalExceptionForError(env, clazz, err);
- }
- }
-}
-
-static jboolean android_os_Parcel_pushAllowFds(JNIEnv* env, jobject clazz, jboolean allowFds)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- jboolean ret = JNI_TRUE;
- if (parcel != NULL) {
- ret = (jboolean)parcel->pushAllowFds(allowFds);
- }
- return ret;
-}
-
-static void android_os_Parcel_restoreAllowFds(JNIEnv* env, jobject clazz, jboolean lastValue)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- parcel->restoreAllowFds((bool)lastValue);
- }
-}
-
-static void android_os_Parcel_writeNative(JNIEnv* env, jobject clazz,
- jobject data, jint offset,
- jint length)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel == NULL) {
- return;
- }
-
- const status_t err = parcel->writeInt32(length);
- if (err != NO_ERROR) {
- signalExceptionForError(env, clazz, err);
- return;
- }
-
- void* dest = parcel->writeInplace(length);
- if (dest == NULL) {
- signalExceptionForError(env, clazz, NO_MEMORY);
- return;
- }
-
- jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)data, 0);
- if (ar) {
- memcpy(dest, ar + offset, length);
- env->ReleasePrimitiveArrayCritical((jarray)data, ar, 0);
- }
-}
-
-
-static void android_os_Parcel_writeInt(JNIEnv* env, jobject clazz, jint val)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- const status_t err = parcel->writeInt32(val);
- if (err != NO_ERROR) {
- signalExceptionForError(env, clazz, err);
- }
- }
-}
-
-static void android_os_Parcel_writeLong(JNIEnv* env, jobject clazz, jlong val)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- const status_t err = parcel->writeInt64(val);
- if (err != NO_ERROR) {
- signalExceptionForError(env, clazz, err);
- }
- }
-}
-
-static void android_os_Parcel_writeFloat(JNIEnv* env, jobject clazz, jfloat val)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- const status_t err = parcel->writeFloat(val);
- if (err != NO_ERROR) {
- signalExceptionForError(env, clazz, err);
- }
- }
-}
-
-static void android_os_Parcel_writeDouble(JNIEnv* env, jobject clazz, jdouble val)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- const status_t err = parcel->writeDouble(val);
- if (err != NO_ERROR) {
- signalExceptionForError(env, clazz, err);
- }
- }
-}
-
-static void android_os_Parcel_writeString(JNIEnv* env, jobject clazz, jstring val)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- status_t err = NO_MEMORY;
- if (val) {
- const jchar* str = env->GetStringCritical(val, 0);
- if (str) {
- err = parcel->writeString16(str, env->GetStringLength(val));
- env->ReleaseStringCritical(val, str);
- }
- } else {
- err = parcel->writeString16(NULL, 0);
- }
- if (err != NO_ERROR) {
- signalExceptionForError(env, clazz, err);
- }
- }
-}
-
-static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jobject clazz, jobject object)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
- if (err != NO_ERROR) {
- signalExceptionForError(env, clazz, err);
- }
- }
-}
-
-static void android_os_Parcel_writeFileDescriptor(JNIEnv* env, jobject clazz, jobject object)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- const status_t err =
- parcel->writeDupFileDescriptor(jniGetFDFromFileDescriptor(env, object));
- if (err != NO_ERROR) {
- signalExceptionForError(env, clazz, err);
- }
- }
-}
-
-static jbyteArray android_os_Parcel_createByteArray(JNIEnv* env, jobject clazz)
-{
- jbyteArray ret = NULL;
-
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- int32_t len = parcel->readInt32();
-
- // sanity check the stored length against the true data size
- if (len >= 0 && len <= (int32_t)parcel->dataAvail()) {
- ret = env->NewByteArray(len);
-
- if (ret != NULL) {
- jbyte* a2 = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
- if (a2) {
- const void* data = parcel->readInplace(len);
- memcpy(a2, data, len);
- env->ReleasePrimitiveArrayCritical(ret, a2, 0);
- }
- }
- }
- }
-
- return ret;
-}
-
-static jint android_os_Parcel_readInt(JNIEnv* env, jobject clazz)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- return parcel->readInt32();
- }
- return 0;
-}
-
-static jlong android_os_Parcel_readLong(JNIEnv* env, jobject clazz)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- return parcel->readInt64();
- }
- return 0;
-}
-
-static jfloat android_os_Parcel_readFloat(JNIEnv* env, jobject clazz)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- return parcel->readFloat();
- }
- return 0;
-}
-
-static jdouble android_os_Parcel_readDouble(JNIEnv* env, jobject clazz)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- return parcel->readDouble();
- }
- return 0;
-}
-
-static jstring android_os_Parcel_readString(JNIEnv* env, jobject clazz)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- size_t len;
- const char16_t* str = parcel->readString16Inplace(&len);
- if (str) {
- return env->NewString(str, len);
- }
- return NULL;
- }
- return NULL;
-}
-
-static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jobject clazz)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- return javaObjectForIBinder(env, parcel->readStrongBinder());
- }
- return NULL;
-}
-
-static jobject android_os_Parcel_readFileDescriptor(JNIEnv* env, jobject clazz)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- int fd = parcel->readFileDescriptor();
- if (fd < 0) return NULL;
- fd = dup(fd);
- if (fd < 0) return NULL;
- return jniCreateFileDescriptor(env, fd);
- }
- return NULL;
-}
-
-static jobject android_os_Parcel_openFileDescriptor(JNIEnv* env, jobject clazz,
- jstring name, jint mode)
-{
- if (name == NULL) {
- jniThrowNullPointerException(env, NULL);
- return NULL;
- }
- const jchar* str = env->GetStringCritical(name, 0);
- if (str == NULL) {
- // Whatever, whatever.
- jniThrowException(env, "java/lang/IllegalStateException", NULL);
- return NULL;
- }
- String8 name8(str, env->GetStringLength(name));
- env->ReleaseStringCritical(name, str);
- int flags=0;
- switch (mode&0x30000000) {
- case 0:
- case 0x10000000:
- flags = O_RDONLY;
- break;
- case 0x20000000:
- flags = O_WRONLY;
- break;
- case 0x30000000:
- flags = O_RDWR;
- break;
- }
-
- if (mode&0x08000000) flags |= O_CREAT;
- if (mode&0x04000000) flags |= O_TRUNC;
- if (mode&0x02000000) flags |= O_APPEND;
-
- int realMode = S_IRWXU|S_IRWXG;
- if (mode&0x00000001) realMode |= S_IROTH;
- if (mode&0x00000002) realMode |= S_IWOTH;
-
- int fd = open(name8.string(), flags, realMode);
- if (fd < 0) {
- jniThrowException(env, "java/io/FileNotFoundException", strerror(errno));
- return NULL;
- }
- jobject object = jniCreateFileDescriptor(env, fd);
- if (object == NULL) {
- close(fd);
- }
- return object;
-}
-
-static jobject android_os_Parcel_dupFileDescriptor(JNIEnv* env, jobject clazz, jobject orig)
-{
- if (orig == NULL) {
- jniThrowNullPointerException(env, NULL);
- return NULL;
- }
- int origfd = jniGetFDFromFileDescriptor(env, orig);
- if (origfd < 0) {
- jniThrowException(env, "java/lang/IllegalArgumentException", "bad FileDescriptor");
- return NULL;
- }
-
- int fd = dup(origfd);
- if (fd < 0) {
- jniThrowIOException(env, errno);
- return NULL;
- }
- jobject object = jniCreateFileDescriptor(env, fd);
- if (object == NULL) {
- close(fd);
- }
- return object;
-}
-
-static void android_os_Parcel_closeFileDescriptor(JNIEnv* env, jobject clazz, jobject object)
-{
- if (object == NULL) {
- jniThrowNullPointerException(env, NULL);
- return;
- }
- int fd = jniGetFDFromFileDescriptor(env, object);
- if (fd >= 0) {
- jniSetFileDescriptorOfFD(env, object, -1);
- //ALOGI("Closing ParcelFileDescriptor %d\n", fd);
- close(fd);
- }
-}
-
-static void android_os_Parcel_clearFileDescriptor(JNIEnv* env, jobject clazz, jobject object)
-{
- if (object == NULL) {
- jniThrowNullPointerException(env, NULL);
- return;
- }
- int fd = jniGetFDFromFileDescriptor(env, object);
- if (fd >= 0) {
- jniSetFileDescriptorOfFD(env, object, -1);
- }
-}
-
-static void android_os_Parcel_freeBuffer(JNIEnv* env, jobject clazz)
-{
- int32_t own = env->GetIntField(clazz, gParcelOffsets.mOwnObject);
- if (own) {
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- //ALOGI("Parcel.freeBuffer() called for C++ Parcel %p\n", parcel);
- parcel->freeData();
- }
- }
-}
-
-static void android_os_Parcel_init(JNIEnv* env, jobject clazz, jint parcelInt)
-{
- Parcel* parcel = (Parcel*)parcelInt;
- int own = 0;
- if (!parcel) {
- //ALOGI("Initializing obj %p: creating new Parcel\n", clazz);
- own = 1;
- parcel = new Parcel;
- } else {
- //ALOGI("Initializing obj %p: given existing Parcel %p\n", clazz, parcel);
- }
- if (parcel == NULL) {
- jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
- return;
- }
- //ALOGI("Initializing obj %p from C++ Parcel %p, own=%d\n", clazz, parcel, own);
- env->SetIntField(clazz, gParcelOffsets.mOwnObject, own);
- env->SetIntField(clazz, gParcelOffsets.mObject, (int)parcel);
-}
-
-static void android_os_Parcel_destroy(JNIEnv* env, jobject clazz)
-{
- int32_t own = env->GetIntField(clazz, gParcelOffsets.mOwnObject);
- if (own) {
- Parcel* parcel = parcelForJavaObject(env, clazz);
- env->SetIntField(clazz, gParcelOffsets.mObject, 0);
- //ALOGI("Destroying obj %p: deleting C++ Parcel %p\n", clazz, parcel);
- delete parcel;
- } else {
- env->SetIntField(clazz, gParcelOffsets.mObject, 0);
- //ALOGI("Destroying obj %p: leaving C++ Parcel %p\n", clazz);
- }
-}
-
-static jbyteArray android_os_Parcel_marshall(JNIEnv* env, jobject clazz)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel == NULL) {
- return NULL;
- }
-
- // do not marshall if there are binder objects in the parcel
- if (parcel->objectsCount())
- {
- jniThrowException(env, "java/lang/RuntimeException", "Tried to marshall a Parcel that contained Binder objects.");
- return NULL;
- }
-
- jbyteArray ret = env->NewByteArray(parcel->dataSize());
-
- if (ret != NULL)
- {
- jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
- if (array != NULL)
- {
- memcpy(array, parcel->data(), parcel->dataSize());
- env->ReleasePrimitiveArrayCritical(ret, array, 0);
- }
- }
-
- return ret;
-}
-
-static void android_os_Parcel_unmarshall(JNIEnv* env, jobject clazz, jbyteArray data, jint offset, jint length)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel == NULL || length < 0) {
- return;
- }
-
- jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(data, 0);
- if (array)
- {
- parcel->setDataSize(length);
- parcel->setDataPosition(0);
-
- void* raw = parcel->writeInplace(length);
- memcpy(raw, (array + offset), length);
-
- env->ReleasePrimitiveArrayCritical(data, array, 0);
- }
-}
-
-static void android_os_Parcel_appendFrom(JNIEnv* env, jobject clazz, jobject parcel, jint offset, jint length)
-{
- Parcel* thisParcel = parcelForJavaObject(env, clazz);
- if (thisParcel == NULL) {
- return;
- }
- Parcel* otherParcel = parcelForJavaObject(env, parcel);
- if (otherParcel == NULL) {
- return;
- }
-
- status_t err = thisParcel->appendFrom(otherParcel, offset, length);
- if (err != NO_ERROR) {
- signalExceptionForError(env, clazz, err);
- }
-}
-
-static jboolean android_os_Parcel_hasFileDescriptors(JNIEnv* env, jobject clazz)
-{
- jboolean ret = JNI_FALSE;
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- if (parcel->hasFileDescriptors()) {
- ret = JNI_TRUE;
- }
- }
- return ret;
-}
-
-static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jobject clazz, jstring name)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- // In the current implementation, the token is just the serialized interface name that
- // the caller expects to be invoking
- const jchar* str = env->GetStringCritical(name, 0);
- if (str != NULL) {
- parcel->writeInterfaceToken(String16(str, env->GetStringLength(name)));
- env->ReleaseStringCritical(name, str);
- }
- }
-}
-
-static void android_os_Parcel_enforceInterface(JNIEnv* env, jobject clazz, jstring name)
+int register_android_os_Binder(JNIEnv* env)
{
- jboolean ret = JNI_FALSE;
-
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- const jchar* str = env->GetStringCritical(name, 0);
- if (str) {
- IPCThreadState* threadState = IPCThreadState::self();
- const int32_t oldPolicy = threadState->getStrictModePolicy();
- const bool isValid = parcel->enforceInterface(
- String16(str, env->GetStringLength(name)),
- threadState);
- env->ReleaseStringCritical(name, str);
- if (isValid) {
- const int32_t newPolicy = threadState->getStrictModePolicy();
- if (oldPolicy != newPolicy) {
- // Need to keep the Java-level thread-local strict
- // mode policy in sync for the libcore
- // enforcements, which involves an upcall back
- // into Java. (We can't modify the
- // Parcel.enforceInterface signature, as it's
- // pseudo-public, and used via AIDL
- // auto-generation...)
- set_dalvik_blockguard_policy(env, newPolicy);
- }
- return; // everything was correct -> return silently
- }
- }
- }
-
- // all error conditions wind up here
- jniThrowException(env, "java/lang/SecurityException",
- "Binder invocation to an incorrect interface");
-}
-
-// ----------------------------------------------------------------------------
-
-static const JNINativeMethod gParcelMethods[] = {
- {"dataSize", "()I", (void*)android_os_Parcel_dataSize},
- {"dataAvail", "()I", (void*)android_os_Parcel_dataAvail},
- {"dataPosition", "()I", (void*)android_os_Parcel_dataPosition},
- {"dataCapacity", "()I", (void*)android_os_Parcel_dataCapacity},
- {"setDataSize", "(I)V", (void*)android_os_Parcel_setDataSize},
- {"setDataPosition", "(I)V", (void*)android_os_Parcel_setDataPosition},
- {"setDataCapacity", "(I)V", (void*)android_os_Parcel_setDataCapacity},
- {"pushAllowFds", "(Z)Z", (void*)android_os_Parcel_pushAllowFds},
- {"restoreAllowFds", "(Z)V", (void*)android_os_Parcel_restoreAllowFds},
- {"writeNative", "([BII)V", (void*)android_os_Parcel_writeNative},
- {"writeInt", "(I)V", (void*)android_os_Parcel_writeInt},
- {"writeLong", "(J)V", (void*)android_os_Parcel_writeLong},
- {"writeFloat", "(F)V", (void*)android_os_Parcel_writeFloat},
- {"writeDouble", "(D)V", (void*)android_os_Parcel_writeDouble},
- {"writeString", "(Ljava/lang/String;)V", (void*)android_os_Parcel_writeString},
- {"writeStrongBinder", "(Landroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder},
- {"writeFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_writeFileDescriptor},
- {"createByteArray", "()[B", (void*)android_os_Parcel_createByteArray},
- {"readInt", "()I", (void*)android_os_Parcel_readInt},
- {"readLong", "()J", (void*)android_os_Parcel_readLong},
- {"readFloat", "()F", (void*)android_os_Parcel_readFloat},
- {"readDouble", "()D", (void*)android_os_Parcel_readDouble},
- {"readString", "()Ljava/lang/String;", (void*)android_os_Parcel_readString},
- {"readStrongBinder", "()Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder},
- {"internalReadFileDescriptor", "()Ljava/io/FileDescriptor;", (void*)android_os_Parcel_readFileDescriptor},
- {"openFileDescriptor", "(Ljava/lang/String;I)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_openFileDescriptor},
- {"dupFileDescriptor", "(Ljava/io/FileDescriptor;)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_dupFileDescriptor},
- {"closeFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_closeFileDescriptor},
- {"clearFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_clearFileDescriptor},
- {"freeBuffer", "()V", (void*)android_os_Parcel_freeBuffer},
- {"init", "(I)V", (void*)android_os_Parcel_init},
- {"destroy", "()V", (void*)android_os_Parcel_destroy},
- {"marshall", "()[B", (void*)android_os_Parcel_marshall},
- {"unmarshall", "([BII)V", (void*)android_os_Parcel_unmarshall},
- {"appendFrom", "(Landroid/os/Parcel;II)V", (void*)android_os_Parcel_appendFrom},
- {"hasFileDescriptors", "()Z", (void*)android_os_Parcel_hasFileDescriptors},
- {"writeInterfaceToken", "(Ljava/lang/String;)V", (void*)android_os_Parcel_writeInterfaceToken},
- {"enforceInterface", "(Ljava/lang/String;)V", (void*)android_os_Parcel_enforceInterface},
-};
-
-const char* const kParcelPathName = "android/os/Parcel";
+ if (int_register_android_os_Binder(env) < 0)
+ return -1;
+ if (int_register_android_os_BinderInternal(env) < 0)
+ return -1;
+ if (int_register_android_os_BinderProxy(env) < 0)
+ return -1;
-static int int_register_android_os_Parcel(JNIEnv* env)
-{
jclass clazz;
clazz = env->FindClass("android/util/Log");
@@ -1894,14 +1281,6 @@ static int int_register_android_os_Parcel(JNIEnv* env)
gParcelFileDescriptorOffsets.mConstructor
= env->GetMethodID(clazz, "<init>", "(Ljava/io/FileDescriptor;)V");
- clazz = env->FindClass(kParcelPathName);
- LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Parcel");
-
- gParcelOffsets.mObject
- = env->GetFieldID(clazz, "mObject", "I");
- gParcelOffsets.mOwnObject
- = env->GetFieldID(clazz, "mOwnObject", "I");
-
clazz = env->FindClass("android/os/StrictMode");
LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.StrictMode");
gStrictModeCallbackOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
@@ -1910,20 +1289,5 @@ static int int_register_android_os_Parcel(JNIEnv* env)
LOG_FATAL_IF(gStrictModeCallbackOffsets.mCallback == NULL,
"Unable to find strict mode callback.");
- return AndroidRuntime::registerNativeMethods(
- env, kParcelPathName,
- gParcelMethods, NELEM(gParcelMethods));
-}
-
-int register_android_os_Binder(JNIEnv* env)
-{
- if (int_register_android_os_Binder(env) < 0)
- return -1;
- if (int_register_android_os_BinderInternal(env) < 0)
- return -1;
- if (int_register_android_os_BinderProxy(env) < 0)
- return -1;
- if (int_register_android_os_Parcel(env) < 0)
- return -1;
return 0;
}
diff --git a/core/jni/android_util_Binder.h b/core/jni/android_util_Binder.h
index 0122691..ca320ef 100644
--- a/core/jni/android_util_Binder.h
+++ b/core/jni/android_util_Binder.h
@@ -15,6 +15,9 @@
** limitations under the License.
*/
+#ifndef ANDROID_UTIL_BINDER_H
+#define ANDROID_UTIL_BINDER_H
+
#include <binder/IBinder.h>
#include "jni.h"
@@ -25,10 +28,13 @@ namespace android {
extern jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val);
extern sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj);
-// Conversion from Java Parcel Object to C++ Parcel instance.
-// Note: does not type checking; must guarantee jobject is a Java Parcel
-extern Parcel* parcelForJavaObject(JNIEnv* env, jobject obj);
-
extern jobject newParcelFileDescriptor(JNIEnv* env, jobject fileDesc);
+extern void set_dalvik_blockguard_policy(JNIEnv* env, jint strict_policy);
+
+extern void signalExceptionForError(JNIEnv* env, jobject obj, status_t err,
+ bool canThrowRemoteException = false);
+
}
+
+#endif
diff --git a/core/jni/android_view_InputChannel.cpp b/core/jni/android_view_InputChannel.cpp
index 8350e73..9c44a59 100644
--- a/core/jni/android_view_InputChannel.cpp
+++ b/core/jni/android_view_InputChannel.cpp
@@ -23,6 +23,7 @@
#include <utils/Log.h>
#include <androidfw/InputTransport.h>
#include "android_view_InputChannel.h"
+#include "android_os_Parcel.h"
#include "android_util_Binder.h"
namespace android {
diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp
index 0fb1b17..e69fb74 100644
--- a/core/jni/android_view_MotionEvent.cpp
+++ b/core/jni/android_view_MotionEvent.cpp
@@ -21,6 +21,7 @@
#include <android_runtime/AndroidRuntime.h>
#include <utils/Log.h>
#include <androidfw/Input.h>
+#include "android_os_Parcel.h"
#include "android_view_MotionEvent.h"
#include "android_util_Binder.h"
#include "android/graphics/Matrix.h"
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 6ec5d20..f572f71 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -36,6 +36,7 @@
#include "utils/String8.h"
#include "android_media_Utils.h"
+#include "android_os_Parcel.h"
#include "android_util_Binder.h"
#include <binder/Parcel.h>
#include <gui/ISurfaceTexture.h>