1 /* 2 * Copyright 2013 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 package org.webrtc; 12 13 import android.content.Context; 14 import android.os.Process; 15 import androidx.annotation.Nullable; 16 import java.util.List; 17 import org.webrtc.Logging.Severity; 18 import org.webrtc.PeerConnection; 19 import org.webrtc.audio.AudioDeviceModule; 20 import org.webrtc.audio.JavaAudioDeviceModule; 21 22 /** 23 * Java wrapper for a C++ PeerConnectionFactoryInterface. Main entry point to 24 * the PeerConnection API for clients. 25 */ 26 public class PeerConnectionFactory { 27 public static final String TRIAL_ENABLED = "Enabled"; 28 @Deprecated public static final String VIDEO_FRAME_EMIT_TRIAL = "VideoFrameEmit"; 29 30 private static final String TAG = "PeerConnectionFactory"; 31 private static final String VIDEO_CAPTURER_THREAD_NAME = "VideoCapturerThread"; 32 33 /** Helper class holding both Java and C++ thread info. */ 34 private static class ThreadInfo { 35 final Thread thread; 36 final int tid; 37 getCurrent()38 public static ThreadInfo getCurrent() { 39 return new ThreadInfo(Thread.currentThread(), Process.myTid()); 40 } 41 ThreadInfo(Thread thread, int tid)42 private ThreadInfo(Thread thread, int tid) { 43 this.thread = thread; 44 this.tid = tid; 45 } 46 } 47 48 private static volatile boolean internalTracerInitialized; 49 50 // Remove these once deprecated static printStackTrace() is gone. 51 @Nullable private static ThreadInfo staticNetworkThread; 52 @Nullable private static ThreadInfo staticWorkerThread; 53 @Nullable private static ThreadInfo staticSignalingThread; 54 55 private long nativeFactory; 56 @Nullable private volatile ThreadInfo networkThread; 57 @Nullable private volatile ThreadInfo workerThread; 58 @Nullable private volatile ThreadInfo signalingThread; 59 60 public static class InitializationOptions { 61 final Context applicationContext; 62 final String fieldTrials; 63 final boolean enableInternalTracer; 64 final NativeLibraryLoader nativeLibraryLoader; 65 final String nativeLibraryName; 66 @Nullable Loggable loggable; 67 @Nullable Severity loggableSeverity; 68 InitializationOptions(Context applicationContext, String fieldTrials, boolean enableInternalTracer, NativeLibraryLoader nativeLibraryLoader, String nativeLibraryName, @Nullable Loggable loggable, @Nullable Severity loggableSeverity)69 private InitializationOptions(Context applicationContext, String fieldTrials, 70 boolean enableInternalTracer, NativeLibraryLoader nativeLibraryLoader, 71 String nativeLibraryName, @Nullable Loggable loggable, 72 @Nullable Severity loggableSeverity) { 73 this.applicationContext = applicationContext; 74 this.fieldTrials = fieldTrials; 75 this.enableInternalTracer = enableInternalTracer; 76 this.nativeLibraryLoader = nativeLibraryLoader; 77 this.nativeLibraryName = nativeLibraryName; 78 this.loggable = loggable; 79 this.loggableSeverity = loggableSeverity; 80 } 81 builder(Context applicationContext)82 public static Builder builder(Context applicationContext) { 83 return new Builder(applicationContext); 84 } 85 86 public static class Builder { 87 private final Context applicationContext; 88 private String fieldTrials = ""; 89 private boolean enableInternalTracer; 90 private NativeLibraryLoader nativeLibraryLoader = new NativeLibrary.DefaultLoader(); 91 private String nativeLibraryName = "jingle_peerconnection_so"; 92 @Nullable private Loggable loggable; 93 @Nullable private Severity loggableSeverity; 94 Builder(Context applicationContext)95 Builder(Context applicationContext) { 96 this.applicationContext = applicationContext; 97 } 98 setFieldTrials(String fieldTrials)99 public Builder setFieldTrials(String fieldTrials) { 100 this.fieldTrials = fieldTrials; 101 return this; 102 } 103 setEnableInternalTracer(boolean enableInternalTracer)104 public Builder setEnableInternalTracer(boolean enableInternalTracer) { 105 this.enableInternalTracer = enableInternalTracer; 106 return this; 107 } 108 setNativeLibraryLoader(NativeLibraryLoader nativeLibraryLoader)109 public Builder setNativeLibraryLoader(NativeLibraryLoader nativeLibraryLoader) { 110 this.nativeLibraryLoader = nativeLibraryLoader; 111 return this; 112 } 113 setNativeLibraryName(String nativeLibraryName)114 public Builder setNativeLibraryName(String nativeLibraryName) { 115 this.nativeLibraryName = nativeLibraryName; 116 return this; 117 } 118 setInjectableLogger(Loggable loggable, Severity severity)119 public Builder setInjectableLogger(Loggable loggable, Severity severity) { 120 this.loggable = loggable; 121 this.loggableSeverity = severity; 122 return this; 123 } 124 createInitializationOptions()125 public PeerConnectionFactory.InitializationOptions createInitializationOptions() { 126 return new PeerConnectionFactory.InitializationOptions(applicationContext, fieldTrials, 127 enableInternalTracer, nativeLibraryLoader, nativeLibraryName, loggable, 128 loggableSeverity); 129 } 130 } 131 } 132 133 public static class Options { 134 // Keep in sync with webrtc/rtc_base/network.h! 135 // 136 // These bit fields are defined for `networkIgnoreMask` below. 137 static final int ADAPTER_TYPE_UNKNOWN = 0; 138 static final int ADAPTER_TYPE_ETHERNET = 1 << 0; 139 static final int ADAPTER_TYPE_WIFI = 1 << 1; 140 static final int ADAPTER_TYPE_CELLULAR = 1 << 2; 141 static final int ADAPTER_TYPE_VPN = 1 << 3; 142 static final int ADAPTER_TYPE_LOOPBACK = 1 << 4; 143 static final int ADAPTER_TYPE_ANY = 1 << 5; 144 145 public int networkIgnoreMask; 146 public boolean disableEncryption; 147 public boolean disableNetworkMonitor; 148 149 @CalledByNative("Options") getNetworkIgnoreMask()150 int getNetworkIgnoreMask() { 151 return networkIgnoreMask; 152 } 153 154 @CalledByNative("Options") getDisableEncryption()155 boolean getDisableEncryption() { 156 return disableEncryption; 157 } 158 159 @CalledByNative("Options") getDisableNetworkMonitor()160 boolean getDisableNetworkMonitor() { 161 return disableNetworkMonitor; 162 } 163 } 164 165 public static class Builder { 166 @Nullable private Options options; 167 @Nullable private AudioDeviceModule audioDeviceModule; 168 private AudioEncoderFactoryFactory audioEncoderFactoryFactory = 169 new BuiltinAudioEncoderFactoryFactory(); 170 private AudioDecoderFactoryFactory audioDecoderFactoryFactory = 171 new BuiltinAudioDecoderFactoryFactory(); 172 @Nullable private VideoEncoderFactory videoEncoderFactory; 173 @Nullable private VideoDecoderFactory videoDecoderFactory; 174 @Nullable private AudioProcessingFactory audioProcessingFactory; 175 @Nullable private FecControllerFactoryFactoryInterface fecControllerFactoryFactory; 176 @Nullable private NetworkControllerFactoryFactory networkControllerFactoryFactory; 177 @Nullable private NetworkStatePredictorFactoryFactory networkStatePredictorFactoryFactory; 178 @Nullable private NetEqFactoryFactory neteqFactoryFactory; 179 Builder()180 private Builder() {} 181 setOptions(Options options)182 public Builder setOptions(Options options) { 183 this.options = options; 184 return this; 185 } 186 setAudioDeviceModule(AudioDeviceModule audioDeviceModule)187 public Builder setAudioDeviceModule(AudioDeviceModule audioDeviceModule) { 188 this.audioDeviceModule = audioDeviceModule; 189 return this; 190 } 191 setAudioEncoderFactoryFactory( AudioEncoderFactoryFactory audioEncoderFactoryFactory)192 public Builder setAudioEncoderFactoryFactory( 193 AudioEncoderFactoryFactory audioEncoderFactoryFactory) { 194 if (audioEncoderFactoryFactory == null) { 195 throw new IllegalArgumentException( 196 "PeerConnectionFactory.Builder does not accept a null AudioEncoderFactoryFactory."); 197 } 198 this.audioEncoderFactoryFactory = audioEncoderFactoryFactory; 199 return this; 200 } 201 setAudioDecoderFactoryFactory( AudioDecoderFactoryFactory audioDecoderFactoryFactory)202 public Builder setAudioDecoderFactoryFactory( 203 AudioDecoderFactoryFactory audioDecoderFactoryFactory) { 204 if (audioDecoderFactoryFactory == null) { 205 throw new IllegalArgumentException( 206 "PeerConnectionFactory.Builder does not accept a null AudioDecoderFactoryFactory."); 207 } 208 this.audioDecoderFactoryFactory = audioDecoderFactoryFactory; 209 return this; 210 } 211 setVideoEncoderFactory(VideoEncoderFactory videoEncoderFactory)212 public Builder setVideoEncoderFactory(VideoEncoderFactory videoEncoderFactory) { 213 this.videoEncoderFactory = videoEncoderFactory; 214 return this; 215 } 216 setVideoDecoderFactory(VideoDecoderFactory videoDecoderFactory)217 public Builder setVideoDecoderFactory(VideoDecoderFactory videoDecoderFactory) { 218 this.videoDecoderFactory = videoDecoderFactory; 219 return this; 220 } 221 setAudioProcessingFactory(AudioProcessingFactory audioProcessingFactory)222 public Builder setAudioProcessingFactory(AudioProcessingFactory audioProcessingFactory) { 223 if (audioProcessingFactory == null) { 224 throw new NullPointerException( 225 "PeerConnectionFactory builder does not accept a null AudioProcessingFactory."); 226 } 227 this.audioProcessingFactory = audioProcessingFactory; 228 return this; 229 } 230 setFecControllerFactoryFactoryInterface( FecControllerFactoryFactoryInterface fecControllerFactoryFactory)231 public Builder setFecControllerFactoryFactoryInterface( 232 FecControllerFactoryFactoryInterface fecControllerFactoryFactory) { 233 this.fecControllerFactoryFactory = fecControllerFactoryFactory; 234 return this; 235 } 236 setNetworkControllerFactoryFactory( NetworkControllerFactoryFactory networkControllerFactoryFactory)237 public Builder setNetworkControllerFactoryFactory( 238 NetworkControllerFactoryFactory networkControllerFactoryFactory) { 239 this.networkControllerFactoryFactory = networkControllerFactoryFactory; 240 return this; 241 } 242 setNetworkStatePredictorFactoryFactory( NetworkStatePredictorFactoryFactory networkStatePredictorFactoryFactory)243 public Builder setNetworkStatePredictorFactoryFactory( 244 NetworkStatePredictorFactoryFactory networkStatePredictorFactoryFactory) { 245 this.networkStatePredictorFactoryFactory = networkStatePredictorFactoryFactory; 246 return this; 247 } 248 249 /** 250 * Sets a NetEqFactoryFactory for the PeerConnectionFactory. When using a 251 * custom NetEqFactoryFactory, the AudioDecoderFactoryFactory will be set 252 * to null. The AudioDecoderFactoryFactory should be wrapped in the 253 * NetEqFactoryFactory. 254 */ setNetEqFactoryFactory(NetEqFactoryFactory neteqFactoryFactory)255 public Builder setNetEqFactoryFactory(NetEqFactoryFactory neteqFactoryFactory) { 256 this.neteqFactoryFactory = neteqFactoryFactory; 257 return this; 258 } 259 createPeerConnectionFactory()260 public PeerConnectionFactory createPeerConnectionFactory() { 261 checkInitializeHasBeenCalled(); 262 if (audioDeviceModule == null) { 263 audioDeviceModule = JavaAudioDeviceModule.builder(ContextUtils.getApplicationContext()) 264 .createAudioDeviceModule(); 265 } 266 return nativeCreatePeerConnectionFactory(ContextUtils.getApplicationContext(), options, 267 audioDeviceModule.getNativeAudioDeviceModulePointer(), 268 audioEncoderFactoryFactory.createNativeAudioEncoderFactory(), 269 audioDecoderFactoryFactory.createNativeAudioDecoderFactory(), videoEncoderFactory, 270 videoDecoderFactory, 271 audioProcessingFactory == null ? 0 : audioProcessingFactory.createNative(), 272 fecControllerFactoryFactory == null ? 0 : fecControllerFactoryFactory.createNative(), 273 networkControllerFactoryFactory == null 274 ? 0 275 : networkControllerFactoryFactory.createNativeNetworkControllerFactory(), 276 networkStatePredictorFactoryFactory == null 277 ? 0 278 : networkStatePredictorFactoryFactory.createNativeNetworkStatePredictorFactory(), 279 neteqFactoryFactory == null ? 0 : neteqFactoryFactory.createNativeNetEqFactory()); 280 } 281 } 282 builder()283 public static Builder builder() { 284 return new Builder(); 285 } 286 287 /** 288 * Loads and initializes WebRTC. This must be called at least once before creating a 289 * PeerConnectionFactory. Replaces all the old initialization methods. Must not be called while 290 * a PeerConnectionFactory is alive. 291 */ initialize(InitializationOptions options)292 public static void initialize(InitializationOptions options) { 293 ContextUtils.initialize(options.applicationContext); 294 NativeLibrary.initialize(options.nativeLibraryLoader, options.nativeLibraryName); 295 nativeInitializeAndroidGlobals(); 296 nativeInitializeFieldTrials(options.fieldTrials); 297 if (options.enableInternalTracer && !internalTracerInitialized) { 298 initializeInternalTracer(); 299 } 300 if (options.loggable != null) { 301 Logging.injectLoggable(options.loggable, options.loggableSeverity); 302 nativeInjectLoggable(new JNILogging(options.loggable), options.loggableSeverity.ordinal()); 303 } else { 304 Logging.d(TAG, 305 "PeerConnectionFactory was initialized without an injected Loggable. " 306 + "Any existing Loggable will be deleted."); 307 Logging.deleteInjectedLoggable(); 308 nativeDeleteLoggable(); 309 } 310 } 311 checkInitializeHasBeenCalled()312 private static void checkInitializeHasBeenCalled() { 313 if (!NativeLibrary.isLoaded() || ContextUtils.getApplicationContext() == null) { 314 throw new IllegalStateException( 315 "PeerConnectionFactory.initialize was not called before creating a " 316 + "PeerConnectionFactory."); 317 } 318 } 319 initializeInternalTracer()320 private static void initializeInternalTracer() { 321 internalTracerInitialized = true; 322 nativeInitializeInternalTracer(); 323 } 324 shutdownInternalTracer()325 public static void shutdownInternalTracer() { 326 internalTracerInitialized = false; 327 nativeShutdownInternalTracer(); 328 } 329 330 // Field trial initialization. Must be called before PeerConnectionFactory 331 // is created. 332 // Deprecated, use PeerConnectionFactory.initialize instead. 333 @Deprecated initializeFieldTrials(String fieldTrialsInitString)334 public static void initializeFieldTrials(String fieldTrialsInitString) { 335 nativeInitializeFieldTrials(fieldTrialsInitString); 336 } 337 338 // Wrapper of webrtc::field_trial::FindFullName. Develop the feature with default behaviour off. 339 // Example usage: 340 // if (PeerConnectionFactory.fieldTrialsFindFullName("WebRTCExperiment").equals("Enabled")) { 341 // method1(); 342 // } else { 343 // method2(); 344 // } fieldTrialsFindFullName(String name)345 public static String fieldTrialsFindFullName(String name) { 346 return NativeLibrary.isLoaded() ? nativeFindFieldTrialsFullName(name) : ""; 347 } 348 // Start/stop internal capturing of internal tracing. startInternalTracingCapture(String tracingFilename)349 public static boolean startInternalTracingCapture(String tracingFilename) { 350 return nativeStartInternalTracingCapture(tracingFilename); 351 } 352 stopInternalTracingCapture()353 public static void stopInternalTracingCapture() { 354 nativeStopInternalTracingCapture(); 355 } 356 357 @CalledByNative PeerConnectionFactory(long nativeFactory)358 PeerConnectionFactory(long nativeFactory) { 359 checkInitializeHasBeenCalled(); 360 if (nativeFactory == 0) { 361 throw new RuntimeException("Failed to initialize PeerConnectionFactory!"); 362 } 363 this.nativeFactory = nativeFactory; 364 } 365 366 /** 367 * Internal helper function to pass the parameters down into the native JNI bridge. 368 */ 369 @Nullable createPeerConnectionInternal(PeerConnection.RTCConfiguration rtcConfig, MediaConstraints constraints, PeerConnection.Observer observer, SSLCertificateVerifier sslCertificateVerifier)370 PeerConnection createPeerConnectionInternal(PeerConnection.RTCConfiguration rtcConfig, 371 MediaConstraints constraints, PeerConnection.Observer observer, 372 SSLCertificateVerifier sslCertificateVerifier) { 373 checkPeerConnectionFactoryExists(); 374 long nativeObserver = PeerConnection.createNativePeerConnectionObserver(observer); 375 if (nativeObserver == 0) { 376 return null; 377 } 378 long nativePeerConnection = nativeCreatePeerConnection( 379 nativeFactory, rtcConfig, constraints, nativeObserver, sslCertificateVerifier); 380 if (nativePeerConnection == 0) { 381 return null; 382 } 383 return new PeerConnection(nativePeerConnection); 384 } 385 386 /** 387 * Deprecated. PeerConnection constraints are deprecated. Supply values in rtcConfig struct 388 * instead and use the method without constraints in the signature. 389 */ 390 @Nullable 391 @Deprecated createPeerConnection(PeerConnection.RTCConfiguration rtcConfig, MediaConstraints constraints, PeerConnection.Observer observer)392 public PeerConnection createPeerConnection(PeerConnection.RTCConfiguration rtcConfig, 393 MediaConstraints constraints, PeerConnection.Observer observer) { 394 return createPeerConnectionInternal( 395 rtcConfig, constraints, observer, /* sslCertificateVerifier= */ null); 396 } 397 398 /** 399 * Deprecated. PeerConnection constraints are deprecated. Supply values in rtcConfig struct 400 * instead and use the method without constraints in the signature. 401 */ 402 @Nullable 403 @Deprecated createPeerConnection(List<PeerConnection.IceServer> iceServers, MediaConstraints constraints, PeerConnection.Observer observer)404 public PeerConnection createPeerConnection(List<PeerConnection.IceServer> iceServers, 405 MediaConstraints constraints, PeerConnection.Observer observer) { 406 PeerConnection.RTCConfiguration rtcConfig = new PeerConnection.RTCConfiguration(iceServers); 407 rtcConfig.sdpSemantics = PeerConnection.SdpSemantics.UNIFIED_PLAN; 408 return createPeerConnection(rtcConfig, constraints, observer); 409 } 410 411 @Nullable createPeerConnection( List<PeerConnection.IceServer> iceServers, PeerConnection.Observer observer)412 public PeerConnection createPeerConnection( 413 List<PeerConnection.IceServer> iceServers, PeerConnection.Observer observer) { 414 PeerConnection.RTCConfiguration rtcConfig = new PeerConnection.RTCConfiguration(iceServers); 415 rtcConfig.sdpSemantics = PeerConnection.SdpSemantics.UNIFIED_PLAN; 416 return createPeerConnection(rtcConfig, observer); 417 } 418 419 @Nullable createPeerConnection( PeerConnection.RTCConfiguration rtcConfig, PeerConnection.Observer observer)420 public PeerConnection createPeerConnection( 421 PeerConnection.RTCConfiguration rtcConfig, PeerConnection.Observer observer) { 422 return createPeerConnection(rtcConfig, null /* constraints */, observer); 423 } 424 425 @Nullable createPeerConnection( PeerConnection.RTCConfiguration rtcConfig, PeerConnectionDependencies dependencies)426 public PeerConnection createPeerConnection( 427 PeerConnection.RTCConfiguration rtcConfig, PeerConnectionDependencies dependencies) { 428 return createPeerConnectionInternal(rtcConfig, null /* constraints */, 429 dependencies.getObserver(), dependencies.getSSLCertificateVerifier()); 430 } 431 createLocalMediaStream(String label)432 public MediaStream createLocalMediaStream(String label) { 433 checkPeerConnectionFactoryExists(); 434 return new MediaStream(nativeCreateLocalMediaStream(nativeFactory, label)); 435 } 436 437 /** 438 * Create video source with given parameters. If alignTimestamps is false, the caller is 439 * responsible for aligning the frame timestamps to rtc::TimeNanos(). This can be used to achieve 440 * higher accuracy if there is a big delay between frame creation and frames being delivered to 441 * the returned video source. If alignTimestamps is true, timestamps will be aligned to 442 * rtc::TimeNanos() when they arrive to the returned video source. 443 */ createVideoSource(boolean isScreencast, boolean alignTimestamps)444 public VideoSource createVideoSource(boolean isScreencast, boolean alignTimestamps) { 445 checkPeerConnectionFactoryExists(); 446 return new VideoSource(nativeCreateVideoSource(nativeFactory, isScreencast, alignTimestamps)); 447 } 448 449 /** 450 * Same as above with alignTimestamps set to true. 451 * 452 * @see #createVideoSource(boolean, boolean) 453 */ createVideoSource(boolean isScreencast)454 public VideoSource createVideoSource(boolean isScreencast) { 455 return createVideoSource(isScreencast, /* alignTimestamps= */ true); 456 } 457 createVideoTrack(String id, VideoSource source)458 public VideoTrack createVideoTrack(String id, VideoSource source) { 459 checkPeerConnectionFactoryExists(); 460 return new VideoTrack( 461 nativeCreateVideoTrack(nativeFactory, id, source.getNativeVideoTrackSource())); 462 } 463 createAudioSource(MediaConstraints constraints)464 public AudioSource createAudioSource(MediaConstraints constraints) { 465 checkPeerConnectionFactoryExists(); 466 return new AudioSource(nativeCreateAudioSource(nativeFactory, constraints)); 467 } 468 createAudioTrack(String id, AudioSource source)469 public AudioTrack createAudioTrack(String id, AudioSource source) { 470 checkPeerConnectionFactoryExists(); 471 return new AudioTrack(nativeCreateAudioTrack(nativeFactory, id, source.getNativeAudioSource())); 472 } 473 474 // Starts recording an AEC dump. Ownership of the file is transfered to the 475 // native code. If an AEC dump is already in progress, it will be stopped and 476 // a new one will start using the provided file. startAecDump(int file_descriptor, int filesize_limit_bytes)477 public boolean startAecDump(int file_descriptor, int filesize_limit_bytes) { 478 checkPeerConnectionFactoryExists(); 479 return nativeStartAecDump(nativeFactory, file_descriptor, filesize_limit_bytes); 480 } 481 482 // Stops recording an AEC dump. If no AEC dump is currently being recorded, 483 // this call will have no effect. stopAecDump()484 public void stopAecDump() { 485 checkPeerConnectionFactoryExists(); 486 nativeStopAecDump(nativeFactory); 487 } 488 dispose()489 public void dispose() { 490 checkPeerConnectionFactoryExists(); 491 nativeFreeFactory(nativeFactory); 492 networkThread = null; 493 workerThread = null; 494 signalingThread = null; 495 nativeFactory = 0; 496 } 497 498 /** Returns a pointer to the native webrtc::PeerConnectionFactoryInterface. */ getNativePeerConnectionFactory()499 public long getNativePeerConnectionFactory() { 500 checkPeerConnectionFactoryExists(); 501 return nativeGetNativePeerConnectionFactory(nativeFactory); 502 } 503 504 /** Returns a pointer to the native OwnedFactoryAndThreads object */ getNativeOwnedFactoryAndThreads()505 public long getNativeOwnedFactoryAndThreads() { 506 checkPeerConnectionFactoryExists(); 507 return nativeFactory; 508 } 509 checkPeerConnectionFactoryExists()510 private void checkPeerConnectionFactoryExists() { 511 if (nativeFactory == 0) { 512 throw new IllegalStateException("PeerConnectionFactory has been disposed."); 513 } 514 } 515 printStackTrace( @ullable ThreadInfo threadInfo, boolean printNativeStackTrace)516 private static void printStackTrace( 517 @Nullable ThreadInfo threadInfo, boolean printNativeStackTrace) { 518 if (threadInfo == null) { 519 // Thread callbacks have not been completed yet, ignore call. 520 return; 521 } 522 final String threadName = threadInfo.thread.getName(); 523 StackTraceElement[] stackTraces = threadInfo.thread.getStackTrace(); 524 if (stackTraces.length > 0) { 525 Logging.w(TAG, threadName + " stacktrace:"); 526 for (StackTraceElement stackTrace : stackTraces) { 527 Logging.w(TAG, stackTrace.toString()); 528 } 529 } 530 if (printNativeStackTrace) { 531 // Imitate output from debuggerd/tombstone so that stack trace can easily be symbolized with 532 // ndk-stack. 533 Logging.w(TAG, "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***"); 534 Logging.w(TAG, 535 "pid: " + Process.myPid() + ", tid: " + threadInfo.tid + ", name: " + threadName 536 + " >>> WebRTC <<<"); 537 nativePrintStackTrace(threadInfo.tid); 538 } 539 } 540 541 /** Deprecated, use non-static version instead. */ 542 @Deprecated printStackTraces()543 public static void printStackTraces() { 544 printStackTrace(staticNetworkThread, /* printNativeStackTrace= */ false); 545 printStackTrace(staticWorkerThread, /* printNativeStackTrace= */ false); 546 printStackTrace(staticSignalingThread, /* printNativeStackTrace= */ false); 547 } 548 549 /** 550 * Print the Java stack traces for the critical threads used by PeerConnectionFactory, namely; 551 * signaling thread, worker thread, and network thread. If printNativeStackTraces is true, also 552 * attempt to print the C++ stack traces for these threads. 553 */ printInternalStackTraces(boolean printNativeStackTraces)554 public void printInternalStackTraces(boolean printNativeStackTraces) { 555 printStackTrace(signalingThread, printNativeStackTraces); 556 printStackTrace(workerThread, printNativeStackTraces); 557 printStackTrace(networkThread, printNativeStackTraces); 558 } 559 560 @CalledByNative onNetworkThreadReady()561 private void onNetworkThreadReady() { 562 networkThread = ThreadInfo.getCurrent(); 563 staticNetworkThread = networkThread; 564 Logging.d(TAG, "onNetworkThreadReady"); 565 } 566 567 @CalledByNative onWorkerThreadReady()568 private void onWorkerThreadReady() { 569 workerThread = ThreadInfo.getCurrent(); 570 staticWorkerThread = workerThread; 571 Logging.d(TAG, "onWorkerThreadReady"); 572 } 573 574 @CalledByNative onSignalingThreadReady()575 private void onSignalingThreadReady() { 576 signalingThread = ThreadInfo.getCurrent(); 577 staticSignalingThread = signalingThread; 578 Logging.d(TAG, "onSignalingThreadReady"); 579 } 580 581 // Must be called at least once before creating a PeerConnectionFactory 582 // (for example, at application startup time). nativeInitializeAndroidGlobals()583 private static native void nativeInitializeAndroidGlobals(); nativeInitializeFieldTrials(String fieldTrialsInitString)584 private static native void nativeInitializeFieldTrials(String fieldTrialsInitString); nativeFindFieldTrialsFullName(String name)585 private static native String nativeFindFieldTrialsFullName(String name); nativeInitializeInternalTracer()586 private static native void nativeInitializeInternalTracer(); 587 // Internal tracing shutdown, called to prevent resource leaks. Must be called after 588 // PeerConnectionFactory is gone to prevent races with code performing tracing. nativeShutdownInternalTracer()589 private static native void nativeShutdownInternalTracer(); nativeStartInternalTracingCapture(String tracingFilename)590 private static native boolean nativeStartInternalTracingCapture(String tracingFilename); nativeStopInternalTracingCapture()591 private static native void nativeStopInternalTracingCapture(); 592 nativeCreatePeerConnectionFactory(Context context, Options options, long nativeAudioDeviceModule, long audioEncoderFactory, long audioDecoderFactory, VideoEncoderFactory encoderFactory, VideoDecoderFactory decoderFactory, long nativeAudioProcessor, long nativeFecControllerFactory, long nativeNetworkControllerFactory, long nativeNetworkStatePredictorFactory, long neteqFactory)593 private static native PeerConnectionFactory nativeCreatePeerConnectionFactory(Context context, 594 Options options, long nativeAudioDeviceModule, long audioEncoderFactory, 595 long audioDecoderFactory, VideoEncoderFactory encoderFactory, 596 VideoDecoderFactory decoderFactory, long nativeAudioProcessor, 597 long nativeFecControllerFactory, long nativeNetworkControllerFactory, 598 long nativeNetworkStatePredictorFactory, long neteqFactory); 599 nativeCreatePeerConnection(long factory, PeerConnection.RTCConfiguration rtcConfig, MediaConstraints constraints, long nativeObserver, SSLCertificateVerifier sslCertificateVerifier)600 private static native long nativeCreatePeerConnection(long factory, 601 PeerConnection.RTCConfiguration rtcConfig, MediaConstraints constraints, long nativeObserver, 602 SSLCertificateVerifier sslCertificateVerifier); nativeCreateLocalMediaStream(long factory, String label)603 private static native long nativeCreateLocalMediaStream(long factory, String label); nativeCreateVideoSource( long factory, boolean is_screencast, boolean alignTimestamps)604 private static native long nativeCreateVideoSource( 605 long factory, boolean is_screencast, boolean alignTimestamps); nativeCreateVideoTrack( long factory, String id, long nativeVideoSource)606 private static native long nativeCreateVideoTrack( 607 long factory, String id, long nativeVideoSource); nativeCreateAudioSource(long factory, MediaConstraints constraints)608 private static native long nativeCreateAudioSource(long factory, MediaConstraints constraints); nativeCreateAudioTrack(long factory, String id, long nativeSource)609 private static native long nativeCreateAudioTrack(long factory, String id, long nativeSource); nativeStartAecDump( long factory, int file_descriptor, int filesize_limit_bytes)610 private static native boolean nativeStartAecDump( 611 long factory, int file_descriptor, int filesize_limit_bytes); nativeStopAecDump(long factory)612 private static native void nativeStopAecDump(long factory); nativeFreeFactory(long factory)613 private static native void nativeFreeFactory(long factory); nativeGetNativePeerConnectionFactory(long factory)614 private static native long nativeGetNativePeerConnectionFactory(long factory); nativeInjectLoggable(JNILogging jniLogging, int severity)615 private static native void nativeInjectLoggable(JNILogging jniLogging, int severity); nativeDeleteLoggable()616 private static native void nativeDeleteLoggable(); nativePrintStackTrace(int tid)617 private static native void nativePrintStackTrace(int tid); 618 } 619