xref: /aosp_15_r20/external/webrtc/sdk/android/api/org/webrtc/PeerConnectionFactory.java (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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