diff options
author | Jeff Sharkey <jsharkey@android.com> | 2012-03-06 18:26:19 -0800 |
---|---|---|
committer | Jeff Sharkey <jsharkey@android.com> | 2012-03-08 16:06:30 -0800 |
commit | d84e1ce0b535128f03416145554fb405f9fade3e (patch) | |
tree | 545922d1256d7b320dd07b236955a902320f9d9c | |
parent | 21b4d6b7a5959b567355aae032bd76500c148e54 (diff) | |
download | frameworks_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.mk | 1 | ||||
-rw-r--r-- | core/jni/AndroidRuntime.cpp | 2 | ||||
-rw-r--r-- | core/jni/android/graphics/Bitmap.cpp | 1 | ||||
-rw-r--r-- | core/jni/android/graphics/Region.cpp | 1 | ||||
-rw-r--r-- | core/jni/android_database_CursorWindow.cpp | 1 | ||||
-rw-r--r-- | core/jni/android_os_Parcel.cpp | 701 | ||||
-rw-r--r-- | core/jni/android_os_Parcel.h | 27 | ||||
-rw-r--r-- | core/jni/android_util_Binder.cpp | 676 | ||||
-rw-r--r-- | core/jni/android_util_Binder.h | 14 | ||||
-rw-r--r-- | core/jni/android_view_InputChannel.cpp | 1 | ||||
-rw-r--r-- | core/jni/android_view_MotionEvent.cpp | 1 | ||||
-rw-r--r-- | media/jni/android_media_MediaPlayer.cpp | 1 |
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> |