From 7bd6cccb40f550850501b56077b872f8b13380aa Mon Sep 17 00:00:00 2001 From: Magnus Jedvert Date: Fri, 24 Nov 2017 14:42:47 +0100 Subject: [PATCH] Android: Generate JNI code for DataChannel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: webrtc:8278 Change-Id: I107c839656500971cbd3da7557e14776759c318a Reviewed-on: https://webrtc-review.googlesource.com/25820 Commit-Queue: Magnus Jedvert Reviewed-by: Sami Kalliomäki Cr-Commit-Position: refs/heads/master@{#20873} --- sdk/android/BUILD.gn | 6 +- sdk/android/api/org/webrtc/DataChannel.java | 66 ++++++++++---- sdk/android/src/jni/classreferenceholder.cc | 4 - .../pc/{datachannel_jni.cc => datachannel.cc} | 86 ++++++++++++++++--- sdk/android/src/jni/pc/datachannel.h | 25 ++++++ .../src/jni/pc/datachannelobserver_jni.cc | 67 --------------- .../src/jni/pc/datachannelobserver_jni.h | 44 ---------- .../src/jni/pc/java_native_conversion.cc | 25 ------ .../src/jni/pc/java_native_conversion.h | 2 - sdk/android/src/jni/pc/peerconnection_jni.cc | 19 +--- .../src/jni/pc/peerconnectionobserver_jni.cc | 26 ++---- .../src/jni/pc/peerconnectionobserver_jni.h | 2 - 12 files changed, 160 insertions(+), 212 deletions(-) rename sdk/android/src/jni/pc/{datachannel_jni.cc => datachannel.cc} (50%) create mode 100644 sdk/android/src/jni/pc/datachannel.h delete mode 100644 sdk/android/src/jni/pc/datachannelobserver_jni.cc delete mode 100644 sdk/android/src/jni/pc/datachannelobserver_jni.h diff --git a/sdk/android/BUILD.gn b/sdk/android/BUILD.gn index ecf8a1e2c8..c346563e76 100644 --- a/sdk/android/BUILD.gn +++ b/sdk/android/BUILD.gn @@ -278,6 +278,7 @@ rtc_static_library("null_media_jni") { generate_jni("generated_peerconnection_jni") { sources = [ + "api/org/webrtc/DataChannel.java", "api/org/webrtc/MediaConstraints.java", "api/org/webrtc/NetworkMonitor.java", "api/org/webrtc/NetworkMonitorAutoDetect.java", @@ -293,9 +294,8 @@ rtc_static_library("peerconnection_jni") { "src/jni/pc/androidnetworkmonitor_jni.h", "src/jni/pc/audiotrack_jni.cc", "src/jni/pc/callsessionfilerotatinglogsink_jni.cc", - "src/jni/pc/datachannel_jni.cc", - "src/jni/pc/datachannelobserver_jni.cc", - "src/jni/pc/datachannelobserver_jni.h", + "src/jni/pc/datachannel.cc", + "src/jni/pc/datachannel.h", "src/jni/pc/dtmfsender_jni.cc", "src/jni/pc/java_native_conversion.cc", "src/jni/pc/java_native_conversion.h", diff --git a/sdk/android/api/org/webrtc/DataChannel.java b/sdk/android/api/org/webrtc/DataChannel.java index dc64ccc048..883025e960 100644 --- a/sdk/android/api/org/webrtc/DataChannel.java +++ b/sdk/android/api/org/webrtc/DataChannel.java @@ -26,17 +26,34 @@ public class DataChannel { // Optional unsigned short in WebIDL, -1 means unspecified. public int id = -1; - public Init() {} + @CalledByNative("Init") + boolean getOrdered() { + return ordered; + } - // Called only by native code. - private Init(boolean ordered, int maxRetransmitTimeMs, int maxRetransmits, String protocol, - boolean negotiated, int id) { - this.ordered = ordered; - this.maxRetransmitTimeMs = maxRetransmitTimeMs; - this.maxRetransmits = maxRetransmits; - this.protocol = protocol; - this.negotiated = negotiated; - this.id = id; + @CalledByNative("Init") + int getMaxRetransmitTimeMs() { + return maxRetransmitTimeMs; + } + + @CalledByNative("Init") + int getMaxRetransmits() { + return maxRetransmits; + } + + @CalledByNative("Init") + String getProtocol() { + return protocol; + } + + @CalledByNative("Init") + boolean getNegotiated() { + return negotiated; + } + + @CalledByNative("Init") + int getId() { + return id; } } @@ -51,6 +68,7 @@ public class DataChannel { */ public final boolean binary; + @CalledByNative("Buffer") public Buffer(ByteBuffer data, boolean binary) { this.data = data; this.binary = binary; @@ -60,23 +78,34 @@ public class DataChannel { /** Java version of C++ DataChannelObserver. */ public interface Observer { /** The data channel's bufferedAmount has changed. */ - public void onBufferedAmountChange(long previousAmount); + @CalledByNative("Observer") public void onBufferedAmountChange(long previousAmount); /** The data channel state has changed. */ - public void onStateChange(); + @CalledByNative("Observer") public void onStateChange(); /** * A data buffer was successfully received. NOTE: |buffer.data| will be * freed once this function returns so callers who want to use the data * asynchronously must make sure to copy it first. */ - public void onMessage(Buffer buffer); + @CalledByNative("Observer") public void onMessage(Buffer buffer); } /** Keep in sync with DataChannelInterface::DataState. */ - public enum State { CONNECTING, OPEN, CLOSING, CLOSED } + public enum State { + CONNECTING, + OPEN, + CLOSING, + CLOSED; + + @CalledByNative("State") + static State fromNativeIndex(int nativeIndex) { + return values()[nativeIndex]; + } + } private final long nativeDataChannel; private long nativeObserver; + @CalledByNative public DataChannel(long nativeDataChannel) { this.nativeDataChannel = nativeDataChannel; } @@ -123,5 +152,12 @@ public class DataChannel { private native boolean sendNative(byte[] data, boolean binary); /** Dispose of native resources attached to this channel. */ - public native void dispose(); + public void dispose() { + JniCommon.nativeReleaseRef(nativeDataChannel); + } + + @CalledByNative + long getNativeDataChannel() { + return nativeDataChannel; + } }; diff --git a/sdk/android/src/jni/classreferenceholder.cc b/sdk/android/src/jni/classreferenceholder.cc index 910aa5692c..1187d3e41d 100644 --- a/sdk/android/src/jni/classreferenceholder.cc +++ b/sdk/android/src/jni/classreferenceholder.cc @@ -63,10 +63,6 @@ ClassReferenceHolder::ClassReferenceHolder(JNIEnv* jni) { LoadClass(jni, "org/webrtc/Camera1Enumerator"); LoadClass(jni, "org/webrtc/Camera2Enumerator"); LoadClass(jni, "org/webrtc/CameraEnumerationAndroid"); - LoadClass(jni, "org/webrtc/DataChannel"); - LoadClass(jni, "org/webrtc/DataChannel$Buffer"); - LoadClass(jni, "org/webrtc/DataChannel$Init"); - LoadClass(jni, "org/webrtc/DataChannel$State"); LoadClass(jni, "org/webrtc/EglBase"); LoadClass(jni, "org/webrtc/EglBase$Context"); LoadClass(jni, "org/webrtc/EglBase14$Context"); diff --git a/sdk/android/src/jni/pc/datachannel_jni.cc b/sdk/android/src/jni/pc/datachannel.cc similarity index 50% rename from sdk/android/src/jni/pc/datachannel_jni.cc rename to sdk/android/src/jni/pc/datachannel.cc index a4e3cb631a..758e4b90e7 100644 --- a/sdk/android/src/jni/pc/datachannel_jni.cc +++ b/sdk/android/src/jni/pc/datachannel.cc @@ -10,27 +10,90 @@ #include +#include + #include "api/datachannelinterface.h" +#include "rtc_base/logging.h" +#include "rtc_base/ptr_util.h" +#include "sdk/android/generated_peerconnection_jni/jni/DataChannel_jni.h" #include "sdk/android/src/jni/jni_helpers.h" -#include "sdk/android/src/jni/pc/datachannelobserver_jni.h" +#include "sdk/android/src/jni/pc/datachannel.h" namespace webrtc { namespace jni { -static DataChannelInterface* ExtractNativeDC(JNIEnv* jni, jobject j_dc) { - jfieldID native_dc_id = - GetFieldID(jni, GetObjectClass(jni, j_dc), "nativeDataChannel", "J"); - jlong j_d = GetLongField(jni, j_dc, native_dc_id); +namespace { +// Adapter for a Java DataChannel$Observer presenting a C++ DataChannelObserver +// and dispatching the callback from C++ back to Java. +class DataChannelObserverJni : public DataChannelObserver { + public: + DataChannelObserverJni(JNIEnv* jni, jobject j_observer); + virtual ~DataChannelObserverJni() {} + + void OnBufferedAmountChange(uint64_t previous_amount) override; + void OnStateChange() override; + void OnMessage(const DataBuffer& buffer) override; + + private: + const ScopedGlobalRef j_observer_global_; +}; + +DataChannelObserverJni::DataChannelObserverJni(JNIEnv* jni, jobject j_observer) + : j_observer_global_(jni, j_observer) {} + +void DataChannelObserverJni::OnBufferedAmountChange(uint64_t previous_amount) { + JNIEnv* env = AttachCurrentThreadIfNeeded(); + Java_Observer_onBufferedAmountChange(env, *j_observer_global_, + previous_amount); +} + +void DataChannelObserverJni::OnStateChange() { + JNIEnv* env = AttachCurrentThreadIfNeeded(); + Java_Observer_onStateChange(env, *j_observer_global_); +} + +void DataChannelObserverJni::OnMessage(const DataBuffer& buffer) { + JNIEnv* env = AttachCurrentThreadIfNeeded(); + ScopedLocalRefFrame local_ref_frame(env); + jobject byte_buffer = env->NewDirectByteBuffer( + const_cast(buffer.data.data()), buffer.data.size()); + jobject j_buffer = Java_Buffer_Constructor(env, byte_buffer, buffer.binary); + Java_Observer_onMessage(env, *j_observer_global_, j_buffer); +} + +DataChannelInterface* ExtractNativeDC(JNIEnv* jni, jobject j_dc) { + jlong j_d = Java_DataChannel_getNativeDataChannel(jni, j_dc); return reinterpret_cast(j_d); } +} // namespace + +DataChannelInit JavaToNativeDataChannelInit(JNIEnv* env, jobject j_init) { + DataChannelInit init; + init.ordered = Java_Init_getOrdered(env, j_init); + init.maxRetransmitTime = Java_Init_getMaxRetransmitTimeMs(env, j_init); + init.maxRetransmits = Java_Init_getMaxRetransmits(env, j_init); + init.protocol = JavaToStdString(env, Java_Init_getProtocol(env, j_init)); + init.negotiated = Java_Init_getNegotiated(env, j_init); + init.id = Java_Init_getId(env, j_init); + return init; +} + +jobject WrapNativeDataChannel( + JNIEnv* env, + rtc::scoped_refptr channel) { + // Channel is now owned by Java object, and will be freed from there. + return channel ? Java_DataChannel_Constructor( + env, jlongFromPointer(channel.release())) + : nullptr; +} + JNI_FUNCTION_DECLARATION(jlong, DataChannel_registerObserverNative, JNIEnv* jni, jobject j_dc, jobject j_observer) { - std::unique_ptr observer( - new DataChannelObserverJni(jni, j_observer)); + auto observer = rtc::MakeUnique(jni, j_observer); ExtractNativeDC(jni, j_dc)->RegisterObserver(observer.get()); return jlongFromPointer(observer.release()); } @@ -62,8 +125,7 @@ JNI_FUNCTION_DECLARATION(jobject, DataChannel_state, JNIEnv* jni, jobject j_dc) { - return JavaEnumFromIndexAndClassName(jni, "DataChannel$State", - ExtractNativeDC(jni, j_dc)->state()); + return Java_State_fromNativeIndex(jni, ExtractNativeDC(jni, j_dc)->state()); } JNI_FUNCTION_DECLARATION(jlong, @@ -86,16 +148,12 @@ JNI_FUNCTION_DECLARATION(jboolean, jobject j_dc, jbyteArray data, jboolean binary) { - jbyte* bytes = jni->GetByteArrayElements(data, NULL); + jbyte* bytes = jni->GetByteArrayElements(data, nullptr); bool ret = ExtractNativeDC(jni, j_dc)->Send(DataBuffer( rtc::CopyOnWriteBuffer(bytes, jni->GetArrayLength(data)), binary)); jni->ReleaseByteArrayElements(data, bytes, JNI_ABORT); return ret; } -JNI_FUNCTION_DECLARATION(void, DataChannel_dispose, JNIEnv* jni, jobject j_dc) { - CHECK_RELEASE(ExtractNativeDC(jni, j_dc)); -} - } // namespace jni } // namespace webrtc diff --git a/sdk/android/src/jni/pc/datachannel.h b/sdk/android/src/jni/pc/datachannel.h new file mode 100644 index 0000000000..557520af44 --- /dev/null +++ b/sdk/android/src/jni/pc/datachannel.h @@ -0,0 +1,25 @@ +/* + * Copyright 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef SDK_ANDROID_SRC_JNI_PC_DATACHANNEL_H_ +#define SDK_ANDROID_SRC_JNI_PC_DATACHANNEL_H_ + +namespace webrtc { +namespace jni { + +DataChannelInit JavaToNativeDataChannelInit(JNIEnv* env, jobject j_init); + +jobject WrapNativeDataChannel(JNIEnv* env, + rtc::scoped_refptr channel); + +} // namespace jni +} // namespace webrtc + +#endif // SDK_ANDROID_SRC_JNI_PC_DATACHANNEL_H_ diff --git a/sdk/android/src/jni/pc/datachannelobserver_jni.cc b/sdk/android/src/jni/pc/datachannelobserver_jni.cc deleted file mode 100644 index 1ca8932e0e..0000000000 --- a/sdk/android/src/jni/pc/datachannelobserver_jni.cc +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2017 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "sdk/android/src/jni/pc/datachannelobserver_jni.h" - -#include "sdk/android/src/jni/classreferenceholder.h" - -namespace webrtc { -namespace jni { - -// Convenience, used since callbacks occur on the signaling thread, which may -// be a non-Java thread. -static JNIEnv* jni() { - return AttachCurrentThreadIfNeeded(); -} - -DataChannelObserverJni::DataChannelObserverJni(JNIEnv* jni, jobject j_observer) - : j_observer_global_(jni, j_observer), - j_observer_class_(jni, GetObjectClass(jni, j_observer)), - j_buffer_class_(jni, FindClass(jni, "org/webrtc/DataChannel$Buffer")), - j_on_buffered_amount_change_mid_(GetMethodID(jni, - *j_observer_class_, - "onBufferedAmountChange", - "(J)V")), - j_on_state_change_mid_( - GetMethodID(jni, *j_observer_class_, "onStateChange", "()V")), - j_on_message_mid_(GetMethodID(jni, - *j_observer_class_, - "onMessage", - "(Lorg/webrtc/DataChannel$Buffer;)V")), - j_buffer_ctor_(GetMethodID(jni, - *j_buffer_class_, - "", - "(Ljava/nio/ByteBuffer;Z)V")) {} - -void DataChannelObserverJni::OnBufferedAmountChange(uint64_t previous_amount) { - ScopedLocalRefFrame local_ref_frame(jni()); - jni()->CallVoidMethod(*j_observer_global_, j_on_buffered_amount_change_mid_, - previous_amount); - CHECK_EXCEPTION(jni()) << "error during CallVoidMethod"; -} - -void DataChannelObserverJni::OnStateChange() { - ScopedLocalRefFrame local_ref_frame(jni()); - jni()->CallVoidMethod(*j_observer_global_, j_on_state_change_mid_); - CHECK_EXCEPTION(jni()) << "error during CallVoidMethod"; -} - -void DataChannelObserverJni::OnMessage(const DataBuffer& buffer) { - ScopedLocalRefFrame local_ref_frame(jni()); - jobject byte_buffer = jni()->NewDirectByteBuffer( - const_cast(buffer.data.data()), buffer.data.size()); - jobject j_buffer = jni()->NewObject(*j_buffer_class_, j_buffer_ctor_, - byte_buffer, buffer.binary); - jni()->CallVoidMethod(*j_observer_global_, j_on_message_mid_, j_buffer); - CHECK_EXCEPTION(jni()) << "error during CallVoidMethod"; -} - -} // namespace jni -} // namespace webrtc diff --git a/sdk/android/src/jni/pc/datachannelobserver_jni.h b/sdk/android/src/jni/pc/datachannelobserver_jni.h deleted file mode 100644 index dcea9dec55..0000000000 --- a/sdk/android/src/jni/pc/datachannelobserver_jni.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2017 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef SDK_ANDROID_SRC_JNI_PC_DATACHANNELOBSERVER_JNI_H_ -#define SDK_ANDROID_SRC_JNI_PC_DATACHANNELOBSERVER_JNI_H_ - -#include "api/datachannelinterface.h" -#include "sdk/android/src/jni/jni_helpers.h" - -namespace webrtc { -namespace jni { - -// Adapter for a Java DataChannel$Observer presenting a C++ DataChannelObserver -// and dispatching the callback from C++ back to Java. -class DataChannelObserverJni : public DataChannelObserver { - public: - DataChannelObserverJni(JNIEnv* jni, jobject j_observer); - virtual ~DataChannelObserverJni() {} - - void OnBufferedAmountChange(uint64_t previous_amount) override; - void OnStateChange() override; - void OnMessage(const DataBuffer& buffer) override; - - private: - const ScopedGlobalRef j_observer_global_; - const ScopedGlobalRef j_observer_class_; - const ScopedGlobalRef j_buffer_class_; - const jmethodID j_on_buffered_amount_change_mid_; - const jmethodID j_on_state_change_mid_; - const jmethodID j_on_message_mid_; - const jmethodID j_buffer_ctor_; -}; - -} // namespace jni -} // namespace webrtc - -#endif // SDK_ANDROID_SRC_JNI_PC_DATACHANNELOBSERVER_JNI_H_ diff --git a/sdk/android/src/jni/pc/java_native_conversion.cc b/sdk/android/src/jni/pc/java_native_conversion.cc index 31668e95be..56a1f4efc6 100644 --- a/sdk/android/src/jni/pc/java_native_conversion.cc +++ b/sdk/android/src/jni/pc/java_native_conversion.cc @@ -18,31 +18,6 @@ namespace webrtc { namespace jni { -DataChannelInit JavaToNativeDataChannelInit(JNIEnv* jni, jobject j_init) { - DataChannelInit init; - - jclass j_init_class = FindClass(jni, "org/webrtc/DataChannel$Init"); - jfieldID ordered_id = GetFieldID(jni, j_init_class, "ordered", "Z"); - jfieldID max_retransmit_time_id = - GetFieldID(jni, j_init_class, "maxRetransmitTimeMs", "I"); - jfieldID max_retransmits_id = - GetFieldID(jni, j_init_class, "maxRetransmits", "I"); - jfieldID protocol_id = - GetFieldID(jni, j_init_class, "protocol", "Ljava/lang/String;"); - jfieldID negotiated_id = GetFieldID(jni, j_init_class, "negotiated", "Z"); - jfieldID id_id = GetFieldID(jni, j_init_class, "id", "I"); - - init.ordered = GetBooleanField(jni, j_init, ordered_id); - init.maxRetransmitTime = GetIntField(jni, j_init, max_retransmit_time_id); - init.maxRetransmits = GetIntField(jni, j_init, max_retransmits_id); - init.protocol = - JavaToStdString(jni, GetStringField(jni, j_init, protocol_id)); - init.negotiated = GetBooleanField(jni, j_init, negotiated_id); - init.id = GetIntField(jni, j_init, id_id); - - return init; -} - jobject NativeToJavaMediaType(JNIEnv* jni, cricket::MediaType media_type) { jclass j_media_type_class = FindClass(jni, "org/webrtc/MediaStreamTrack$MediaType"); diff --git a/sdk/android/src/jni/pc/java_native_conversion.h b/sdk/android/src/jni/pc/java_native_conversion.h index 73e1eef79e..9b74ad3f91 100644 --- a/sdk/android/src/jni/pc/java_native_conversion.h +++ b/sdk/android/src/jni/pc/java_native_conversion.h @@ -30,8 +30,6 @@ namespace webrtc { namespace jni { -DataChannelInit JavaToNativeDataChannelInit(JNIEnv* jni, jobject j_init); - cricket::MediaType JavaToNativeMediaType(JNIEnv* jni, jobject j_media_type); jobject NativeToJavaMediaType(JNIEnv* jni, cricket::MediaType media_type); diff --git a/sdk/android/src/jni/pc/peerconnection_jni.cc b/sdk/android/src/jni/pc/peerconnection_jni.cc index 8183700514..075f38229b 100644 --- a/sdk/android/src/jni/pc/peerconnection_jni.cc +++ b/sdk/android/src/jni/pc/peerconnection_jni.cc @@ -37,6 +37,7 @@ #include "rtc_base/logging.h" #include "sdk/android/src/jni/classreferenceholder.h" #include "sdk/android/src/jni/jni_helpers.h" +#include "sdk/android/src/jni/pc/datachannel.h" #include "sdk/android/src/jni/pc/java_native_conversion.h" #include "sdk/android/src/jni/pc/mediaconstraints_jni.h" #include "sdk/android/src/jni/pc/peerconnectionobserver_jni.h" @@ -95,23 +96,7 @@ JNI_FUNCTION_DECLARATION(jobject, rtc::scoped_refptr 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()); - if (!nativeChannelPtr) { - RTC_LOG(LS_ERROR) << "Failed to create DataChannel"; - return nullptr; - } - jclass j_data_channel_class = FindClass(jni, "org/webrtc/DataChannel"); - jmethodID j_data_channel_ctor = - GetMethodID(jni, j_data_channel_class, "", "(J)V"); - jobject j_channel = jni->NewObject(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. - channel->AddRef(); - return j_channel; + return WrapNativeDataChannel(jni, channel); } JNI_FUNCTION_DECLARATION(void, diff --git a/sdk/android/src/jni/pc/peerconnectionobserver_jni.cc b/sdk/android/src/jni/pc/peerconnectionobserver_jni.cc index a0eac9185b..03436de47b 100644 --- a/sdk/android/src/jni/pc/peerconnectionobserver_jni.cc +++ b/sdk/android/src/jni/pc/peerconnectionobserver_jni.cc @@ -15,6 +15,7 @@ #include "rtc_base/ptr_util.h" #include "sdk/android/src/jni/classreferenceholder.h" +#include "sdk/android/src/jni/pc/datachannel.h" #include "sdk/android/src/jni/pc/java_native_conversion.h" namespace webrtc { @@ -46,9 +47,6 @@ PeerConnectionObserverJni::PeerConnectionObserverJni(JNIEnv* jni, j_video_track_class_(jni, FindClass(jni, "org/webrtc/VideoTrack")), j_video_track_ctor_( GetMethodID(jni, *j_video_track_class_, "", "(J)V")), - j_data_channel_class_(jni, FindClass(jni, "org/webrtc/DataChannel")), - j_data_channel_ctor_( - GetMethodID(jni, *j_data_channel_class_, "", "(J)V")), j_rtp_receiver_class_(jni, FindClass(jni, "org/webrtc/RtpReceiver")), j_rtp_receiver_ctor_( GetMethodID(jni, *j_rtp_receiver_class_, "", "(J)V")) {} @@ -290,23 +288,13 @@ void PeerConnectionObserverJni::OnRemoveStream( void PeerConnectionObserverJni::OnDataChannel( rtc::scoped_refptr channel) { - ScopedLocalRefFrame local_ref_frame(jni()); - jobject j_channel = - jni()->NewObject(*j_data_channel_class_, j_data_channel_ctor_, - jlongFromPointer(channel.get())); - CHECK_EXCEPTION(jni()) << "error during NewObject"; - - jmethodID m = GetMethodID(jni(), *j_observer_class_, "onDataChannel", + JNIEnv* env = AttachCurrentThreadIfNeeded(); + ScopedLocalRefFrame local_ref_frame(env); + jobject j_channel = WrapNativeDataChannel(env, channel); + jmethodID m = GetMethodID(env, *j_observer_class_, "onDataChannel", "(Lorg/webrtc/DataChannel;)V"); - jni()->CallVoidMethod(*j_observer_global_, m, j_channel); - - // Channel is now owned by Java object, and will be freed from - // DataChannel.dispose(). Important that this be done _after_ the - // CallVoidMethod above as Java code might call back into native code and be - // surprised to see a refcount of 2. - channel->AddRef(); - - CHECK_EXCEPTION(jni()) << "error during CallVoidMethod"; + env->CallVoidMethod(*j_observer_global_, m, j_channel); + CHECK_EXCEPTION(env) << "error during CallVoidMethod"; } void PeerConnectionObserverJni::OnRenegotiationNeeded() { diff --git a/sdk/android/src/jni/pc/peerconnectionobserver_jni.h b/sdk/android/src/jni/pc/peerconnectionobserver_jni.h index d6fd0f397f..44eb319a61 100644 --- a/sdk/android/src/jni/pc/peerconnectionobserver_jni.h +++ b/sdk/android/src/jni/pc/peerconnectionobserver_jni.h @@ -118,8 +118,6 @@ class PeerConnectionObserverJni : public PeerConnectionObserver, const jmethodID j_audio_track_ctor_; const ScopedGlobalRef j_video_track_class_; const jmethodID j_video_track_ctor_; - const ScopedGlobalRef j_data_channel_class_; - const jmethodID j_data_channel_ctor_; const ScopedGlobalRef j_rtp_receiver_class_; const jmethodID j_rtp_receiver_ctor_;