PeerConnection Java: explicitly cast DataChannel* to jlong for Java.
Otherwise on 32-bit ARM Android the nativeDataChannel param the Java ctor sees is a 64-bit value whose low 32 bits are the pointer, and whose high 32-bits are garbage. BUG=2302 R=wu@webrtc.org Review URL: https://webrtc-codereview.appspot.com/2114004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@4665 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
c8c32638be
commit
8788167b9b
@ -131,6 +131,12 @@ using webrtc::VideoRendererInterface;
|
||||
CHECK(!count, "Unexpected refcount"); \
|
||||
} while (0)
|
||||
|
||||
// Lifted from chromium's base/basictypes.h.
|
||||
template <bool>
|
||||
struct CompileAssert {};
|
||||
#define COMPILE_ASSERT(expr, msg) \
|
||||
typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]
|
||||
|
||||
namespace {
|
||||
|
||||
static JavaVM* g_jvm = NULL; // Set in JNI_OnLoad().
|
||||
@ -189,6 +195,24 @@ static JNIEnv* AttachCurrentThreadIfNeeded() {
|
||||
return jni;
|
||||
}
|
||||
|
||||
// Return a |jlong| that will automatically convert back to |ptr| when assigned
|
||||
// to a |uint64|
|
||||
static jlong jlongFromPointer(void* ptr) {
|
||||
COMPILE_ASSERT(sizeof(intptr_t) <= sizeof(uint64),
|
||||
Time_to_rethink_the_use_of_jlongs);
|
||||
// Guaranteed to fit by the COMPILE_ASSERT above.
|
||||
uint64 u64 = reinterpret_cast<intptr_t>(ptr);
|
||||
// If the unsigned value fits in the signed type, return it directly.
|
||||
if (u64 <= std::numeric_limits<int64>::max())
|
||||
return u64;
|
||||
// Otherwise, we need to get move u64 into the range of [int64min, -1] subject
|
||||
// to the constraints of remaining equal to |u64| modulo |2^64|.
|
||||
u64 = std::numeric_limits<uint64>::max() - u64; // In [0,int64max].
|
||||
int64 i64 = -u64; // In [-int64max, 0].
|
||||
i64 -= 1; // In [int64min, -1], and i64+2^64==u64.
|
||||
return i64;
|
||||
}
|
||||
|
||||
// Android's FindClass() is trickier than usual because the app-specific
|
||||
// ClassLoader is not consulted when there is no app-specific frame on the
|
||||
// stack. Consequently, we only look up classes once in JNI_OnLoad.
|
||||
@ -1346,11 +1370,16 @@ JOW(jobject, PeerConnection_createDataChannel)(
|
||||
talk_base::scoped_refptr<DataChannelInterface> channel(
|
||||
ExtractNativePC(jni, j_pc)->CreateDataChannel(
|
||||
JavaToStdString(jni, j_label), &init));
|
||||
// Mustn't pass channel.get() directly through NewObject to avoid reading its
|
||||
// vararg parameter as 64-bit and reading memory that doesn't belong to the
|
||||
// 32-bit parameter.
|
||||
jlong nativeChannelPtr = jlongFromPointer(channel.get());
|
||||
CHECK(nativeChannelPtr, "Failed to create DataChannel");
|
||||
jclass j_data_channel_class = FindClass(jni, "org/webrtc/DataChannel");
|
||||
jmethodID j_data_channel_ctor = GetMethodID(
|
||||
jni, j_data_channel_class, "<init>", "(J)V");
|
||||
jobject j_channel = jni->NewObject(
|
||||
j_data_channel_class, j_data_channel_ctor, channel.get());
|
||||
j_data_channel_class, j_data_channel_ctor, nativeChannelPtr);
|
||||
CHECK_EXCEPTION(jni, "error during NewObject");
|
||||
// Channel is now owned by Java object, and will be freed from there.
|
||||
int bumped_count = channel->AddRef();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user