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 android.support.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 return createPeerConnection(rtcConfig, constraints, observer); 408 } 409 410 @Nullable createPeerConnection( List<PeerConnection.IceServer> iceServers, PeerConnection.Observer observer)411 public PeerConnection createPeerConnection( 412 List<PeerConnection.IceServer> iceServers, PeerConnection.Observer observer) { 413 PeerConnection.RTCConfiguration rtcConfig = new PeerConnection.RTCConfiguration(iceServers); 414 return createPeerConnection(rtcConfig, observer); 415 } 416 417 @Nullable createPeerConnection( PeerConnection.RTCConfiguration rtcConfig, PeerConnection.Observer observer)418 public PeerConnection createPeerConnection( 419 PeerConnection.RTCConfiguration rtcConfig, PeerConnection.Observer observer) { 420 return createPeerConnection(rtcConfig, null /* constraints */, observer); 421 } 422 423 @Nullable createPeerConnection( PeerConnection.RTCConfiguration rtcConfig, PeerConnectionDependencies dependencies)424 public PeerConnection createPeerConnection( 425 PeerConnection.RTCConfiguration rtcConfig, PeerConnectionDependencies dependencies) { 426 return createPeerConnectionInternal(rtcConfig, null /* constraints */, 427 dependencies.getObserver(), dependencies.getSSLCertificateVerifier()); 428 } 429 createLocalMediaStream(String label)430 public MediaStream createLocalMediaStream(String label) { 431 checkPeerConnectionFactoryExists(); 432 return new MediaStream(nativeCreateLocalMediaStream(nativeFactory, label)); 433 } 434 435 /** 436 * Create video source with given parameters. If alignTimestamps is false, the caller is 437 * responsible for aligning the frame timestamps to rtc::TimeNanos(). This can be used to achieve 438 * higher accuracy if there is a big delay between frame creation and frames being delivered to 439 * the returned video source. If alignTimestamps is true, timestamps will be aligned to 440 * rtc::TimeNanos() when they arrive to the returned video source. 441 */ createVideoSource(boolean isScreencast, boolean alignTimestamps)442 public VideoSource createVideoSource(boolean isScreencast, boolean alignTimestamps) { 443 checkPeerConnectionFactoryExists(); 444 return new VideoSource(nativeCreateVideoSource(nativeFactory, isScreencast, alignTimestamps)); 445 } 446 447 /** 448 * Same as above with alignTimestamps set to true. 449 * 450 * @see #createVideoSource(boolean, boolean) 451 */ createVideoSource(boolean isScreencast)452 public VideoSource createVideoSource(boolean isScreencast) { 453 return createVideoSource(isScreencast, /* alignTimestamps= */ true); 454 } 455 createVideoTrack(String id, VideoSource source)456 public VideoTrack createVideoTrack(String id, VideoSource source) { 457 checkPeerConnectionFactoryExists(); 458 return new VideoTrack( 459 nativeCreateVideoTrack(nativeFactory, id, source.getNativeVideoTrackSource())); 460 } 461 createAudioSource(MediaConstraints constraints)462 public AudioSource createAudioSource(MediaConstraints constraints) { 463 checkPeerConnectionFactoryExists(); 464 return new AudioSource(nativeCreateAudioSource(nativeFactory, constraints)); 465 } 466 createAudioTrack(String id, AudioSource source)467 public AudioTrack createAudioTrack(String id, AudioSource source) { 468 checkPeerConnectionFactoryExists(); 469 return new AudioTrack(nativeCreateAudioTrack(nativeFactory, id, source.getNativeAudioSource())); 470 } 471 472 // Starts recording an AEC dump. Ownership of the file is transfered to the 473 // native code. If an AEC dump is already in progress, it will be stopped and 474 // a new one will start using the provided file. startAecDump(int file_descriptor, int filesize_limit_bytes)475 public boolean startAecDump(int file_descriptor, int filesize_limit_bytes) { 476 checkPeerConnectionFactoryExists(); 477 return nativeStartAecDump(nativeFactory, file_descriptor, filesize_limit_bytes); 478 } 479 480 // Stops recording an AEC dump. If no AEC dump is currently being recorded, 481 // this call will have no effect. stopAecDump()482 public void stopAecDump() { 483 checkPeerConnectionFactoryExists(); 484 nativeStopAecDump(nativeFactory); 485 } 486 dispose()487 public void dispose() { 488 checkPeerConnectionFactoryExists(); 489 nativeFreeFactory(nativeFactory); 490 networkThread = null; 491 workerThread = null; 492 signalingThread = null; 493 nativeFactory = 0; 494 } 495 496 /** Returns a pointer to the native webrtc::PeerConnectionFactoryInterface. */ getNativePeerConnectionFactory()497 public long getNativePeerConnectionFactory() { 498 checkPeerConnectionFactoryExists(); 499 return nativeGetNativePeerConnectionFactory(nativeFactory); 500 } 501 502 /** Returns a pointer to the native OwnedFactoryAndThreads object */ getNativeOwnedFactoryAndThreads()503 public long getNativeOwnedFactoryAndThreads() { 504 checkPeerConnectionFactoryExists(); 505 return nativeFactory; 506 } 507 checkPeerConnectionFactoryExists()508 private void checkPeerConnectionFactoryExists() { 509 if (nativeFactory == 0) { 510 throw new IllegalStateException("PeerConnectionFactory has been disposed."); 511 } 512 } 513 printStackTrace( @ullable ThreadInfo threadInfo, boolean printNativeStackTrace)514 private static void printStackTrace( 515 @Nullable ThreadInfo threadInfo, boolean printNativeStackTrace) { 516 if (threadInfo == null) { 517 // Thread callbacks have not been completed yet, ignore call. 518 return; 519 } 520 final String threadName = threadInfo.thread.getName(); 521 StackTraceElement[] stackTraces = threadInfo.thread.getStackTrace(); 522 if (stackTraces.length > 0) { 523 Logging.w(TAG, threadName + " stacktrace:"); 524 for (StackTraceElement stackTrace : stackTraces) { 525 Logging.w(TAG, stackTrace.toString()); 526 } 527 } 528 if (printNativeStackTrace) { 529 // Imitate output from debuggerd/tombstone so that stack trace can easily be symbolized with 530 // ndk-stack. 531 Logging.w(TAG, "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***"); 532 Logging.w(TAG, 533 "pid: " + Process.myPid() + ", tid: " + threadInfo.tid + ", name: " + threadName 534 + " >>> WebRTC <<<"); 535 nativePrintStackTrace(threadInfo.tid); 536 } 537 } 538 539 /** Deprecated, use non-static version instead. */ 540 @Deprecated printStackTraces()541 public static void printStackTraces() { 542 printStackTrace(staticNetworkThread, /* printNativeStackTrace= */ false); 543 printStackTrace(staticWorkerThread, /* printNativeStackTrace= */ false); 544 printStackTrace(staticSignalingThread, /* printNativeStackTrace= */ false); 545 } 546 547 /** 548 * Print the Java stack traces for the critical threads used by PeerConnectionFactory, namely; 549 * signaling thread, worker thread, and network thread. If printNativeStackTraces is true, also 550 * attempt to print the C++ stack traces for these (and some other) threads. 551 */ printInternalStackTraces(boolean printNativeStackTraces)552 public void printInternalStackTraces(boolean printNativeStackTraces) { 553 printStackTrace(signalingThread, printNativeStackTraces); 554 printStackTrace(workerThread, printNativeStackTraces); 555 printStackTrace(networkThread, printNativeStackTraces); 556 if (printNativeStackTraces) { 557 nativePrintStackTracesOfRegisteredThreads(); 558 } 559 } 560 561 @CalledByNative onNetworkThreadReady()562 private void onNetworkThreadReady() { 563 networkThread = ThreadInfo.getCurrent(); 564 staticNetworkThread = networkThread; 565 Logging.d(TAG, "onNetworkThreadReady"); 566 } 567 568 @CalledByNative onWorkerThreadReady()569 private void onWorkerThreadReady() { 570 workerThread = ThreadInfo.getCurrent(); 571 staticWorkerThread = workerThread; 572 Logging.d(TAG, "onWorkerThreadReady"); 573 } 574 575 @CalledByNative onSignalingThreadReady()576 private void onSignalingThreadReady() { 577 signalingThread = ThreadInfo.getCurrent(); 578 staticSignalingThread = signalingThread; 579 Logging.d(TAG, "onSignalingThreadReady"); 580 } 581 582 // Must be called at least once before creating a PeerConnectionFactory 583 // (for example, at application startup time). nativeInitializeAndroidGlobals()584 private static native void nativeInitializeAndroidGlobals(); nativeInitializeFieldTrials(String fieldTrialsInitString)585 private static native void nativeInitializeFieldTrials(String fieldTrialsInitString); nativeFindFieldTrialsFullName(String name)586 private static native String nativeFindFieldTrialsFullName(String name); nativeInitializeInternalTracer()587 private static native void nativeInitializeInternalTracer(); 588 // Internal tracing shutdown, called to prevent resource leaks. Must be called after 589 // PeerConnectionFactory is gone to prevent races with code performing tracing. nativeShutdownInternalTracer()590 private static native void nativeShutdownInternalTracer(); nativeStartInternalTracingCapture(String tracingFilename)591 private static native boolean nativeStartInternalTracingCapture(String tracingFilename); nativeStopInternalTracingCapture()592 private static native void nativeStopInternalTracingCapture(); 593 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)594 private static native PeerConnectionFactory nativeCreatePeerConnectionFactory(Context context, 595 Options options, long nativeAudioDeviceModule, long audioEncoderFactory, 596 long audioDecoderFactory, VideoEncoderFactory encoderFactory, 597 VideoDecoderFactory decoderFactory, long nativeAudioProcessor, 598 long nativeFecControllerFactory, long nativeNetworkControllerFactory, 599 long nativeNetworkStatePredictorFactory, long neteqFactory); 600 nativeCreatePeerConnection(long factory, PeerConnection.RTCConfiguration rtcConfig, MediaConstraints constraints, long nativeObserver, SSLCertificateVerifier sslCertificateVerifier)601 private static native long nativeCreatePeerConnection(long factory, 602 PeerConnection.RTCConfiguration rtcConfig, MediaConstraints constraints, long nativeObserver, 603 SSLCertificateVerifier sslCertificateVerifier); nativeCreateLocalMediaStream(long factory, String label)604 private static native long nativeCreateLocalMediaStream(long factory, String label); nativeCreateVideoSource( long factory, boolean is_screencast, boolean alignTimestamps)605 private static native long nativeCreateVideoSource( 606 long factory, boolean is_screencast, boolean alignTimestamps); nativeCreateVideoTrack( long factory, String id, long nativeVideoSource)607 private static native long nativeCreateVideoTrack( 608 long factory, String id, long nativeVideoSource); nativeCreateAudioSource(long factory, MediaConstraints constraints)609 private static native long nativeCreateAudioSource(long factory, MediaConstraints constraints); nativeCreateAudioTrack(long factory, String id, long nativeSource)610 private static native long nativeCreateAudioTrack(long factory, String id, long nativeSource); nativeStartAecDump( long factory, int file_descriptor, int filesize_limit_bytes)611 private static native boolean nativeStartAecDump( 612 long factory, int file_descriptor, int filesize_limit_bytes); nativeStopAecDump(long factory)613 private static native void nativeStopAecDump(long factory); nativeFreeFactory(long factory)614 private static native void nativeFreeFactory(long factory); nativeGetNativePeerConnectionFactory(long factory)615 private static native long nativeGetNativePeerConnectionFactory(long factory); nativeInjectLoggable(JNILogging jniLogging, int severity)616 private static native void nativeInjectLoggable(JNILogging jniLogging, int severity); nativeDeleteLoggable()617 private static native void nativeDeleteLoggable(); nativePrintStackTrace(int tid)618 private static native void nativePrintStackTrace(int tid); nativePrintStackTracesOfRegisteredThreads()619 private static native void nativePrintStackTracesOfRegisteredThreads(); 620 } 621