diff --git a/sdk/android/BUILD.gn b/sdk/android/BUILD.gn index ee6c1b9571..a76e6b3e69 100644 --- a/sdk/android/BUILD.gn +++ b/sdk/android/BUILD.gn @@ -920,6 +920,7 @@ group("native_api") { ":native_api_base", ":native_api_codecs", ":native_api_jni", + ":native_api_peerconnection", ":native_api_video", ] } @@ -1009,6 +1010,31 @@ rtc_static_library("native_api_codecs") { ] } +# API for creating Java PeerConnectionFactory from C++ equivalents. +rtc_static_library("native_api_peerconnection") { + visibility = [ "*" ] + sources = [ + "native_api/peerconnection/peerconnectionfactory.cc", + "native_api/peerconnection/peerconnectionfactory.h", + ] + + if (is_clang) { + # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163). + suppressed_configs += [ + "//build/config/clang:extra_warnings", + "//build/config/clang:find_bad_constructs", + ] + } + + deps = [ + ":base_jni", + ":peerconnection_jni", + "//api:libjingle_peerconnection_api", + "//api/video_codecs:video_codecs_api", + "//rtc_base:rtc_base", + ] +} + # API for creating C++ wrapper implementations of api/mediastreaminterface.h # video interfaces from their Java equivalents. rtc_static_library("native_api_video") { @@ -1031,6 +1057,7 @@ generate_jni("generated_native_unittests_jni") { sources = [ "native_unittests/org/webrtc/JavaTypesTestHelper.java", + "native_unittests/org/webrtc/PeerConnectionFactoryInitializationHelper.java", ] jni_package = "" jni_generator_include = "//sdk/android/src/jni/jni_generator_helper.h" @@ -1039,7 +1066,10 @@ generate_jni("generated_native_unittests_jni") { rtc_android_library("native_unittests_java") { testonly = true - java_files = [ "native_unittests/org/webrtc/JavaTypesTestHelper.java" ] + java_files = [ + "native_unittests/org/webrtc/JavaTypesTestHelper.java", + "native_unittests/org/webrtc/PeerConnectionFactoryInitializationHelper.java", + ] deps = [ ":libjingle_peerconnection_java", @@ -1051,14 +1081,37 @@ rtc_source_set("native_unittests") { sources = [ "native_unittests/java_types_unittest.cc", + "native_unittests/peerconnection/peerconnectionfactory_unittest.cc", "native_unittests/test_jni_onload.cc", ] + if (is_clang) { + # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163). + suppressed_configs += [ + "//build/config/clang:extra_warnings", + "//build/config/clang:find_bad_constructs", + ] + } + deps = [ + ":audio_jni", ":generated_native_unittests_jni", + ":media_jni", ":native_api_base", ":native_api_jni", + ":native_api_peerconnection", + ":native_unittests_java", + ":video_jni", + "//api/audio_codecs:builtin_audio_decoder_factory", + "//api/audio_codecs:builtin_audio_encoder_factory", + "//media:rtc_audio_video", + "//media:rtc_internal_video_codecs", + "//media:rtc_media_base", + "//modules/audio_processing:audio_processing", + "//modules/utility:utility", + "//pc:libjingle_peerconnection", "//rtc_base:checks", + "//rtc_base:rtc_base_approved", "//test:test_support", "//testing/gtest", ] diff --git a/sdk/android/api/org/webrtc/PeerConnectionFactory.java b/sdk/android/api/org/webrtc/PeerConnectionFactory.java index 03eb9e39fc..d2eb73acfc 100644 --- a/sdk/android/api/org/webrtc/PeerConnectionFactory.java +++ b/sdk/android/api/org/webrtc/PeerConnectionFactory.java @@ -277,6 +277,15 @@ public class PeerConnectionFactory { } } + @CalledByNative + PeerConnectionFactory(long nativeFactory) { + checkInitializeHasBeenCalled(); + if (nativeFactory == 0) { + throw new RuntimeException("Failed to initialize PeerConnectionFactory!"); + } + this.nativeFactory = nativeFactory; + } + /** * Deprecated. PeerConnection constraints are deprecated. Supply values in rtcConfig struct * instead and use the method without constraints in the signature. diff --git a/sdk/android/native_api/peerconnection/peerconnectionfactory.cc b/sdk/android/native_api/peerconnection/peerconnectionfactory.cc new file mode 100644 index 0000000000..892905bf0f --- /dev/null +++ b/sdk/android/native_api/peerconnection/peerconnectionfactory.cc @@ -0,0 +1,33 @@ +/* + * Copyright 2018 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/native_api/peerconnection/peerconnectionfactory.h" + +#include + +#include +#include + +#include "sdk/android/src/jni/pc/peerconnectionfactory.h" + +namespace webrtc { + +jobject NativeToJavaPeerConnectionFactory( + JNIEnv* jni, + rtc::scoped_refptr pcf, + std::unique_ptr network_thread, + std::unique_ptr worker_thread, + std::unique_ptr signaling_thread, + rtc::NetworkMonitorFactory* network_monitor_factory) { + return webrtc::jni::NativeToJavaPeerConnectionFactory( + jni, pcf, std::move(network_thread), std::move(worker_thread), + std::move(signaling_thread), network_monitor_factory); +} + +} // namespace webrtc diff --git a/sdk/android/native_api/peerconnection/peerconnectionfactory.h b/sdk/android/native_api/peerconnection/peerconnectionfactory.h new file mode 100644 index 0000000000..652be7adc6 --- /dev/null +++ b/sdk/android/native_api/peerconnection/peerconnectionfactory.h @@ -0,0 +1,34 @@ +/* + * Copyright 2018 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_NATIVE_API_PEERCONNECTION_PEERCONNECTIONFACTORY_H_ +#define SDK_ANDROID_NATIVE_API_PEERCONNECTION_PEERCONNECTIONFACTORY_H_ + +#include + +#include + +#include "api/peerconnectioninterface.h" +#include "rtc_base/thread.h" + +namespace webrtc { + +// Creates java PeerConnectionFactory with specified |pcf|. +jobject NativeToJavaPeerConnectionFactory( + JNIEnv* jni, + rtc::scoped_refptr pcf, + std::unique_ptr network_thread, + std::unique_ptr worker_thread, + std::unique_ptr signaling_thread, + rtc::NetworkMonitorFactory* network_monitor_factory = nullptr); + +} // namespace webrtc + +#endif // SDK_ANDROID_NATIVE_API_PEERCONNECTION_PEERCONNECTIONFACTORY_H_ diff --git a/sdk/android/native_unittests/org/webrtc/PeerConnectionFactoryInitializationHelper.java b/sdk/android/native_unittests/org/webrtc/PeerConnectionFactoryInitializationHelper.java new file mode 100644 index 0000000000..445a6733ea --- /dev/null +++ b/sdk/android/native_unittests/org/webrtc/PeerConnectionFactoryInitializationHelper.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018 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; + +import android.content.Context; +import org.webrtc.PeerConnectionFactory.InitializationOptions; + +public class PeerConnectionFactoryInitializationHelper { + private static class MockLoader implements NativeLibraryLoader { + @Override + public boolean load(String name) { + return true; + } + } + + @CalledByNative + public static void initializeFactoryForTests() { + Context ctx = ContextUtils.getApplicationContext(); + InitializationOptions options = InitializationOptions.builder(ctx) + .setNativeLibraryLoader(new MockLoader()) + .createInitializationOptions(); + + PeerConnectionFactory.initialize(options); + } +} diff --git a/sdk/android/native_unittests/peerconnection/DEPS b/sdk/android/native_unittests/peerconnection/DEPS new file mode 100644 index 0000000000..3c47a81522 --- /dev/null +++ b/sdk/android/native_unittests/peerconnection/DEPS @@ -0,0 +1,5 @@ +include_rules = [ + "+media/base", + "+media/engine", + "+modules/audio_processing/include/audio_processing.h", +] diff --git a/sdk/android/native_unittests/peerconnection/peerconnectionfactory_unittest.cc b/sdk/android/native_unittests/peerconnection/peerconnectionfactory_unittest.cc new file mode 100644 index 0000000000..97f6497794 --- /dev/null +++ b/sdk/android/native_unittests/peerconnection/peerconnectionfactory_unittest.cc @@ -0,0 +1,96 @@ +/* + * Copyright 2018 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/native_api/peerconnection/peerconnectionfactory.h" + +#include "api/audio_codecs/builtin_audio_decoder_factory.h" +#include "api/audio_codecs/builtin_audio_encoder_factory.h" +#include "media/base/mediaengine.h" +#include "media/engine/internaldecoderfactory.h" +#include "media/engine/internalencoderfactory.h" +#include "media/engine/webrtcmediaengine.h" +#include "modules/audio_processing/include/audio_processing.h" +#include "rtc_base/logging.h" +#include "rtc_base/ptr_util.h" +#include "sdk/android/generated_native_unittests_jni/jni/PeerConnectionFactoryInitializationHelper_jni.h" +#include "sdk/android/native_api/jni/jvm.h" +#include "test/gtest.h" + +namespace webrtc { +namespace test { +namespace { + +// Create native peer connection factory, that will be wrapped by java one +rtc::scoped_refptr CreateTestPCF( + rtc::Thread* network_thread, + rtc::Thread* worker_thread, + rtc::Thread* signaling_thread) { + // talk/ assumes pretty widely that the current Thread is ThreadManager'd, but + // ThreadManager only WrapCurrentThread()s the thread where it is first + // created. Since the semantics around when auto-wrapping happens in + // webrtc/rtc_base/ are convoluted, we simply wrap here to avoid having to + // think about ramifications of auto-wrapping there. + rtc::ThreadManager::Instance()->WrapCurrentThread(); + + std::unique_ptr media_engine = + cricket::WebRtcMediaEngineFactory::Create( + nullptr /* adm */, webrtc::CreateBuiltinAudioEncoderFactory(), + webrtc::CreateBuiltinAudioDecoderFactory(), + rtc::MakeUnique(), + rtc::MakeUnique(), + nullptr /* audio_mixer */, webrtc::AudioProcessingBuilder().Create()); + RTC_LOG(LS_INFO) << "Media engine created: " << media_engine.get(); + + auto factory = CreateModularPeerConnectionFactory( + network_thread, worker_thread, signaling_thread, std::move(media_engine), + webrtc::CreateCallFactory(), webrtc::CreateRtcEventLogFactory()); + RTC_LOG(LS_INFO) << "PeerConnectionFactory created: " << factory; + RTC_CHECK(factory) << "Failed to create the peer connection factory; " + << "WebRTC/libjingle init likely failed on this device"; + + return factory; +} + +TEST(PeerConnectionFactoryTest, NativeToJavaPeerConnectionFactory) { + JNIEnv* jni = AttachCurrentThreadIfNeeded(); + + RTC_LOG(INFO) << "Initializing java peer connection factory."; + Java_PeerConnectionFactoryInitializationHelper_initializeFactoryForTests(jni); + RTC_LOG(INFO) << "Java peer connection factory initialized."; + + // Create threads. + std::unique_ptr network_thread = + rtc::Thread::CreateWithSocketServer(); + network_thread->SetName("network_thread", nullptr); + RTC_CHECK(network_thread->Start()) << "Failed to start thread"; + + std::unique_ptr worker_thread = rtc::Thread::Create(); + worker_thread->SetName("worker_thread", nullptr); + RTC_CHECK(worker_thread->Start()) << "Failed to start thread"; + + std::unique_ptr signaling_thread = rtc::Thread::Create(); + signaling_thread->SetName("signaling_thread", NULL); + RTC_CHECK(signaling_thread->Start()) << "Failed to start thread"; + + rtc::scoped_refptr factory = + CreateTestPCF(network_thread.get(), worker_thread.get(), + signaling_thread.get()); + + jobject java_factory = NativeToJavaPeerConnectionFactory( + jni, factory, std::move(network_thread), std::move(worker_thread), + std::move(signaling_thread), nullptr /* network_monitor_factory */); + + RTC_LOG(INFO) << java_factory; + + EXPECT_NE(java_factory, nullptr); +} + +} // namespace +} // namespace test +} // namespace webrtc diff --git a/sdk/android/src/jni/pc/peerconnectionfactory.cc b/sdk/android/src/jni/pc/peerconnectionfactory.cc index b4496a5244..d10455ef85 100644 --- a/sdk/android/src/jni/pc/peerconnectionfactory.cc +++ b/sdk/android/src/jni/pc/peerconnectionfactory.cc @@ -13,7 +13,6 @@ #include #include -#include "api/peerconnectioninterface.h" #include "api/video_codecs/video_decoder_factory.h" #include "api/video_codecs/video_encoder_factory.h" #include "media/base/mediaengine.h" @@ -99,6 +98,25 @@ void PeerConnectionFactorySignalingThreadReady() { Java_PeerConnectionFactory_onSignalingThreadReady(env); } +jobject NativeToJavaPeerConnectionFactory( + JNIEnv* jni, + rtc::scoped_refptr pcf, + std::unique_ptr network_thread, + std::unique_ptr worker_thread, + std::unique_ptr signaling_thread, + rtc::NetworkMonitorFactory* network_monitor_factory) { + jni::OwnedFactoryAndThreads* owned_factory = new jni::OwnedFactoryAndThreads( + std::move(network_thread), std::move(worker_thread), + std::move(signaling_thread), nullptr /* legacy_encoder_factory */, + nullptr /* legacy_decoder_factory */, network_monitor_factory, + pcf.release()); + owned_factory->InvokeJavaCallbacksOnFactoryThreads(); + + return Java_PeerConnectionFactory_Constructor( + jni, NativeToJavaPointer(owned_factory)) + .Release(); +} + static void JNI_PeerConnectionFactory_InitializeAndroidGlobals( JNIEnv* jni, const JavaParamRef&, diff --git a/sdk/android/src/jni/pc/peerconnectionfactory.h b/sdk/android/src/jni/pc/peerconnectionfactory.h index 2f50253bdf..6f09776df9 100644 --- a/sdk/android/src/jni/pc/peerconnectionfactory.h +++ b/sdk/android/src/jni/pc/peerconnectionfactory.h @@ -12,6 +12,8 @@ #define SDK_ANDROID_SRC_JNI_PC_PEERCONNECTIONFACTORY_H_ #include +#include "api/peerconnectioninterface.h" +#include "rtc_base/thread.h" namespace webrtc { namespace jni { @@ -20,6 +22,15 @@ void PeerConnectionFactoryNetworkThreadReady(); void PeerConnectionFactoryWorkerThreadReady(); void PeerConnectionFactorySignalingThreadReady(); +// Creates java PeerConnectionFactory with specified |pcf|. +jobject NativeToJavaPeerConnectionFactory( + JNIEnv* jni, + rtc::scoped_refptr pcf, + std::unique_ptr network_thread, + std::unique_ptr worker_thread, + std::unique_ptr signaling_thread, + rtc::NetworkMonitorFactory* network_monitor_factory = nullptr); + } // namespace jni } // namespace webrtc