diff --git a/examples/androidapp/src/org/appspot/apprtc/PeerConnectionClient.java b/examples/androidapp/src/org/appspot/apprtc/PeerConnectionClient.java index 8cc487e7b8..0776ccba60 100644 --- a/examples/androidapp/src/org/appspot/apprtc/PeerConnectionClient.java +++ b/examples/androidapp/src/org/appspot/apprtc/PeerConnectionClient.java @@ -36,6 +36,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import org.appspot.apprtc.AppRTCClient.SignalingParameters; import org.appspot.apprtc.RecordedAudioToFileController; +import org.webrtc.AddIceObserver; import org.webrtc.AudioSource; import org.webrtc.AudioTrack; import org.webrtc.CameraVideoCapturer; @@ -824,7 +825,16 @@ public class PeerConnectionClient { if (queuedRemoteCandidates != null) { queuedRemoteCandidates.add(candidate); } else { - peerConnection.addIceCandidate(candidate); + peerConnection.addIceCandidate(candidate, new AddIceObserver() { + @Override + public void onAddSuccess() { + Log.d(TAG, "Candidate " + candidate + " successfully added."); + } + @Override + public void onAddFailure(String error) { + Log.d(TAG, "Candidate " + candidate + " addition failed: " + error); + } + }); } } }); @@ -1146,7 +1156,16 @@ public class PeerConnectionClient { if (queuedRemoteCandidates != null) { Log.d(TAG, "Add " + queuedRemoteCandidates.size() + " remote candidates"); for (IceCandidate candidate : queuedRemoteCandidates) { - peerConnection.addIceCandidate(candidate); + peerConnection.addIceCandidate(candidate, new AddIceObserver() { + @Override + public void onAddSuccess() { + Log.d(TAG, "Candidate " + candidate + " successfully added."); + } + @Override + public void onAddFailure(String error) { + Log.d(TAG, "Candidate " + candidate + " addition failed: " + error); + } + }); } queuedRemoteCandidates = null; } diff --git a/sdk/android/BUILD.gn b/sdk/android/BUILD.gn index 0d2ede0022..c5c903b6ca 100644 --- a/sdk/android/BUILD.gn +++ b/sdk/android/BUILD.gn @@ -262,6 +262,7 @@ if (is_android) { rtc_android_library("peerconnection_java") { visibility = [ "*" ] sources = [ + "api/org/webrtc/AddIceObserver.java", "api/org/webrtc/AudioProcessingFactory.java", "api/org/webrtc/AudioSource.java", "api/org/webrtc/AudioTrack.java", @@ -692,6 +693,8 @@ if (current_os == "linux" || is_android) { visibility = [ "*" ] sources = [ + "src/jni/pc/add_ice_candidate_observer.cc", + "src/jni/pc/add_ice_candidate_observer.h", "src/jni/pc/android_network_monitor.h", "src/jni/pc/audio_track.cc", "src/jni/pc/call_session_file_rotating_log_sink.cc", @@ -1264,6 +1267,7 @@ if (current_os == "linux" || is_android) { generate_jni("generated_peerconnection_jni") { sources = [ + "api/org/webrtc/AddIceObserver.java", "api/org/webrtc/AudioTrack.java", "api/org/webrtc/CallSessionFileRotatingLogSink.java", "api/org/webrtc/CandidatePairChangeEvent.java", diff --git a/sdk/android/api/org/webrtc/AddIceObserver.java b/sdk/android/api/org/webrtc/AddIceObserver.java new file mode 100644 index 0000000000..ff2c690029 --- /dev/null +++ b/sdk/android/api/org/webrtc/AddIceObserver.java @@ -0,0 +1,20 @@ +/* + * Copyright 2021 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. + */ + +package org.webrtc; + +/** Interface to handle completion of addIceCandidate */ +public interface AddIceObserver { + /** Called when ICE candidate added successfully.*/ + @CalledByNative public void onAddSuccess(); + + /** Called when ICE candidate addition failed.*/ + @CalledByNative public void onAddFailure(String error); +} diff --git a/sdk/android/api/org/webrtc/PeerConnection.java b/sdk/android/api/org/webrtc/PeerConnection.java index d998f00810..b28fbaf464 100644 --- a/sdk/android/api/org/webrtc/PeerConnection.java +++ b/sdk/android/api/org/webrtc/PeerConnection.java @@ -932,6 +932,11 @@ public class PeerConnection { return nativeAddIceCandidate(candidate.sdpMid, candidate.sdpMLineIndex, candidate.sdp); } + public void addIceCandidate(IceCandidate candidate, AddIceObserver observer) { + nativeAddIceCandidateWithObserver( + candidate.sdpMid, candidate.sdpMLineIndex, candidate.sdp, observer); + } + public boolean removeIceCandidates(final IceCandidate[] candidates) { return nativeRemoveIceCandidates(candidates); } @@ -1293,6 +1298,8 @@ public class PeerConnection { private native boolean nativeSetConfiguration(RTCConfiguration config); private native boolean nativeAddIceCandidate( String sdpMid, int sdpMLineIndex, String iceCandidateSdp); + private native void nativeAddIceCandidateWithObserver( + String sdpMid, int sdpMLineIndex, String iceCandidateSdp, AddIceObserver observer); private native boolean nativeRemoveIceCandidates(final IceCandidate[] candidates); private native boolean nativeAddLocalStream(long stream); private native void nativeRemoveLocalStream(long stream); diff --git a/sdk/android/src/jni/pc/add_ice_candidate_observer.cc b/sdk/android/src/jni/pc/add_ice_candidate_observer.cc new file mode 100644 index 0000000000..7f3dddbb28 --- /dev/null +++ b/sdk/android/src/jni/pc/add_ice_candidate_observer.cc @@ -0,0 +1,39 @@ +/* + * Copyright 2021 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/add_ice_candidate_observer.h" + +#include + +#include "sdk/android/generated_peerconnection_jni/AddIceObserver_jni.h" +#include "sdk/android/native_api/jni/java_types.h" +#include "sdk/android/src/jni/jni_helpers.h" +#include "sdk/media_constraints.h" + +namespace webrtc { +namespace jni { + +AddIceCandidateObserverJni::AddIceCandidateObserverJni( + JNIEnv* env, + const JavaRef& j_observer) + : j_observer_global_(env, j_observer) {} + +void AddIceCandidateObserverJni::OnComplete(webrtc::RTCError error) { + JNIEnv* env = AttachCurrentThreadIfNeeded(); + if (error.ok()) { + Java_AddIceObserver_onAddSuccess(env, j_observer_global_); + } else { + Java_AddIceObserver_onAddFailure(env, j_observer_global_, + NativeToJavaString(env, error.message())); + } +} + +} // namespace jni +} // namespace webrtc diff --git a/sdk/android/src/jni/pc/add_ice_candidate_observer.h b/sdk/android/src/jni/pc/add_ice_candidate_observer.h new file mode 100644 index 0000000000..ed72de9df6 --- /dev/null +++ b/sdk/android/src/jni/pc/add_ice_candidate_observer.h @@ -0,0 +1,37 @@ +/* + * Copyright 2021 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_ADD_ICE_CANDIDATE_OBSERVER_H_ +#define SDK_ANDROID_SRC_JNI_PC_ADD_ICE_CANDIDATE_OBSERVER_H_ + +#include +#include + +#include "api/peer_connection_interface.h" +#include "sdk/android/src/jni/jni_helpers.h" + +namespace webrtc { +namespace jni { + +class AddIceCandidateObserverJni final : public rtc::RefCountedBase { + public: + AddIceCandidateObserverJni(JNIEnv* env, const JavaRef& j_observer); + ~AddIceCandidateObserverJni() override = default; + + void OnComplete(RTCError error); + + private: + const ScopedJavaGlobalRef j_observer_global_; +}; + +} // namespace jni +} // namespace webrtc + +#endif // SDK_ANDROID_SRC_JNI_PC_ADD_ICE_CANDIDATE_OBSERVER_H_ diff --git a/sdk/android/src/jni/pc/peer_connection.cc b/sdk/android/src/jni/pc/peer_connection.cc index be1cddd0e0..84263ae952 100644 --- a/sdk/android/src/jni/pc/peer_connection.cc +++ b/sdk/android/src/jni/pc/peer_connection.cc @@ -44,6 +44,7 @@ #include "sdk/android/generated_peerconnection_jni/PeerConnection_jni.h" #include "sdk/android/native_api/jni/java_types.h" #include "sdk/android/src/jni/jni_helpers.h" +#include "sdk/android/src/jni/pc/add_ice_candidate_observer.h" #include "sdk/android/src/jni/pc/crypto_options.h" #include "sdk/android/src/jni/pc/data_channel.h" #include "sdk/android/src/jni/pc/ice_candidate.h" @@ -651,6 +652,25 @@ static jboolean JNI_PeerConnection_AddIceCandidate( return ExtractNativePC(jni, j_pc)->AddIceCandidate(candidate.get()); } +static void JNI_PeerConnection_AddIceCandidateWithObserver( + JNIEnv* jni, + const JavaParamRef& j_pc, + const JavaParamRef& j_sdp_mid, + jint j_sdp_mline_index, + const JavaParamRef& j_candidate_sdp, + const JavaParamRef& j_observer) { + std::string sdp_mid = JavaToNativeString(jni, j_sdp_mid); + std::string sdp = JavaToNativeString(jni, j_candidate_sdp); + std::unique_ptr candidate( + CreateIceCandidate(sdp_mid, j_sdp_mline_index, sdp, nullptr)); + + rtc::scoped_refptr observer( + new AddIceCandidateObserverJni(jni, j_observer)); + ExtractNativePC(jni, j_pc)->AddIceCandidate( + std::move(candidate), + [observer](RTCError error) { observer->OnComplete(error); }); +} + static jboolean JNI_PeerConnection_RemoveIceCandidates( JNIEnv* jni, const JavaParamRef& j_pc,