• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.support.annotation.Nullable;
14 import java.util.ArrayList;
15 import java.util.Arrays;
16 import java.util.Collections;
17 import java.util.HashMap;
18 import java.util.List;
19 import java.util.Map;
20 import org.webrtc.CandidatePairChangeEvent;
21 import org.webrtc.DataChannel;
22 import org.webrtc.MediaStreamTrack;
23 import org.webrtc.RtpTransceiver;
24 
25 /**
26  * Java-land version of the PeerConnection APIs; wraps the C++ API
27  * http://www.webrtc.org/reference/native-apis, which in turn is inspired by the
28  * JS APIs: http://dev.w3.org/2011/webrtc/editor/webrtc.html and
29  * http://www.w3.org/TR/mediacapture-streams/
30  */
31 public class PeerConnection {
32   /** Tracks PeerConnectionInterface::IceGatheringState */
33   public enum IceGatheringState {
34     NEW,
35     GATHERING,
36     COMPLETE;
37 
38     @CalledByNative("IceGatheringState")
fromNativeIndex(int nativeIndex)39     static IceGatheringState fromNativeIndex(int nativeIndex) {
40       return values()[nativeIndex];
41     }
42   }
43 
44   /** Tracks PeerConnectionInterface::IceConnectionState */
45   public enum IceConnectionState {
46     NEW,
47     CHECKING,
48     CONNECTED,
49     COMPLETED,
50     FAILED,
51     DISCONNECTED,
52     CLOSED;
53 
54     @CalledByNative("IceConnectionState")
fromNativeIndex(int nativeIndex)55     static IceConnectionState fromNativeIndex(int nativeIndex) {
56       return values()[nativeIndex];
57     }
58   }
59 
60   /** Tracks PeerConnectionInterface::PeerConnectionState */
61   public enum PeerConnectionState {
62     NEW,
63     CONNECTING,
64     CONNECTED,
65     DISCONNECTED,
66     FAILED,
67     CLOSED;
68 
69     @CalledByNative("PeerConnectionState")
fromNativeIndex(int nativeIndex)70     static PeerConnectionState fromNativeIndex(int nativeIndex) {
71       return values()[nativeIndex];
72     }
73   }
74 
75   /** Tracks PeerConnectionInterface::TlsCertPolicy */
76   public enum TlsCertPolicy {
77     TLS_CERT_POLICY_SECURE,
78     TLS_CERT_POLICY_INSECURE_NO_CHECK,
79   }
80 
81   /** Tracks PeerConnectionInterface::SignalingState */
82   public enum SignalingState {
83     STABLE,
84     HAVE_LOCAL_OFFER,
85     HAVE_LOCAL_PRANSWER,
86     HAVE_REMOTE_OFFER,
87     HAVE_REMOTE_PRANSWER,
88     CLOSED;
89 
90     @CalledByNative("SignalingState")
fromNativeIndex(int nativeIndex)91     static SignalingState fromNativeIndex(int nativeIndex) {
92       return values()[nativeIndex];
93     }
94   }
95 
96   /** Java version of PeerConnectionObserver. */
97   public static interface Observer {
98     /** Triggered when the SignalingState changes. */
onSignalingChange(SignalingState newState)99     @CalledByNative("Observer") void onSignalingChange(SignalingState newState);
100 
101     /** Triggered when the IceConnectionState changes. */
onIceConnectionChange(IceConnectionState newState)102     @CalledByNative("Observer") void onIceConnectionChange(IceConnectionState newState);
103 
104     /* Triggered when the standard-compliant state transition of IceConnectionState happens. */
105     @CalledByNative("Observer")
onStandardizedIceConnectionChange(IceConnectionState newState)106     default void onStandardizedIceConnectionChange(IceConnectionState newState) {}
107 
108     /** Triggered when the PeerConnectionState changes. */
109     @CalledByNative("Observer")
onConnectionChange(PeerConnectionState newState)110     default void onConnectionChange(PeerConnectionState newState) {}
111 
112     /** Triggered when the ICE connection receiving status changes. */
onIceConnectionReceivingChange(boolean receiving)113     @CalledByNative("Observer") void onIceConnectionReceivingChange(boolean receiving);
114 
115     /** Triggered when the IceGatheringState changes. */
onIceGatheringChange(IceGatheringState newState)116     @CalledByNative("Observer") void onIceGatheringChange(IceGatheringState newState);
117 
118     /** Triggered when a new ICE candidate has been found. */
onIceCandidate(IceCandidate candidate)119     @CalledByNative("Observer") void onIceCandidate(IceCandidate candidate);
120 
121     /** Triggered when some ICE candidates have been removed. */
onIceCandidatesRemoved(IceCandidate[] candidates)122     @CalledByNative("Observer") void onIceCandidatesRemoved(IceCandidate[] candidates);
123 
124     /** Triggered when the ICE candidate pair is changed. */
125     @CalledByNative("Observer")
onSelectedCandidatePairChanged(CandidatePairChangeEvent event)126     default void onSelectedCandidatePairChanged(CandidatePairChangeEvent event) {}
127 
128     /** Triggered when media is received on a new stream from remote peer. */
onAddStream(MediaStream stream)129     @CalledByNative("Observer") void onAddStream(MediaStream stream);
130 
131     /** Triggered when a remote peer close a stream. */
onRemoveStream(MediaStream stream)132     @CalledByNative("Observer") void onRemoveStream(MediaStream stream);
133 
134     /** Triggered when a remote peer opens a DataChannel. */
onDataChannel(DataChannel dataChannel)135     @CalledByNative("Observer") void onDataChannel(DataChannel dataChannel);
136 
137     /** Triggered when renegotiation is necessary. */
onRenegotiationNeeded()138     @CalledByNative("Observer") void onRenegotiationNeeded();
139 
140     /**
141      * Triggered when a new track is signaled by the remote peer, as a result of
142      * setRemoteDescription.
143      */
onAddTrack(RtpReceiver receiver, MediaStream[] mediaStreams)144     @CalledByNative("Observer") void onAddTrack(RtpReceiver receiver, MediaStream[] mediaStreams);
145 
146     /**
147      * Triggered when the signaling from SetRemoteDescription indicates that a transceiver
148      * will be receiving media from a remote endpoint. This is only called if UNIFIED_PLAN
149      * semantics are specified. The transceiver will be disposed automatically.
150      */
onTrack(RtpTransceiver transceiver)151     @CalledByNative("Observer") default void onTrack(RtpTransceiver transceiver){};
152   }
153 
154   /** Java version of PeerConnectionInterface.IceServer. */
155   public static class IceServer {
156     // List of URIs associated with this server. Valid formats are described
157     // in RFC7064 and RFC7065, and more may be added in the future. The "host"
158     // part of the URI may contain either an IP address or a hostname.
159     @Deprecated public final String uri;
160     public final List<String> urls;
161     public final String username;
162     public final String password;
163     public final TlsCertPolicy tlsCertPolicy;
164 
165     // If the URIs in |urls| only contain IP addresses, this field can be used
166     // to indicate the hostname, which may be necessary for TLS (using the SNI
167     // extension). If |urls| itself contains the hostname, this isn't
168     // necessary.
169     public final String hostname;
170 
171     // List of protocols to be used in the TLS ALPN extension.
172     public final List<String> tlsAlpnProtocols;
173 
174     // List of elliptic curves to be used in the TLS elliptic curves extension.
175     // Only curve names supported by OpenSSL should be used (eg. "P-256","X25519").
176     public final List<String> tlsEllipticCurves;
177 
178     /** Convenience constructor for STUN servers. */
179     @Deprecated
IceServer(String uri)180     public IceServer(String uri) {
181       this(uri, "", "");
182     }
183 
184     @Deprecated
IceServer(String uri, String username, String password)185     public IceServer(String uri, String username, String password) {
186       this(uri, username, password, TlsCertPolicy.TLS_CERT_POLICY_SECURE);
187     }
188 
189     @Deprecated
IceServer(String uri, String username, String password, TlsCertPolicy tlsCertPolicy)190     public IceServer(String uri, String username, String password, TlsCertPolicy tlsCertPolicy) {
191       this(uri, username, password, tlsCertPolicy, "");
192     }
193 
194     @Deprecated
IceServer(String uri, String username, String password, TlsCertPolicy tlsCertPolicy, String hostname)195     public IceServer(String uri, String username, String password, TlsCertPolicy tlsCertPolicy,
196         String hostname) {
197       this(uri, Collections.singletonList(uri), username, password, tlsCertPolicy, hostname, null,
198           null);
199     }
200 
IceServer(String uri, List<String> urls, String username, String password, TlsCertPolicy tlsCertPolicy, String hostname, List<String> tlsAlpnProtocols, List<String> tlsEllipticCurves)201     private IceServer(String uri, List<String> urls, String username, String password,
202         TlsCertPolicy tlsCertPolicy, String hostname, List<String> tlsAlpnProtocols,
203         List<String> tlsEllipticCurves) {
204       if (uri == null || urls == null || urls.isEmpty()) {
205         throw new IllegalArgumentException("uri == null || urls == null || urls.isEmpty()");
206       }
207       for (String it : urls) {
208         if (it == null) {
209           throw new IllegalArgumentException("urls element is null: " + urls);
210         }
211       }
212       if (username == null) {
213         throw new IllegalArgumentException("username == null");
214       }
215       if (password == null) {
216         throw new IllegalArgumentException("password == null");
217       }
218       if (hostname == null) {
219         throw new IllegalArgumentException("hostname == null");
220       }
221       this.uri = uri;
222       this.urls = urls;
223       this.username = username;
224       this.password = password;
225       this.tlsCertPolicy = tlsCertPolicy;
226       this.hostname = hostname;
227       this.tlsAlpnProtocols = tlsAlpnProtocols;
228       this.tlsEllipticCurves = tlsEllipticCurves;
229     }
230 
231     @Override
toString()232     public String toString() {
233       return urls + " [" + username + ":" + password + "] [" + tlsCertPolicy + "] [" + hostname
234           + "] [" + tlsAlpnProtocols + "] [" + tlsEllipticCurves + "]";
235     }
236 
237     @Override
equals(@ullable Object obj)238     public boolean equals(@Nullable Object obj) {
239       if (obj == null) {
240         return false;
241       }
242       if (obj == this) {
243         return true;
244       }
245       if (!(obj instanceof IceServer)) {
246         return false;
247       }
248       IceServer other = (IceServer) obj;
249       return (uri.equals(other.uri) && urls.equals(other.urls) && username.equals(other.username)
250           && password.equals(other.password) && tlsCertPolicy.equals(other.tlsCertPolicy)
251           && hostname.equals(other.hostname) && tlsAlpnProtocols.equals(other.tlsAlpnProtocols)
252           && tlsEllipticCurves.equals(other.tlsEllipticCurves));
253     }
254 
255     @Override
hashCode()256     public int hashCode() {
257       Object[] values = {uri, urls, username, password, tlsCertPolicy, hostname, tlsAlpnProtocols,
258           tlsEllipticCurves};
259       return Arrays.hashCode(values);
260     }
261 
builder(String uri)262     public static Builder builder(String uri) {
263       return new Builder(Collections.singletonList(uri));
264     }
265 
builder(List<String> urls)266     public static Builder builder(List<String> urls) {
267       return new Builder(urls);
268     }
269 
270     public static class Builder {
271       @Nullable private final List<String> urls;
272       private String username = "";
273       private String password = "";
274       private TlsCertPolicy tlsCertPolicy = TlsCertPolicy.TLS_CERT_POLICY_SECURE;
275       private String hostname = "";
276       private List<String> tlsAlpnProtocols;
277       private List<String> tlsEllipticCurves;
278 
Builder(List<String> urls)279       private Builder(List<String> urls) {
280         if (urls == null || urls.isEmpty()) {
281           throw new IllegalArgumentException("urls == null || urls.isEmpty(): " + urls);
282         }
283         this.urls = urls;
284       }
285 
setUsername(String username)286       public Builder setUsername(String username) {
287         this.username = username;
288         return this;
289       }
290 
setPassword(String password)291       public Builder setPassword(String password) {
292         this.password = password;
293         return this;
294       }
295 
setTlsCertPolicy(TlsCertPolicy tlsCertPolicy)296       public Builder setTlsCertPolicy(TlsCertPolicy tlsCertPolicy) {
297         this.tlsCertPolicy = tlsCertPolicy;
298         return this;
299       }
300 
setHostname(String hostname)301       public Builder setHostname(String hostname) {
302         this.hostname = hostname;
303         return this;
304       }
305 
setTlsAlpnProtocols(List<String> tlsAlpnProtocols)306       public Builder setTlsAlpnProtocols(List<String> tlsAlpnProtocols) {
307         this.tlsAlpnProtocols = tlsAlpnProtocols;
308         return this;
309       }
310 
setTlsEllipticCurves(List<String> tlsEllipticCurves)311       public Builder setTlsEllipticCurves(List<String> tlsEllipticCurves) {
312         this.tlsEllipticCurves = tlsEllipticCurves;
313         return this;
314       }
315 
createIceServer()316       public IceServer createIceServer() {
317         return new IceServer(urls.get(0), urls, username, password, tlsCertPolicy, hostname,
318             tlsAlpnProtocols, tlsEllipticCurves);
319       }
320     }
321 
322     @Nullable
323     @CalledByNative("IceServer")
getUrls()324     List<String> getUrls() {
325       return urls;
326     }
327 
328     @Nullable
329     @CalledByNative("IceServer")
getUsername()330     String getUsername() {
331       return username;
332     }
333 
334     @Nullable
335     @CalledByNative("IceServer")
getPassword()336     String getPassword() {
337       return password;
338     }
339 
340     @CalledByNative("IceServer")
getTlsCertPolicy()341     TlsCertPolicy getTlsCertPolicy() {
342       return tlsCertPolicy;
343     }
344 
345     @Nullable
346     @CalledByNative("IceServer")
getHostname()347     String getHostname() {
348       return hostname;
349     }
350 
351     @CalledByNative("IceServer")
getTlsAlpnProtocols()352     List<String> getTlsAlpnProtocols() {
353       return tlsAlpnProtocols;
354     }
355 
356     @CalledByNative("IceServer")
getTlsEllipticCurves()357     List<String> getTlsEllipticCurves() {
358       return tlsEllipticCurves;
359     }
360   }
361 
362   /** Java version of PeerConnectionInterface.IceTransportsType */
363   public enum IceTransportsType { NONE, RELAY, NOHOST, ALL }
364 
365   /** Java version of PeerConnectionInterface.BundlePolicy */
366   public enum BundlePolicy { BALANCED, MAXBUNDLE, MAXCOMPAT }
367 
368   /** Java version of PeerConnectionInterface.RtcpMuxPolicy */
369   public enum RtcpMuxPolicy { NEGOTIATE, REQUIRE }
370 
371   /** Java version of PeerConnectionInterface.TcpCandidatePolicy */
372   public enum TcpCandidatePolicy { ENABLED, DISABLED }
373 
374   /** Java version of PeerConnectionInterface.CandidateNetworkPolicy */
375   public enum CandidateNetworkPolicy { ALL, LOW_COST }
376 
377   // Keep in sync with webrtc/rtc_base/network_constants.h.
378   public enum AdapterType {
379     UNKNOWN(0),
380     ETHERNET(1 << 0),
381     WIFI(1 << 1),
382     CELLULAR(1 << 2),
383     VPN(1 << 3),
384     LOOPBACK(1 << 4),
385     ADAPTER_TYPE_ANY(1 << 5),
386     CELLULAR_2G(1 << 6),
387     CELLULAR_3G(1 << 7),
388     CELLULAR_4G(1 << 8),
389     CELLULAR_5G(1 << 9);
390 
391     public final Integer bitMask;
AdapterType(Integer bitMask)392     private AdapterType(Integer bitMask) {
393       this.bitMask = bitMask;
394     }
395     private static final Map<Integer, AdapterType> BY_BITMASK = new HashMap<>();
396     static {
397       for (AdapterType t : values()) {
BY_BITMASK.put(t.bitMask, t)398         BY_BITMASK.put(t.bitMask, t);
399       }
400     }
401 
402     @Nullable
403     @CalledByNative("AdapterType")
fromNativeIndex(int nativeIndex)404     static AdapterType fromNativeIndex(int nativeIndex) {
405       return BY_BITMASK.get(nativeIndex);
406     }
407   }
408 
409   /** Java version of rtc::KeyType */
410   public enum KeyType { RSA, ECDSA }
411 
412   /** Java version of PeerConnectionInterface.ContinualGatheringPolicy */
413   public enum ContinualGatheringPolicy { GATHER_ONCE, GATHER_CONTINUALLY }
414 
415   /** Java version of webrtc::PortPrunePolicy */
416   public enum PortPrunePolicy {
417     NO_PRUNE, // Do not prune turn port.
418     PRUNE_BASED_ON_PRIORITY, // Prune turn port based the priority on the same network
419     KEEP_FIRST_READY // Keep the first ready port and prune the rest on the same network.
420   }
421 
422   /**
423    * Java version of webrtc::SdpSemantics.
424    *
425    * Configure the SDP semantics used by this PeerConnection. Note that the
426    * WebRTC 1.0 specification requires UNIFIED_PLAN semantics. The
427    * RtpTransceiver API is only available with UNIFIED_PLAN semantics.
428    *
429    * <p>PLAN_B will cause PeerConnection to create offers and answers with at
430    * most one audio and one video m= section with multiple RtpSenders and
431    * RtpReceivers specified as multiple a=ssrc lines within the section. This
432    * will also cause PeerConnection to ignore all but the first m= section of
433    * the same media type.
434    *
435    * <p>UNIFIED_PLAN will cause PeerConnection to create offers and answers with
436    * multiple m= sections where each m= section maps to one RtpSender and one
437    * RtpReceiver (an RtpTransceiver), either both audio or both video. This
438    * will also cause PeerConnection to ignore all but the first a=ssrc lines
439    * that form a Plan B stream.
440    *
441    * <p>For users who wish to send multiple audio/video streams and need to stay
442    * interoperable with legacy WebRTC implementations, specify PLAN_B.
443    *
444    * <p>For users who wish to send multiple audio/video streams and/or wish to
445    * use the new RtpTransceiver API, specify UNIFIED_PLAN.
446    */
447   public enum SdpSemantics { PLAN_B, UNIFIED_PLAN }
448 
449   /** Java version of PeerConnectionInterface.RTCConfiguration */
450   // TODO(qingsi): Resolve the naming inconsistency of fields with/without units.
451   public static class RTCConfiguration {
452     public IceTransportsType iceTransportsType;
453     public List<IceServer> iceServers;
454     public BundlePolicy bundlePolicy;
455     @Nullable public RtcCertificatePem certificate;
456     public RtcpMuxPolicy rtcpMuxPolicy;
457     public TcpCandidatePolicy tcpCandidatePolicy;
458     public CandidateNetworkPolicy candidateNetworkPolicy;
459     public int audioJitterBufferMaxPackets;
460     public boolean audioJitterBufferFastAccelerate;
461     public int iceConnectionReceivingTimeout;
462     public int iceBackupCandidatePairPingInterval;
463     public KeyType keyType;
464     public ContinualGatheringPolicy continualGatheringPolicy;
465     public int iceCandidatePoolSize;
466     @Deprecated // by the turnPortPrunePolicy. See bugs.webrtc.org/11026
467     public boolean pruneTurnPorts;
468     public PortPrunePolicy turnPortPrunePolicy;
469     public boolean presumeWritableWhenFullyRelayed;
470     public boolean surfaceIceCandidatesOnIceTransportTypeChanged;
471     // The following fields define intervals in milliseconds at which ICE
472     // connectivity checks are sent.
473     //
474     // We consider ICE is "strongly connected" for an agent when there is at
475     // least one candidate pair that currently succeeds in connectivity check
476     // from its direction i.e. sending a ping and receives a ping response, AND
477     // all candidate pairs have sent a minimum number of pings for connectivity
478     // (this number is implementation-specific). Otherwise, ICE is considered in
479     // "weak connectivity".
480     //
481     // Note that the above notion of strong and weak connectivity is not defined
482     // in RFC 5245, and they apply to our current ICE implementation only.
483     //
484     // 1) iceCheckIntervalStrongConnectivityMs defines the interval applied to
485     // ALL candidate pairs when ICE is strongly connected,
486     // 2) iceCheckIntervalWeakConnectivityMs defines the counterpart for ALL
487     // pairs when ICE is weakly connected, and
488     // 3) iceCheckMinInterval defines the minimal interval (equivalently the
489     // maximum rate) that overrides the above two intervals when either of them
490     // is less.
491     @Nullable public Integer iceCheckIntervalStrongConnectivityMs;
492     @Nullable public Integer iceCheckIntervalWeakConnectivityMs;
493     @Nullable public Integer iceCheckMinInterval;
494     // The time period in milliseconds for which a candidate pair must wait for response to
495     // connectivitiy checks before it becomes unwritable.
496     @Nullable public Integer iceUnwritableTimeMs;
497     // The minimum number of connectivity checks that a candidate pair must sent without receiving
498     // response before it becomes unwritable.
499     @Nullable public Integer iceUnwritableMinChecks;
500     // The interval in milliseconds at which STUN candidates will resend STUN binding requests
501     // to keep NAT bindings open.
502     // The default value in the implementation is used if this field is null.
503     @Nullable public Integer stunCandidateKeepaliveIntervalMs;
504     public boolean disableIPv6OnWifi;
505     // By default, PeerConnection will use a limited number of IPv6 network
506     // interfaces, in order to avoid too many ICE candidate pairs being created
507     // and delaying ICE completion.
508     //
509     // Can be set to Integer.MAX_VALUE to effectively disable the limit.
510     public int maxIPv6Networks;
511 
512     // These values will be overridden by MediaStream constraints if deprecated constraints-based
513     // create peerconnection interface is used.
514     public boolean disableIpv6;
515     public boolean enableDscp;
516     public boolean enableCpuOveruseDetection;
517     public boolean enableRtpDataChannel;
518     public boolean suspendBelowMinBitrate;
519     @Nullable public Integer screencastMinBitrate;
520     @Nullable public Boolean combinedAudioVideoBwe;
521     @Nullable public Boolean enableDtlsSrtp;
522     // Use "Unknown" to represent no preference of adapter types, not the
523     // preference of adapters of unknown types.
524     public AdapterType networkPreference;
525     public SdpSemantics sdpSemantics;
526 
527     // This is an optional wrapper for the C++ webrtc::TurnCustomizer.
528     @Nullable public TurnCustomizer turnCustomizer;
529 
530     // Actively reset the SRTP parameters whenever the DTLS transports underneath are reset for
531     // every offer/answer negotiation.This is only intended to be a workaround for crbug.com/835958
532     public boolean activeResetSrtpParams;
533 
534     // Whether this client is allowed to switch encoding codec mid-stream. This is a workaround for
535     // a WebRTC bug where the receiver could get confussed if a codec switch happened mid-call.
536     // Null indicates no change to currently configured value.
537     @Nullable public Boolean allowCodecSwitching;
538 
539     /**
540      * Defines advanced optional cryptographic settings related to SRTP and
541      * frame encryption for native WebRTC. Setting this will overwrite any
542      * options set through the PeerConnectionFactory (which is deprecated).
543      */
544     @Nullable public CryptoOptions cryptoOptions;
545 
546     /**
547      * An optional string that if set will be attached to the
548      * TURN_ALLOCATE_REQUEST which can be used to correlate client
549      * logs with backend logs
550      */
551     @Nullable public String turnLoggingId;
552 
553     // TODO(deadbeef): Instead of duplicating the defaults here, we should do
554     // something to pick up the defaults from C++. The Objective-C equivalent
555     // of RTCConfiguration does that.
RTCConfiguration(List<IceServer> iceServers)556     public RTCConfiguration(List<IceServer> iceServers) {
557       iceTransportsType = IceTransportsType.ALL;
558       bundlePolicy = BundlePolicy.BALANCED;
559       rtcpMuxPolicy = RtcpMuxPolicy.REQUIRE;
560       tcpCandidatePolicy = TcpCandidatePolicy.ENABLED;
561       candidateNetworkPolicy = CandidateNetworkPolicy.ALL;
562       this.iceServers = iceServers;
563       audioJitterBufferMaxPackets = 50;
564       audioJitterBufferFastAccelerate = false;
565       iceConnectionReceivingTimeout = -1;
566       iceBackupCandidatePairPingInterval = -1;
567       keyType = KeyType.ECDSA;
568       continualGatheringPolicy = ContinualGatheringPolicy.GATHER_ONCE;
569       iceCandidatePoolSize = 0;
570       pruneTurnPorts = false;
571       turnPortPrunePolicy = PortPrunePolicy.NO_PRUNE;
572       presumeWritableWhenFullyRelayed = false;
573       surfaceIceCandidatesOnIceTransportTypeChanged = false;
574       iceCheckIntervalStrongConnectivityMs = null;
575       iceCheckIntervalWeakConnectivityMs = null;
576       iceCheckMinInterval = null;
577       iceUnwritableTimeMs = null;
578       iceUnwritableMinChecks = null;
579       stunCandidateKeepaliveIntervalMs = null;
580       disableIPv6OnWifi = false;
581       maxIPv6Networks = 5;
582       disableIpv6 = false;
583       enableDscp = false;
584       enableCpuOveruseDetection = true;
585       enableRtpDataChannel = false;
586       suspendBelowMinBitrate = false;
587       screencastMinBitrate = null;
588       combinedAudioVideoBwe = null;
589       enableDtlsSrtp = null;
590       networkPreference = AdapterType.UNKNOWN;
591       sdpSemantics = SdpSemantics.PLAN_B;
592       activeResetSrtpParams = false;
593       cryptoOptions = null;
594       turnLoggingId = null;
595       allowCodecSwitching = null;
596     }
597 
598     @CalledByNative("RTCConfiguration")
getIceTransportsType()599     IceTransportsType getIceTransportsType() {
600       return iceTransportsType;
601     }
602 
603     @CalledByNative("RTCConfiguration")
getIceServers()604     List<IceServer> getIceServers() {
605       return iceServers;
606     }
607 
608     @CalledByNative("RTCConfiguration")
getBundlePolicy()609     BundlePolicy getBundlePolicy() {
610       return bundlePolicy;
611     }
612 
613     @CalledByNative("RTCConfiguration")
getTurnPortPrunePolicy()614     PortPrunePolicy getTurnPortPrunePolicy() {
615       return turnPortPrunePolicy;
616     }
617 
618     @Nullable
619     @CalledByNative("RTCConfiguration")
getCertificate()620     RtcCertificatePem getCertificate() {
621       return certificate;
622     }
623 
624     @CalledByNative("RTCConfiguration")
getRtcpMuxPolicy()625     RtcpMuxPolicy getRtcpMuxPolicy() {
626       return rtcpMuxPolicy;
627     }
628 
629     @CalledByNative("RTCConfiguration")
getTcpCandidatePolicy()630     TcpCandidatePolicy getTcpCandidatePolicy() {
631       return tcpCandidatePolicy;
632     }
633 
634     @CalledByNative("RTCConfiguration")
getCandidateNetworkPolicy()635     CandidateNetworkPolicy getCandidateNetworkPolicy() {
636       return candidateNetworkPolicy;
637     }
638 
639     @CalledByNative("RTCConfiguration")
getAudioJitterBufferMaxPackets()640     int getAudioJitterBufferMaxPackets() {
641       return audioJitterBufferMaxPackets;
642     }
643 
644     @CalledByNative("RTCConfiguration")
getAudioJitterBufferFastAccelerate()645     boolean getAudioJitterBufferFastAccelerate() {
646       return audioJitterBufferFastAccelerate;
647     }
648 
649     @CalledByNative("RTCConfiguration")
getIceConnectionReceivingTimeout()650     int getIceConnectionReceivingTimeout() {
651       return iceConnectionReceivingTimeout;
652     }
653 
654     @CalledByNative("RTCConfiguration")
getIceBackupCandidatePairPingInterval()655     int getIceBackupCandidatePairPingInterval() {
656       return iceBackupCandidatePairPingInterval;
657     }
658 
659     @CalledByNative("RTCConfiguration")
getKeyType()660     KeyType getKeyType() {
661       return keyType;
662     }
663 
664     @CalledByNative("RTCConfiguration")
getContinualGatheringPolicy()665     ContinualGatheringPolicy getContinualGatheringPolicy() {
666       return continualGatheringPolicy;
667     }
668 
669     @CalledByNative("RTCConfiguration")
getIceCandidatePoolSize()670     int getIceCandidatePoolSize() {
671       return iceCandidatePoolSize;
672     }
673 
674     @CalledByNative("RTCConfiguration")
getPruneTurnPorts()675     boolean getPruneTurnPorts() {
676       return pruneTurnPorts;
677     }
678 
679     @CalledByNative("RTCConfiguration")
getPresumeWritableWhenFullyRelayed()680     boolean getPresumeWritableWhenFullyRelayed() {
681       return presumeWritableWhenFullyRelayed;
682     }
683 
684     @CalledByNative("RTCConfiguration")
getSurfaceIceCandidatesOnIceTransportTypeChanged()685     boolean getSurfaceIceCandidatesOnIceTransportTypeChanged() {
686       return surfaceIceCandidatesOnIceTransportTypeChanged;
687     }
688 
689     @Nullable
690     @CalledByNative("RTCConfiguration")
getIceCheckIntervalStrongConnectivity()691     Integer getIceCheckIntervalStrongConnectivity() {
692       return iceCheckIntervalStrongConnectivityMs;
693     }
694 
695     @Nullable
696     @CalledByNative("RTCConfiguration")
getIceCheckIntervalWeakConnectivity()697     Integer getIceCheckIntervalWeakConnectivity() {
698       return iceCheckIntervalWeakConnectivityMs;
699     }
700 
701     @Nullable
702     @CalledByNative("RTCConfiguration")
getIceCheckMinInterval()703     Integer getIceCheckMinInterval() {
704       return iceCheckMinInterval;
705     }
706 
707     @Nullable
708     @CalledByNative("RTCConfiguration")
getIceUnwritableTimeout()709     Integer getIceUnwritableTimeout() {
710       return iceUnwritableTimeMs;
711     }
712 
713     @Nullable
714     @CalledByNative("RTCConfiguration")
getIceUnwritableMinChecks()715     Integer getIceUnwritableMinChecks() {
716       return iceUnwritableMinChecks;
717     }
718 
719     @Nullable
720     @CalledByNative("RTCConfiguration")
getStunCandidateKeepaliveInterval()721     Integer getStunCandidateKeepaliveInterval() {
722       return stunCandidateKeepaliveIntervalMs;
723     }
724 
725     @CalledByNative("RTCConfiguration")
getDisableIPv6OnWifi()726     boolean getDisableIPv6OnWifi() {
727       return disableIPv6OnWifi;
728     }
729 
730     @CalledByNative("RTCConfiguration")
getMaxIPv6Networks()731     int getMaxIPv6Networks() {
732       return maxIPv6Networks;
733     }
734 
735     @Nullable
736     @CalledByNative("RTCConfiguration")
getTurnCustomizer()737     TurnCustomizer getTurnCustomizer() {
738       return turnCustomizer;
739     }
740 
741     @CalledByNative("RTCConfiguration")
getDisableIpv6()742     boolean getDisableIpv6() {
743       return disableIpv6;
744     }
745 
746     @CalledByNative("RTCConfiguration")
getEnableDscp()747     boolean getEnableDscp() {
748       return enableDscp;
749     }
750 
751     @CalledByNative("RTCConfiguration")
getEnableCpuOveruseDetection()752     boolean getEnableCpuOveruseDetection() {
753       return enableCpuOveruseDetection;
754     }
755 
756     @CalledByNative("RTCConfiguration")
getEnableRtpDataChannel()757     boolean getEnableRtpDataChannel() {
758       return enableRtpDataChannel;
759     }
760 
761     @CalledByNative("RTCConfiguration")
getSuspendBelowMinBitrate()762     boolean getSuspendBelowMinBitrate() {
763       return suspendBelowMinBitrate;
764     }
765 
766     @Nullable
767     @CalledByNative("RTCConfiguration")
getScreencastMinBitrate()768     Integer getScreencastMinBitrate() {
769       return screencastMinBitrate;
770     }
771 
772     @Nullable
773     @CalledByNative("RTCConfiguration")
getCombinedAudioVideoBwe()774     Boolean getCombinedAudioVideoBwe() {
775       return combinedAudioVideoBwe;
776     }
777 
778     @Nullable
779     @CalledByNative("RTCConfiguration")
getEnableDtlsSrtp()780     Boolean getEnableDtlsSrtp() {
781       return enableDtlsSrtp;
782     }
783 
784     @CalledByNative("RTCConfiguration")
getNetworkPreference()785     AdapterType getNetworkPreference() {
786       return networkPreference;
787     }
788 
789     @CalledByNative("RTCConfiguration")
getSdpSemantics()790     SdpSemantics getSdpSemantics() {
791       return sdpSemantics;
792     }
793 
794     @CalledByNative("RTCConfiguration")
getActiveResetSrtpParams()795     boolean getActiveResetSrtpParams() {
796       return activeResetSrtpParams;
797     }
798 
799     @Nullable
800     @CalledByNative("RTCConfiguration")
getAllowCodecSwitching()801     Boolean getAllowCodecSwitching() {
802       return allowCodecSwitching;
803     }
804 
805     @Nullable
806     @CalledByNative("RTCConfiguration")
getCryptoOptions()807     CryptoOptions getCryptoOptions() {
808       return cryptoOptions;
809     }
810 
811     @Nullable
812     @CalledByNative("RTCConfiguration")
getTurnLoggingId()813     String getTurnLoggingId() {
814       return turnLoggingId;
815     }
816   };
817 
818   private final List<MediaStream> localStreams = new ArrayList<>();
819   private final long nativePeerConnection;
820   private List<RtpSender> senders = new ArrayList<>();
821   private List<RtpReceiver> receivers = new ArrayList<>();
822   private List<RtpTransceiver> transceivers = new ArrayList<>();
823 
824   /**
825    * Wraps a PeerConnection created by the factory. Can be used by clients that want to implement
826    * their PeerConnection creation in JNI.
827    */
PeerConnection(NativePeerConnectionFactory factory)828   public PeerConnection(NativePeerConnectionFactory factory) {
829     this(factory.createNativePeerConnection());
830   }
831 
PeerConnection(long nativePeerConnection)832   PeerConnection(long nativePeerConnection) {
833     this.nativePeerConnection = nativePeerConnection;
834   }
835 
836   // JsepInterface.
getLocalDescription()837   public SessionDescription getLocalDescription() {
838     return nativeGetLocalDescription();
839   }
840 
getRemoteDescription()841   public SessionDescription getRemoteDescription() {
842     return nativeGetRemoteDescription();
843   }
844 
getCertificate()845   public RtcCertificatePem getCertificate() {
846     return nativeGetCertificate();
847   }
848 
createDataChannel(String label, DataChannel.Init init)849   public DataChannel createDataChannel(String label, DataChannel.Init init) {
850     return nativeCreateDataChannel(label, init);
851   }
852 
createOffer(SdpObserver observer, MediaConstraints constraints)853   public void createOffer(SdpObserver observer, MediaConstraints constraints) {
854     nativeCreateOffer(observer, constraints);
855   }
856 
createAnswer(SdpObserver observer, MediaConstraints constraints)857   public void createAnswer(SdpObserver observer, MediaConstraints constraints) {
858     nativeCreateAnswer(observer, constraints);
859   }
860 
setLocalDescription(SdpObserver observer, SessionDescription sdp)861   public void setLocalDescription(SdpObserver observer, SessionDescription sdp) {
862     nativeSetLocalDescription(observer, sdp);
863   }
864 
setRemoteDescription(SdpObserver observer, SessionDescription sdp)865   public void setRemoteDescription(SdpObserver observer, SessionDescription sdp) {
866     nativeSetRemoteDescription(observer, sdp);
867   }
868 
869   /**
870    * Enables/disables playout of received audio streams. Enabled by default.
871    *
872    * Note that even if playout is enabled, streams will only be played out if
873    * the appropriate SDP is also applied. The main purpose of this API is to
874    * be able to control the exact time when audio playout starts.
875    */
setAudioPlayout(boolean playout)876   public void setAudioPlayout(boolean playout) {
877     nativeSetAudioPlayout(playout);
878   }
879 
880   /**
881    * Enables/disables recording of transmitted audio streams. Enabled by default.
882    *
883    * Note that even if recording is enabled, streams will only be recorded if
884    * the appropriate SDP is also applied. The main purpose of this API is to
885    * be able to control the exact time when audio recording starts.
886    */
setAudioRecording(boolean recording)887   public void setAudioRecording(boolean recording) {
888     nativeSetAudioRecording(recording);
889   }
890 
setConfiguration(RTCConfiguration config)891   public boolean setConfiguration(RTCConfiguration config) {
892     return nativeSetConfiguration(config);
893   }
894 
addIceCandidate(IceCandidate candidate)895   public boolean addIceCandidate(IceCandidate candidate) {
896     return nativeAddIceCandidate(candidate.sdpMid, candidate.sdpMLineIndex, candidate.sdp);
897   }
898 
removeIceCandidates(final IceCandidate[] candidates)899   public boolean removeIceCandidates(final IceCandidate[] candidates) {
900     return nativeRemoveIceCandidates(candidates);
901   }
902 
903   /**
904    * Adds a new MediaStream to be sent on this peer connection.
905    * Note: This method is not supported with SdpSemantics.UNIFIED_PLAN. Please
906    * use addTrack instead.
907    */
addStream(MediaStream stream)908   public boolean addStream(MediaStream stream) {
909     boolean ret = nativeAddLocalStream(stream.getNativeMediaStream());
910     if (!ret) {
911       return false;
912     }
913     localStreams.add(stream);
914     return true;
915   }
916 
917   /**
918    * Removes the given media stream from this peer connection.
919    * This method is not supported with SdpSemantics.UNIFIED_PLAN. Please use
920    * removeTrack instead.
921    */
removeStream(MediaStream stream)922   public void removeStream(MediaStream stream) {
923     nativeRemoveLocalStream(stream.getNativeMediaStream());
924     localStreams.remove(stream);
925   }
926 
927   /**
928    * Creates an RtpSender without a track.
929    *
930    * <p>This method allows an application to cause the PeerConnection to negotiate
931    * sending/receiving a specific media type, but without having a track to
932    * send yet.
933    *
934    * <p>When the application does want to begin sending a track, it can call
935    * RtpSender.setTrack, which doesn't require any additional SDP negotiation.
936    *
937    * <p>Example use:
938    * <pre>
939    * {@code
940    * audioSender = pc.createSender("audio", "stream1");
941    * videoSender = pc.createSender("video", "stream1");
942    * // Do normal SDP offer/answer, which will kick off ICE/DTLS and negotiate
943    * // media parameters....
944    * // Later, when the endpoint is ready to actually begin sending:
945    * audioSender.setTrack(audioTrack, false);
946    * videoSender.setTrack(videoTrack, false);
947    * }
948    * </pre>
949    * <p>Note: This corresponds most closely to "addTransceiver" in the official
950    * WebRTC API, in that it creates a sender without a track. It was
951    * implemented before addTransceiver because it provides useful
952    * functionality, and properly implementing transceivers would have required
953    * a great deal more work.
954    *
955    * <p>Note: This is only available with SdpSemantics.PLAN_B specified. Please use
956    * addTransceiver instead.
957    *
958    * @param kind      Corresponds to MediaStreamTrack kinds (must be "audio" or
959    *                  "video").
960    * @param stream_id The ID of the MediaStream that this sender's track will
961    *                  be associated with when SDP is applied to the remote
962    *                  PeerConnection. If createSender is used to create an
963    *                  audio and video sender that should be synchronized, they
964    *                  should use the same stream ID.
965    * @return          A new RtpSender object if successful, or null otherwise.
966    */
createSender(String kind, String stream_id)967   public RtpSender createSender(String kind, String stream_id) {
968     RtpSender newSender = nativeCreateSender(kind, stream_id);
969     if (newSender != null) {
970       senders.add(newSender);
971     }
972     return newSender;
973   }
974 
975   /**
976    * Gets all RtpSenders associated with this peer connection.
977    * Note that calling getSenders will dispose of the senders previously
978    * returned.
979    */
getSenders()980   public List<RtpSender> getSenders() {
981     for (RtpSender sender : senders) {
982       sender.dispose();
983     }
984     senders = nativeGetSenders();
985     return Collections.unmodifiableList(senders);
986   }
987 
988   /**
989    * Gets all RtpReceivers associated with this peer connection.
990    * Note that calling getReceivers will dispose of the receivers previously
991    * returned.
992    */
getReceivers()993   public List<RtpReceiver> getReceivers() {
994     for (RtpReceiver receiver : receivers) {
995       receiver.dispose();
996     }
997     receivers = nativeGetReceivers();
998     return Collections.unmodifiableList(receivers);
999   }
1000 
1001   /**
1002    * Gets all RtpTransceivers associated with this peer connection.
1003    * Note that calling getTransceivers will dispose of the transceivers previously
1004    * returned.
1005    * Note: This is only available with SdpSemantics.UNIFIED_PLAN specified.
1006    */
getTransceivers()1007   public List<RtpTransceiver> getTransceivers() {
1008     for (RtpTransceiver transceiver : transceivers) {
1009       transceiver.dispose();
1010     }
1011     transceivers = nativeGetTransceivers();
1012     return Collections.unmodifiableList(transceivers);
1013   }
1014 
1015   /**
1016    * Adds a new media stream track to be sent on this peer connection, and returns
1017    * the newly created RtpSender. If streamIds are specified, the RtpSender will
1018    * be associated with the streams specified in the streamIds list.
1019    *
1020    * @throws IllegalStateException if an error accors in C++ addTrack.
1021    *         An error can occur if:
1022    *           - A sender already exists for the track.
1023    *           - The peer connection is closed.
1024    */
addTrack(MediaStreamTrack track)1025   public RtpSender addTrack(MediaStreamTrack track) {
1026     return addTrack(track, Collections.emptyList());
1027   }
1028 
addTrack(MediaStreamTrack track, List<String> streamIds)1029   public RtpSender addTrack(MediaStreamTrack track, List<String> streamIds) {
1030     if (track == null || streamIds == null) {
1031       throw new NullPointerException("No MediaStreamTrack specified in addTrack.");
1032     }
1033     RtpSender newSender = nativeAddTrack(track.getNativeMediaStreamTrack(), streamIds);
1034     if (newSender == null) {
1035       throw new IllegalStateException("C++ addTrack failed.");
1036     }
1037     senders.add(newSender);
1038     return newSender;
1039   }
1040 
1041   /**
1042    * Stops sending media from sender. The sender will still appear in getSenders. Future
1043    * calls to createOffer will mark the m section for the corresponding transceiver as
1044    * receive only or inactive, as defined in JSEP. Returns true on success.
1045    */
removeTrack(RtpSender sender)1046   public boolean removeTrack(RtpSender sender) {
1047     if (sender == null) {
1048       throw new NullPointerException("No RtpSender specified for removeTrack.");
1049     }
1050     return nativeRemoveTrack(sender.getNativeRtpSender());
1051   }
1052 
1053   /**
1054    * Creates a new RtpTransceiver and adds it to the set of transceivers. Adding a
1055    * transceiver will cause future calls to CreateOffer to add a media description
1056    * for the corresponding transceiver.
1057    *
1058    * <p>The initial value of |mid| in the returned transceiver is null. Setting a
1059    * new session description may change it to a non-null value.
1060    *
1061    * <p>https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-addtransceiver
1062    *
1063    * <p>If a MediaStreamTrack is specified then a transceiver will be added with a
1064    * sender set to transmit the given track. The kind
1065    * of the transceiver (and sender/receiver) will be derived from the kind of
1066    * the track.
1067    *
1068    * <p>If MediaType is specified then a transceiver will be added based upon that type.
1069    * This can be either MEDIA_TYPE_AUDIO or MEDIA_TYPE_VIDEO.
1070    *
1071    * <p>Optionally, an RtpTransceiverInit structure can be specified to configure
1072    * the transceiver from construction. If not specified, the transceiver will
1073    * default to having a direction of kSendRecv and not be part of any streams.
1074    *
1075    * <p>Note: These methods are only available with SdpSemantics.UNIFIED_PLAN specified.
1076    * @throws IllegalStateException if an error accors in C++ addTransceiver
1077    */
addTransceiver(MediaStreamTrack track)1078   public RtpTransceiver addTransceiver(MediaStreamTrack track) {
1079     return addTransceiver(track, new RtpTransceiver.RtpTransceiverInit());
1080   }
1081 
addTransceiver( MediaStreamTrack track, @Nullable RtpTransceiver.RtpTransceiverInit init)1082   public RtpTransceiver addTransceiver(
1083       MediaStreamTrack track, @Nullable RtpTransceiver.RtpTransceiverInit init) {
1084     if (track == null) {
1085       throw new NullPointerException("No MediaStreamTrack specified for addTransceiver.");
1086     }
1087     if (init == null) {
1088       init = new RtpTransceiver.RtpTransceiverInit();
1089     }
1090     RtpTransceiver newTransceiver =
1091         nativeAddTransceiverWithTrack(track.getNativeMediaStreamTrack(), init);
1092     if (newTransceiver == null) {
1093       throw new IllegalStateException("C++ addTransceiver failed.");
1094     }
1095     transceivers.add(newTransceiver);
1096     return newTransceiver;
1097   }
1098 
addTransceiver(MediaStreamTrack.MediaType mediaType)1099   public RtpTransceiver addTransceiver(MediaStreamTrack.MediaType mediaType) {
1100     return addTransceiver(mediaType, new RtpTransceiver.RtpTransceiverInit());
1101   }
1102 
addTransceiver( MediaStreamTrack.MediaType mediaType, @Nullable RtpTransceiver.RtpTransceiverInit init)1103   public RtpTransceiver addTransceiver(
1104       MediaStreamTrack.MediaType mediaType, @Nullable RtpTransceiver.RtpTransceiverInit init) {
1105     if (mediaType == null) {
1106       throw new NullPointerException("No MediaType specified for addTransceiver.");
1107     }
1108     if (init == null) {
1109       init = new RtpTransceiver.RtpTransceiverInit();
1110     }
1111     RtpTransceiver newTransceiver = nativeAddTransceiverOfType(mediaType, init);
1112     if (newTransceiver == null) {
1113       throw new IllegalStateException("C++ addTransceiver failed.");
1114     }
1115     transceivers.add(newTransceiver);
1116     return newTransceiver;
1117   }
1118 
1119   // Older, non-standard implementation of getStats.
1120   @Deprecated
getStats(StatsObserver observer, @Nullable MediaStreamTrack track)1121   public boolean getStats(StatsObserver observer, @Nullable MediaStreamTrack track) {
1122     return nativeOldGetStats(observer, (track == null) ? 0 : track.getNativeMediaStreamTrack());
1123   }
1124 
1125   /**
1126    * Gets stats using the new stats collection API, see webrtc/api/stats/. These
1127    * will replace old stats collection API when the new API has matured enough.
1128    */
getStats(RTCStatsCollectorCallback callback)1129   public void getStats(RTCStatsCollectorCallback callback) {
1130     nativeNewGetStats(callback);
1131   }
1132 
1133   /**
1134    * Limits the bandwidth allocated for all RTP streams sent by this
1135    * PeerConnection. Pass null to leave a value unchanged.
1136    */
setBitrate(Integer min, Integer current, Integer max)1137   public boolean setBitrate(Integer min, Integer current, Integer max) {
1138     return nativeSetBitrate(min, current, max);
1139   }
1140 
1141   /**
1142    * Starts recording an RTC event log.
1143    *
1144    * Ownership of the file is transfered to the native code. If an RTC event
1145    * log is already being recorded, it will be stopped and a new one will start
1146    * using the provided file. Logging will continue until the stopRtcEventLog
1147    * function is called. The max_size_bytes argument is ignored, it is added
1148    * for future use.
1149    */
startRtcEventLog(int file_descriptor, int max_size_bytes)1150   public boolean startRtcEventLog(int file_descriptor, int max_size_bytes) {
1151     return nativeStartRtcEventLog(file_descriptor, max_size_bytes);
1152   }
1153 
1154   /**
1155    * Stops recording an RTC event log. If no RTC event log is currently being
1156    * recorded, this call will have no effect.
1157    */
stopRtcEventLog()1158   public void stopRtcEventLog() {
1159     nativeStopRtcEventLog();
1160   }
1161 
1162   // TODO(fischman): add support for DTMF-related methods once that API
1163   // stabilizes.
signalingState()1164   public SignalingState signalingState() {
1165     return nativeSignalingState();
1166   }
1167 
iceConnectionState()1168   public IceConnectionState iceConnectionState() {
1169     return nativeIceConnectionState();
1170   }
1171 
connectionState()1172   public PeerConnectionState connectionState() {
1173     return nativeConnectionState();
1174   }
1175 
iceGatheringState()1176   public IceGatheringState iceGatheringState() {
1177     return nativeIceGatheringState();
1178   }
1179 
close()1180   public void close() {
1181     nativeClose();
1182   }
1183 
1184   /**
1185    * Free native resources associated with this PeerConnection instance.
1186    *
1187    * This method removes a reference count from the C++ PeerConnection object,
1188    * which should result in it being destroyed. It also calls equivalent
1189    * "dispose" methods on the Java objects attached to this PeerConnection
1190    * (streams, senders, receivers), such that their associated C++ objects
1191    * will also be destroyed.
1192    *
1193    * <p>Note that this method cannot be safely called from an observer callback
1194    * (PeerConnection.Observer, DataChannel.Observer, etc.). If you want to, for
1195    * example, destroy the PeerConnection after an "ICE failed" callback, you
1196    * must do this asynchronously (in other words, unwind the stack first). See
1197    * <a href="https://bugs.chromium.org/p/webrtc/issues/detail?id=3721">bug
1198    * 3721</a> for more details.
1199    */
dispose()1200   public void dispose() {
1201     close();
1202     for (MediaStream stream : localStreams) {
1203       nativeRemoveLocalStream(stream.getNativeMediaStream());
1204       stream.dispose();
1205     }
1206     localStreams.clear();
1207     for (RtpSender sender : senders) {
1208       sender.dispose();
1209     }
1210     senders.clear();
1211     for (RtpReceiver receiver : receivers) {
1212       receiver.dispose();
1213     }
1214     for (RtpTransceiver transceiver : transceivers) {
1215       transceiver.dispose();
1216     }
1217     transceivers.clear();
1218     receivers.clear();
1219     nativeFreeOwnedPeerConnection(nativePeerConnection);
1220   }
1221 
1222   /** Returns a pointer to the native webrtc::PeerConnectionInterface. */
getNativePeerConnection()1223   public long getNativePeerConnection() {
1224     return nativeGetNativePeerConnection();
1225   }
1226 
1227   @CalledByNative
getNativeOwnedPeerConnection()1228   long getNativeOwnedPeerConnection() {
1229     return nativePeerConnection;
1230   }
1231 
createNativePeerConnectionObserver(Observer observer)1232   public static long createNativePeerConnectionObserver(Observer observer) {
1233     return nativeCreatePeerConnectionObserver(observer);
1234   }
1235 
nativeGetNativePeerConnection()1236   private native long nativeGetNativePeerConnection();
nativeGetLocalDescription()1237   private native SessionDescription nativeGetLocalDescription();
nativeGetRemoteDescription()1238   private native SessionDescription nativeGetRemoteDescription();
nativeGetCertificate()1239   private native RtcCertificatePem nativeGetCertificate();
nativeCreateDataChannel(String label, DataChannel.Init init)1240   private native DataChannel nativeCreateDataChannel(String label, DataChannel.Init init);
nativeCreateOffer(SdpObserver observer, MediaConstraints constraints)1241   private native void nativeCreateOffer(SdpObserver observer, MediaConstraints constraints);
nativeCreateAnswer(SdpObserver observer, MediaConstraints constraints)1242   private native void nativeCreateAnswer(SdpObserver observer, MediaConstraints constraints);
nativeSetLocalDescription(SdpObserver observer, SessionDescription sdp)1243   private native void nativeSetLocalDescription(SdpObserver observer, SessionDescription sdp);
nativeSetRemoteDescription(SdpObserver observer, SessionDescription sdp)1244   private native void nativeSetRemoteDescription(SdpObserver observer, SessionDescription sdp);
nativeSetAudioPlayout(boolean playout)1245   private native void nativeSetAudioPlayout(boolean playout);
nativeSetAudioRecording(boolean recording)1246   private native void nativeSetAudioRecording(boolean recording);
nativeSetBitrate(Integer min, Integer current, Integer max)1247   private native boolean nativeSetBitrate(Integer min, Integer current, Integer max);
nativeSignalingState()1248   private native SignalingState nativeSignalingState();
nativeIceConnectionState()1249   private native IceConnectionState nativeIceConnectionState();
nativeConnectionState()1250   private native PeerConnectionState nativeConnectionState();
nativeIceGatheringState()1251   private native IceGatheringState nativeIceGatheringState();
nativeClose()1252   private native void nativeClose();
nativeCreatePeerConnectionObserver(Observer observer)1253   private static native long nativeCreatePeerConnectionObserver(Observer observer);
nativeFreeOwnedPeerConnection(long ownedPeerConnection)1254   private static native void nativeFreeOwnedPeerConnection(long ownedPeerConnection);
nativeSetConfiguration(RTCConfiguration config)1255   private native boolean nativeSetConfiguration(RTCConfiguration config);
nativeAddIceCandidate( String sdpMid, int sdpMLineIndex, String iceCandidateSdp)1256   private native boolean nativeAddIceCandidate(
1257       String sdpMid, int sdpMLineIndex, String iceCandidateSdp);
nativeRemoveIceCandidates(final IceCandidate[] candidates)1258   private native boolean nativeRemoveIceCandidates(final IceCandidate[] candidates);
nativeAddLocalStream(long stream)1259   private native boolean nativeAddLocalStream(long stream);
nativeRemoveLocalStream(long stream)1260   private native void nativeRemoveLocalStream(long stream);
nativeOldGetStats(StatsObserver observer, long nativeTrack)1261   private native boolean nativeOldGetStats(StatsObserver observer, long nativeTrack);
nativeNewGetStats(RTCStatsCollectorCallback callback)1262   private native void nativeNewGetStats(RTCStatsCollectorCallback callback);
nativeCreateSender(String kind, String stream_id)1263   private native RtpSender nativeCreateSender(String kind, String stream_id);
nativeGetSenders()1264   private native List<RtpSender> nativeGetSenders();
nativeGetReceivers()1265   private native List<RtpReceiver> nativeGetReceivers();
nativeGetTransceivers()1266   private native List<RtpTransceiver> nativeGetTransceivers();
nativeAddTrack(long track, List<String> streamIds)1267   private native RtpSender nativeAddTrack(long track, List<String> streamIds);
nativeRemoveTrack(long sender)1268   private native boolean nativeRemoveTrack(long sender);
nativeAddTransceiverWithTrack( long track, RtpTransceiver.RtpTransceiverInit init)1269   private native RtpTransceiver nativeAddTransceiverWithTrack(
1270       long track, RtpTransceiver.RtpTransceiverInit init);
nativeAddTransceiverOfType( MediaStreamTrack.MediaType mediaType, RtpTransceiver.RtpTransceiverInit init)1271   private native RtpTransceiver nativeAddTransceiverOfType(
1272       MediaStreamTrack.MediaType mediaType, RtpTransceiver.RtpTransceiverInit init);
nativeStartRtcEventLog(int file_descriptor, int max_size_bytes)1273   private native boolean nativeStartRtcEventLog(int file_descriptor, int max_size_bytes);
nativeStopRtcEventLog()1274   private native void nativeStopRtcEventLog();
1275 }
1276