webrtc_m130/sdk/android/api/org/webrtc/PeerConnection.java

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

1331 lines
46 KiB
Java
Raw Normal View History

/*
* Copyright 2013 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
package org.webrtc;
import android.support.annotation.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.webrtc.CandidatePairChangeEvent;
import org.webrtc.DataChannel;
import org.webrtc.MediaStreamTrack;
import org.webrtc.RtpTransceiver;
/**
* Java-land version of the PeerConnection APIs; wraps the C++ API
* http://www.webrtc.org/reference/native-apis, which in turn is inspired by the
* JS APIs: http://dev.w3.org/2011/webrtc/editor/webrtc.html and
* http://www.w3.org/TR/mediacapture-streams/
*/
public class PeerConnection {
/** Tracks PeerConnectionInterface::IceGatheringState */
public enum IceGatheringState {
NEW,
GATHERING,
COMPLETE;
@CalledByNative("IceGatheringState")
static IceGatheringState fromNativeIndex(int nativeIndex) {
return values()[nativeIndex];
}
}
/** Tracks PeerConnectionInterface::IceConnectionState */
public enum IceConnectionState {
NEW,
CHECKING,
CONNECTED,
COMPLETED,
FAILED,
DISCONNECTED,
CLOSED;
@CalledByNative("IceConnectionState")
static IceConnectionState fromNativeIndex(int nativeIndex) {
return values()[nativeIndex];
}
}
/** Tracks PeerConnectionInterface::PeerConnectionState */
public enum PeerConnectionState {
NEW,
CONNECTING,
CONNECTED,
DISCONNECTED,
FAILED,
CLOSED;
@CalledByNative("PeerConnectionState")
static PeerConnectionState fromNativeIndex(int nativeIndex) {
return values()[nativeIndex];
}
}
Add disabled certificate check support to IceServer PeerConnection API. Refactor "OPT_SSLTCP" renaming it to "OPT_TLS_FAKE", making it clear that it's not actually some kind of SSL over TCP. Also making it clear that it's mutually exclusive with OPT_TLS. Maintaining deprecated backwards compatible support for "OPT_SSLTCP". Add "OPT_TLS_INSECURE" that implements the new certificate-check disabled TLS mode, which is also mutually exclusive with the other TLS options. PortAllocator: Add a new TLS policy enum TlsCertPolicy which defines the new insecure mode and added it as a RelayCredentials member. TurnPort: Add new TLS policy member with appropriate getter and setter to avoid constructor bloat. Initialize it from the RelayCredentials after the TurnPort is created. Expose the new feature in the PeerConnection API via IceServer.tls_certificate_policy as well as via the Android JNI PeerConnection API. For security reasons we ensure that: 1) The policy is always explicitly initialized to secure. 2) API users have to explicitly integrate with the feature to use it, and will otherwise get no change in behavior. 3) The feature is not immediately exposed in non-native contexts. For example, disabling of certificate validation is not implemented via URI parsing since this would immediately allow it to be used from a web page. This is a second attempt of https://codereview.webrtc.org/2557803002/ which was rolled back in https://codereview.webrtc.org/2590153002/ BUG=webrtc:6840 Review-Url: https://codereview.webrtc.org/2594623002 Cr-Commit-Position: refs/heads/master@{#15967}
2017-01-09 08:35:45 -08:00
/** Tracks PeerConnectionInterface::TlsCertPolicy */
public enum TlsCertPolicy {
TLS_CERT_POLICY_SECURE,
TLS_CERT_POLICY_INSECURE_NO_CHECK,
}
/** Tracks PeerConnectionInterface::SignalingState */
public enum SignalingState {
STABLE,
HAVE_LOCAL_OFFER,
HAVE_LOCAL_PRANSWER,
HAVE_REMOTE_OFFER,
HAVE_REMOTE_PRANSWER,
CLOSED;
@CalledByNative("SignalingState")
static SignalingState fromNativeIndex(int nativeIndex) {
return values()[nativeIndex];
}
}
/** Java version of PeerConnectionObserver. */
public static interface Observer {
/** Triggered when the SignalingState changes. */
@CalledByNative("Observer") void onSignalingChange(SignalingState newState);
/** Triggered when the IceConnectionState changes. */
@CalledByNative("Observer") void onIceConnectionChange(IceConnectionState newState);
/* Triggered when the standard-compliant state transition of IceConnectionState happens. */
@CalledByNative("Observer")
default void onStandardizedIceConnectionChange(IceConnectionState newState) {}
/** Triggered when the PeerConnectionState changes. */
@CalledByNative("Observer")
default void onConnectionChange(PeerConnectionState newState) {}
/** Triggered when the ICE connection receiving status changes. */
@CalledByNative("Observer") void onIceConnectionReceivingChange(boolean receiving);
/** Triggered when the IceGatheringState changes. */
@CalledByNative("Observer") void onIceGatheringChange(IceGatheringState newState);
/** Triggered when a new ICE candidate has been found. */
@CalledByNative("Observer") void onIceCandidate(IceCandidate candidate);
/** Triggered when some ICE candidates have been removed. */
@CalledByNative("Observer") void onIceCandidatesRemoved(IceCandidate[] candidates);
/** Triggered when the ICE candidate pair is changed. */
@CalledByNative("Observer")
default void onSelectedCandidatePairChanged(CandidatePairChangeEvent event) {}
/** Triggered when media is received on a new stream from remote peer. */
@CalledByNative("Observer") void onAddStream(MediaStream stream);
/** Triggered when a remote peer close a stream. */
@CalledByNative("Observer") void onRemoveStream(MediaStream stream);
/** Triggered when a remote peer opens a DataChannel. */
@CalledByNative("Observer") void onDataChannel(DataChannel dataChannel);
/** Triggered when renegotiation is necessary. */
@CalledByNative("Observer") void onRenegotiationNeeded();
/**
* Triggered when a new track is signaled by the remote peer, as a result of
* setRemoteDescription.
*/
2021-05-25 10:35:10 +02:00
@CalledByNative("Observer")
default void onAddTrack(RtpReceiver receiver, MediaStream[] mediaStreams){};
/**
* Triggered when a previously added remote track is removed by the remote
* peer, as a result of setRemoteDescription.
*/
@CalledByNative("Observer") default void onRemoveTrack(RtpReceiver receiver){};
/**
* Triggered when the signaling from SetRemoteDescription indicates that a transceiver
* will be receiving media from a remote endpoint. This is only called if UNIFIED_PLAN
* semantics are specified. The transceiver will be disposed automatically.
*/
@CalledByNative("Observer") default void onTrack(RtpTransceiver transceiver){};
}
/** Java version of PeerConnectionInterface.IceServer. */
public static class IceServer {
// List of URIs associated with this server. Valid formats are described
// in RFC7064 and RFC7065, and more may be added in the future. The "host"
// part of the URI may contain either an IP address or a hostname.
@Deprecated public final String uri;
public final List<String> urls;
public final String username;
public final String password;
public final TlsCertPolicy tlsCertPolicy;
// If the URIs in `urls` only contain IP addresses, this field can be used
// to indicate the hostname, which may be necessary for TLS (using the SNI
// extension). If `urls` itself contains the hostname, this isn't
// necessary.
public final String hostname;
// List of protocols to be used in the TLS ALPN extension.
public final List<String> tlsAlpnProtocols;
// List of elliptic curves to be used in the TLS elliptic curves extension.
// Only curve names supported by OpenSSL should be used (eg. "P-256","X25519").
public final List<String> tlsEllipticCurves;
/** Convenience constructor for STUN servers. */
@Deprecated
public IceServer(String uri) {
this(uri, "", "");
}
@Deprecated
public IceServer(String uri, String username, String password) {
Add disabled certificate check support to IceServer PeerConnection API. Refactor "OPT_SSLTCP" renaming it to "OPT_TLS_FAKE", making it clear that it's not actually some kind of SSL over TCP. Also making it clear that it's mutually exclusive with OPT_TLS. Maintaining deprecated backwards compatible support for "OPT_SSLTCP". Add "OPT_TLS_INSECURE" that implements the new certificate-check disabled TLS mode, which is also mutually exclusive with the other TLS options. PortAllocator: Add a new TLS policy enum TlsCertPolicy which defines the new insecure mode and added it as a RelayCredentials member. TurnPort: Add new TLS policy member with appropriate getter and setter to avoid constructor bloat. Initialize it from the RelayCredentials after the TurnPort is created. Expose the new feature in the PeerConnection API via IceServer.tls_certificate_policy as well as via the Android JNI PeerConnection API. For security reasons we ensure that: 1) The policy is always explicitly initialized to secure. 2) API users have to explicitly integrate with the feature to use it, and will otherwise get no change in behavior. 3) The feature is not immediately exposed in non-native contexts. For example, disabling of certificate validation is not implemented via URI parsing since this would immediately allow it to be used from a web page. This is a second attempt of https://codereview.webrtc.org/2557803002/ which was rolled back in https://codereview.webrtc.org/2590153002/ BUG=webrtc:6840 Review-Url: https://codereview.webrtc.org/2594623002 Cr-Commit-Position: refs/heads/master@{#15967}
2017-01-09 08:35:45 -08:00
this(uri, username, password, TlsCertPolicy.TLS_CERT_POLICY_SECURE);
}
@Deprecated
Add disabled certificate check support to IceServer PeerConnection API. Refactor "OPT_SSLTCP" renaming it to "OPT_TLS_FAKE", making it clear that it's not actually some kind of SSL over TCP. Also making it clear that it's mutually exclusive with OPT_TLS. Maintaining deprecated backwards compatible support for "OPT_SSLTCP". Add "OPT_TLS_INSECURE" that implements the new certificate-check disabled TLS mode, which is also mutually exclusive with the other TLS options. PortAllocator: Add a new TLS policy enum TlsCertPolicy which defines the new insecure mode and added it as a RelayCredentials member. TurnPort: Add new TLS policy member with appropriate getter and setter to avoid constructor bloat. Initialize it from the RelayCredentials after the TurnPort is created. Expose the new feature in the PeerConnection API via IceServer.tls_certificate_policy as well as via the Android JNI PeerConnection API. For security reasons we ensure that: 1) The policy is always explicitly initialized to secure. 2) API users have to explicitly integrate with the feature to use it, and will otherwise get no change in behavior. 3) The feature is not immediately exposed in non-native contexts. For example, disabling of certificate validation is not implemented via URI parsing since this would immediately allow it to be used from a web page. This is a second attempt of https://codereview.webrtc.org/2557803002/ which was rolled back in https://codereview.webrtc.org/2590153002/ BUG=webrtc:6840 Review-Url: https://codereview.webrtc.org/2594623002 Cr-Commit-Position: refs/heads/master@{#15967}
2017-01-09 08:35:45 -08:00
public IceServer(String uri, String username, String password, TlsCertPolicy tlsCertPolicy) {
this(uri, username, password, tlsCertPolicy, "");
}
@Deprecated
public IceServer(String uri, String username, String password, TlsCertPolicy tlsCertPolicy,
String hostname) {
this(uri, Collections.singletonList(uri), username, password, tlsCertPolicy, hostname, null,
null);
}
private IceServer(String uri, List<String> urls, String username, String password,
TlsCertPolicy tlsCertPolicy, String hostname, List<String> tlsAlpnProtocols,
List<String> tlsEllipticCurves) {
if (uri == null || urls == null || urls.isEmpty()) {
throw new IllegalArgumentException("uri == null || urls == null || urls.isEmpty()");
}
for (String it : urls) {
if (it == null) {
throw new IllegalArgumentException("urls element is null: " + urls);
}
}
if (username == null) {
throw new IllegalArgumentException("username == null");
}
if (password == null) {
throw new IllegalArgumentException("password == null");
}
if (hostname == null) {
throw new IllegalArgumentException("hostname == null");
}
this.uri = uri;
this.urls = urls;
this.username = username;
this.password = password;
Add disabled certificate check support to IceServer PeerConnection API. Refactor "OPT_SSLTCP" renaming it to "OPT_TLS_FAKE", making it clear that it's not actually some kind of SSL over TCP. Also making it clear that it's mutually exclusive with OPT_TLS. Maintaining deprecated backwards compatible support for "OPT_SSLTCP". Add "OPT_TLS_INSECURE" that implements the new certificate-check disabled TLS mode, which is also mutually exclusive with the other TLS options. PortAllocator: Add a new TLS policy enum TlsCertPolicy which defines the new insecure mode and added it as a RelayCredentials member. TurnPort: Add new TLS policy member with appropriate getter and setter to avoid constructor bloat. Initialize it from the RelayCredentials after the TurnPort is created. Expose the new feature in the PeerConnection API via IceServer.tls_certificate_policy as well as via the Android JNI PeerConnection API. For security reasons we ensure that: 1) The policy is always explicitly initialized to secure. 2) API users have to explicitly integrate with the feature to use it, and will otherwise get no change in behavior. 3) The feature is not immediately exposed in non-native contexts. For example, disabling of certificate validation is not implemented via URI parsing since this would immediately allow it to be used from a web page. This is a second attempt of https://codereview.webrtc.org/2557803002/ which was rolled back in https://codereview.webrtc.org/2590153002/ BUG=webrtc:6840 Review-Url: https://codereview.webrtc.org/2594623002 Cr-Commit-Position: refs/heads/master@{#15967}
2017-01-09 08:35:45 -08:00
this.tlsCertPolicy = tlsCertPolicy;
this.hostname = hostname;
this.tlsAlpnProtocols = tlsAlpnProtocols;
this.tlsEllipticCurves = tlsEllipticCurves;
}
@Override
public String toString() {
return urls + " [" + username + ":" + password + "] [" + tlsCertPolicy + "] [" + hostname
+ "] [" + tlsAlpnProtocols + "] [" + tlsEllipticCurves + "]";
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj == null) {
return false;
}
if (obj == this) {
return true;
}
if (!(obj instanceof IceServer)) {
return false;
}
IceServer other = (IceServer) obj;
return (uri.equals(other.uri) && urls.equals(other.urls) && username.equals(other.username)
&& password.equals(other.password) && tlsCertPolicy.equals(other.tlsCertPolicy)
&& hostname.equals(other.hostname) && tlsAlpnProtocols.equals(other.tlsAlpnProtocols)
&& tlsEllipticCurves.equals(other.tlsEllipticCurves));
}
@Override
public int hashCode() {
Object[] values = {uri, urls, username, password, tlsCertPolicy, hostname, tlsAlpnProtocols,
tlsEllipticCurves};
return Arrays.hashCode(values);
}
public static Builder builder(String uri) {
return new Builder(Collections.singletonList(uri));
}
public static Builder builder(List<String> urls) {
return new Builder(urls);
}
public static class Builder {
@Nullable private final List<String> urls;
private String username = "";
private String password = "";
private TlsCertPolicy tlsCertPolicy = TlsCertPolicy.TLS_CERT_POLICY_SECURE;
private String hostname = "";
private List<String> tlsAlpnProtocols;
private List<String> tlsEllipticCurves;
private Builder(List<String> urls) {
if (urls == null || urls.isEmpty()) {
throw new IllegalArgumentException("urls == null || urls.isEmpty(): " + urls);
}
this.urls = urls;
}
public Builder setUsername(String username) {
this.username = username;
return this;
}
public Builder setPassword(String password) {
this.password = password;
return this;
}
public Builder setTlsCertPolicy(TlsCertPolicy tlsCertPolicy) {
this.tlsCertPolicy = tlsCertPolicy;
return this;
}
public Builder setHostname(String hostname) {
this.hostname = hostname;
return this;
}
public Builder setTlsAlpnProtocols(List<String> tlsAlpnProtocols) {
this.tlsAlpnProtocols = tlsAlpnProtocols;
return this;
}
public Builder setTlsEllipticCurves(List<String> tlsEllipticCurves) {
this.tlsEllipticCurves = tlsEllipticCurves;
return this;
}
public IceServer createIceServer() {
return new IceServer(urls.get(0), urls, username, password, tlsCertPolicy, hostname,
tlsAlpnProtocols, tlsEllipticCurves);
}
}
@Nullable
@CalledByNative("IceServer")
List<String> getUrls() {
return urls;
}
@Nullable
@CalledByNative("IceServer")
String getUsername() {
return username;
}
@Nullable
@CalledByNative("IceServer")
String getPassword() {
return password;
}
@CalledByNative("IceServer")
TlsCertPolicy getTlsCertPolicy() {
return tlsCertPolicy;
}
@Nullable
@CalledByNative("IceServer")
String getHostname() {
return hostname;
}
@CalledByNative("IceServer")
List<String> getTlsAlpnProtocols() {
return tlsAlpnProtocols;
}
@CalledByNative("IceServer")
List<String> getTlsEllipticCurves() {
return tlsEllipticCurves;
}
}
/** Java version of PeerConnectionInterface.IceTransportsType */
public enum IceTransportsType { NONE, RELAY, NOHOST, ALL }
/** Java version of PeerConnectionInterface.BundlePolicy */
public enum BundlePolicy { BALANCED, MAXBUNDLE, MAXCOMPAT }
/** Java version of PeerConnectionInterface.RtcpMuxPolicy */
public enum RtcpMuxPolicy { NEGOTIATE, REQUIRE }
/** Java version of PeerConnectionInterface.TcpCandidatePolicy */
public enum TcpCandidatePolicy { ENABLED, DISABLED }
/** Java version of PeerConnectionInterface.CandidateNetworkPolicy */
public enum CandidateNetworkPolicy { ALL, LOW_COST }
// Keep in sync with webrtc/rtc_base/network_constants.h.
public enum AdapterType {
UNKNOWN(0),
ETHERNET(1 << 0),
WIFI(1 << 1),
CELLULAR(1 << 2),
VPN(1 << 3),
LOOPBACK(1 << 4),
ADAPTER_TYPE_ANY(1 << 5),
CELLULAR_2G(1 << 6),
CELLULAR_3G(1 << 7),
CELLULAR_4G(1 << 8),
CELLULAR_5G(1 << 9);
public final Integer bitMask;
private AdapterType(Integer bitMask) {
this.bitMask = bitMask;
}
private static final Map<Integer, AdapterType> BY_BITMASK = new HashMap<>();
static {
for (AdapterType t : values()) {
BY_BITMASK.put(t.bitMask, t);
}
}
@Nullable
@CalledByNative("AdapterType")
static AdapterType fromNativeIndex(int nativeIndex) {
return BY_BITMASK.get(nativeIndex);
}
}
/** Java version of rtc::KeyType */
public enum KeyType { RSA, ECDSA }
/** Java version of PeerConnectionInterface.ContinualGatheringPolicy */
public enum ContinualGatheringPolicy { GATHER_ONCE, GATHER_CONTINUALLY }
/** Java version of webrtc::PortPrunePolicy */
public enum PortPrunePolicy {
NO_PRUNE, // Do not prune turn port.
PRUNE_BASED_ON_PRIORITY, // Prune turn port based the priority on the same network
KEEP_FIRST_READY // Keep the first ready port and prune the rest on the same network.
}
/**
* Java version of webrtc::SdpSemantics.
*
* Configure the SDP semantics used by this PeerConnection. Note that the
* WebRTC 1.0 specification requires UNIFIED_PLAN semantics. The
* RtpTransceiver API is only available with UNIFIED_PLAN semantics.
*
* <p>PLAN_B will cause PeerConnection to create offers and answers with at
* most one audio and one video m= section with multiple RtpSenders and
* RtpReceivers specified as multiple a=ssrc lines within the section. This
* will also cause PeerConnection to ignore all but the first m= section of
* the same media type.
*
* <p>UNIFIED_PLAN will cause PeerConnection to create offers and answers with
* multiple m= sections where each m= section maps to one RtpSender and one
* RtpReceiver (an RtpTransceiver), either both audio or both video. This
* will also cause PeerConnection to ignore all but the first a=ssrc lines
* that form a Plan B stream.
*
* <p>For users who wish to send multiple audio/video streams and need to stay
* interoperable with legacy WebRTC implementations, specify PLAN_B.
*
* <p>For users who wish to send multiple audio/video streams and/or wish to
* use the new RtpTransceiver API, specify UNIFIED_PLAN.
*/
public enum SdpSemantics { PLAN_B, UNIFIED_PLAN }
/** Java version of PeerConnectionInterface.RTCConfiguration */
// TODO(qingsi): Resolve the naming inconsistency of fields with/without units.
public static class RTCConfiguration {
public IceTransportsType iceTransportsType;
public List<IceServer> iceServers;
public BundlePolicy bundlePolicy;
@Nullable public RtcCertificatePem certificate;
public RtcpMuxPolicy rtcpMuxPolicy;
public TcpCandidatePolicy tcpCandidatePolicy;
public CandidateNetworkPolicy candidateNetworkPolicy;
public int audioJitterBufferMaxPackets;
public boolean audioJitterBufferFastAccelerate;
public int iceConnectionReceivingTimeout;
public int iceBackupCandidatePairPingInterval;
public KeyType keyType;
public ContinualGatheringPolicy continualGatheringPolicy;
public int iceCandidatePoolSize;
@Deprecated // by the turnPortPrunePolicy. See bugs.webrtc.org/11026
public boolean pruneTurnPorts;
public PortPrunePolicy turnPortPrunePolicy;
public boolean presumeWritableWhenFullyRelayed;
public boolean surfaceIceCandidatesOnIceTransportTypeChanged;
// The following fields define intervals in milliseconds at which ICE
// connectivity checks are sent.
//
// We consider ICE is "strongly connected" for an agent when there is at
// least one candidate pair that currently succeeds in connectivity check
// from its direction i.e. sending a ping and receives a ping response, AND
// all candidate pairs have sent a minimum number of pings for connectivity
// (this number is implementation-specific). Otherwise, ICE is considered in
// "weak connectivity".
//
// Note that the above notion of strong and weak connectivity is not defined
// in RFC 5245, and they apply to our current ICE implementation only.
//
// 1) iceCheckIntervalStrongConnectivityMs defines the interval applied to
// ALL candidate pairs when ICE is strongly connected,
// 2) iceCheckIntervalWeakConnectivityMs defines the counterpart for ALL
// pairs when ICE is weakly connected, and
// 3) iceCheckMinInterval defines the minimal interval (equivalently the
// maximum rate) that overrides the above two intervals when either of them
// is less.
@Nullable public Integer iceCheckIntervalStrongConnectivityMs;
@Nullable public Integer iceCheckIntervalWeakConnectivityMs;
@Nullable public Integer iceCheckMinInterval;
// The time period in milliseconds for which a candidate pair must wait for response to
// connectivitiy checks before it becomes unwritable.
@Nullable public Integer iceUnwritableTimeMs;
// The minimum number of connectivity checks that a candidate pair must sent without receiving
// response before it becomes unwritable.
@Nullable public Integer iceUnwritableMinChecks;
// The interval in milliseconds at which STUN candidates will resend STUN binding requests
// to keep NAT bindings open.
// The default value in the implementation is used if this field is null.
@Nullable public Integer stunCandidateKeepaliveIntervalMs;
// The interval in milliseconds of pings sent when the connection is stable and writable.
// The default value in the implementation is used if this field is null.
@Nullable public Integer stableWritableConnectionPingIntervalMs;
public boolean disableIPv6OnWifi;
// By default, PeerConnection will use a limited number of IPv6 network
// interfaces, in order to avoid too many ICE candidate pairs being created
// and delaying ICE completion.
//
// Can be set to Integer.MAX_VALUE to effectively disable the limit.
public int maxIPv6Networks;
// These values will be overridden by MediaStream constraints if deprecated constraints-based
// create peerconnection interface is used.
public boolean disableIpv6;
public boolean enableDscp;
public boolean enableCpuOveruseDetection;
public boolean suspendBelowMinBitrate;
@Nullable public Integer screencastMinBitrate;
@Nullable public Boolean combinedAudioVideoBwe;
@Nullable public Boolean enableDtlsSrtp;
// Use "Unknown" to represent no preference of adapter types, not the
// preference of adapters of unknown types.
public AdapterType networkPreference;
public SdpSemantics sdpSemantics;
// This is an optional wrapper for the C++ webrtc::TurnCustomizer.
@Nullable public TurnCustomizer turnCustomizer;
// Actively reset the SRTP parameters whenever the DTLS transports underneath are reset for
// every offer/answer negotiation.This is only intended to be a workaround for crbug.com/835958
public boolean activeResetSrtpParams;
// Whether this client is allowed to switch encoding codec mid-stream. This is a workaround for
// a WebRTC bug where the receiver could get confussed if a codec switch happened mid-call.
// Null indicates no change to currently configured value.
@Nullable public Boolean allowCodecSwitching;
/**
* Defines advanced optional cryptographic settings related to SRTP and
* frame encryption for native WebRTC. Setting this will overwrite any
* options set through the PeerConnectionFactory (which is deprecated).
*/
@Nullable public CryptoOptions cryptoOptions;
/**
* An optional string that if set will be attached to the
* TURN_ALLOCATE_REQUEST which can be used to correlate client
* logs with backend logs
*/
@Nullable public String turnLoggingId;
/**
* Allow implicit rollback of local description when remote description
* conflicts with local description.
* See: https://w3c.github.io/webrtc-pc/#dom-peerconnection-setremotedescription
*/
public boolean enableImplicitRollback;
/**
* Control if "a=extmap-allow-mixed" is included in the offer.
* See: https://www.chromestatus.com/feature/6269234631933952
*/
public boolean offerExtmapAllowMixed;
// TODO(deadbeef): Instead of duplicating the defaults here, we should do
// something to pick up the defaults from C++. The Objective-C equivalent
// of RTCConfiguration does that.
public RTCConfiguration(List<IceServer> iceServers) {
iceTransportsType = IceTransportsType.ALL;
bundlePolicy = BundlePolicy.BALANCED;
rtcpMuxPolicy = RtcpMuxPolicy.REQUIRE;
tcpCandidatePolicy = TcpCandidatePolicy.ENABLED;
candidateNetworkPolicy = CandidateNetworkPolicy.ALL;
this.iceServers = iceServers;
audioJitterBufferMaxPackets = 50;
audioJitterBufferFastAccelerate = false;
iceConnectionReceivingTimeout = -1;
iceBackupCandidatePairPingInterval = -1;
keyType = KeyType.ECDSA;
continualGatheringPolicy = ContinualGatheringPolicy.GATHER_ONCE;
iceCandidatePoolSize = 0;
pruneTurnPorts = false;
turnPortPrunePolicy = PortPrunePolicy.NO_PRUNE;
presumeWritableWhenFullyRelayed = false;
surfaceIceCandidatesOnIceTransportTypeChanged = false;
iceCheckIntervalStrongConnectivityMs = null;
iceCheckIntervalWeakConnectivityMs = null;
iceCheckMinInterval = null;
iceUnwritableTimeMs = null;
iceUnwritableMinChecks = null;
stunCandidateKeepaliveIntervalMs = null;
stableWritableConnectionPingIntervalMs = null;
disableIPv6OnWifi = false;
maxIPv6Networks = 5;
disableIpv6 = false;
enableDscp = false;
enableCpuOveruseDetection = true;
suspendBelowMinBitrate = false;
screencastMinBitrate = null;
combinedAudioVideoBwe = null;
enableDtlsSrtp = null;
networkPreference = AdapterType.UNKNOWN;
sdpSemantics = SdpSemantics.PLAN_B;
activeResetSrtpParams = false;
cryptoOptions = null;
turnLoggingId = null;
allowCodecSwitching = null;
enableImplicitRollback = false;
offerExtmapAllowMixed = true;
}
@CalledByNative("RTCConfiguration")
IceTransportsType getIceTransportsType() {
return iceTransportsType;
}
@CalledByNative("RTCConfiguration")
List<IceServer> getIceServers() {
return iceServers;
}
@CalledByNative("RTCConfiguration")
BundlePolicy getBundlePolicy() {
return bundlePolicy;
}
@CalledByNative("RTCConfiguration")
PortPrunePolicy getTurnPortPrunePolicy() {
return turnPortPrunePolicy;
}
@Nullable
@CalledByNative("RTCConfiguration")
RtcCertificatePem getCertificate() {
return certificate;
}
@CalledByNative("RTCConfiguration")
RtcpMuxPolicy getRtcpMuxPolicy() {
return rtcpMuxPolicy;
}
@CalledByNative("RTCConfiguration")
TcpCandidatePolicy getTcpCandidatePolicy() {
return tcpCandidatePolicy;
}
@CalledByNative("RTCConfiguration")
CandidateNetworkPolicy getCandidateNetworkPolicy() {
return candidateNetworkPolicy;
}
@CalledByNative("RTCConfiguration")
int getAudioJitterBufferMaxPackets() {
return audioJitterBufferMaxPackets;
}
@CalledByNative("RTCConfiguration")
boolean getAudioJitterBufferFastAccelerate() {
return audioJitterBufferFastAccelerate;
}
@CalledByNative("RTCConfiguration")
int getIceConnectionReceivingTimeout() {
return iceConnectionReceivingTimeout;
}
@CalledByNative("RTCConfiguration")
int getIceBackupCandidatePairPingInterval() {
return iceBackupCandidatePairPingInterval;
}
@CalledByNative("RTCConfiguration")
KeyType getKeyType() {
return keyType;
}
@CalledByNative("RTCConfiguration")
ContinualGatheringPolicy getContinualGatheringPolicy() {
return continualGatheringPolicy;
}
@CalledByNative("RTCConfiguration")
int getIceCandidatePoolSize() {
return iceCandidatePoolSize;
}
@CalledByNative("RTCConfiguration")
boolean getPruneTurnPorts() {
return pruneTurnPorts;
}
@CalledByNative("RTCConfiguration")
boolean getPresumeWritableWhenFullyRelayed() {
return presumeWritableWhenFullyRelayed;
}
@CalledByNative("RTCConfiguration")
boolean getSurfaceIceCandidatesOnIceTransportTypeChanged() {
return surfaceIceCandidatesOnIceTransportTypeChanged;
}
@Nullable
@CalledByNative("RTCConfiguration")
Integer getIceCheckIntervalStrongConnectivity() {
return iceCheckIntervalStrongConnectivityMs;
}
@Nullable
@CalledByNative("RTCConfiguration")
Integer getIceCheckIntervalWeakConnectivity() {
return iceCheckIntervalWeakConnectivityMs;
}
@Nullable
@CalledByNative("RTCConfiguration")
Integer getIceCheckMinInterval() {
return iceCheckMinInterval;
}
@Nullable
@CalledByNative("RTCConfiguration")
Integer getIceUnwritableTimeout() {
return iceUnwritableTimeMs;
}
@Nullable
@CalledByNative("RTCConfiguration")
Integer getIceUnwritableMinChecks() {
return iceUnwritableMinChecks;
}
@Nullable
@CalledByNative("RTCConfiguration")
Integer getStunCandidateKeepaliveInterval() {
return stunCandidateKeepaliveIntervalMs;
}
@Nullable
@CalledByNative("RTCConfiguration")
Integer getStableWritableConnectionPingIntervalMs() {
return stableWritableConnectionPingIntervalMs;
}
@CalledByNative("RTCConfiguration")
boolean getDisableIPv6OnWifi() {
return disableIPv6OnWifi;
}
@CalledByNative("RTCConfiguration")
int getMaxIPv6Networks() {
return maxIPv6Networks;
}
@Nullable
@CalledByNative("RTCConfiguration")
TurnCustomizer getTurnCustomizer() {
return turnCustomizer;
}
@CalledByNative("RTCConfiguration")
boolean getDisableIpv6() {
return disableIpv6;
}
@CalledByNative("RTCConfiguration")
boolean getEnableDscp() {
return enableDscp;
}
@CalledByNative("RTCConfiguration")
boolean getEnableCpuOveruseDetection() {
return enableCpuOveruseDetection;
}
@CalledByNative("RTCConfiguration")
boolean getSuspendBelowMinBitrate() {
return suspendBelowMinBitrate;
}
@Nullable
@CalledByNative("RTCConfiguration")
Integer getScreencastMinBitrate() {
return screencastMinBitrate;
}
@Nullable
@CalledByNative("RTCConfiguration")
Boolean getCombinedAudioVideoBwe() {
return combinedAudioVideoBwe;
}
@Nullable
@CalledByNative("RTCConfiguration")
Boolean getEnableDtlsSrtp() {
return enableDtlsSrtp;
}
@CalledByNative("RTCConfiguration")
AdapterType getNetworkPreference() {
return networkPreference;
}
@CalledByNative("RTCConfiguration")
SdpSemantics getSdpSemantics() {
return sdpSemantics;
}
@CalledByNative("RTCConfiguration")
boolean getActiveResetSrtpParams() {
return activeResetSrtpParams;
}
@Nullable
@CalledByNative("RTCConfiguration")
Boolean getAllowCodecSwitching() {
return allowCodecSwitching;
}
@Nullable
@CalledByNative("RTCConfiguration")
CryptoOptions getCryptoOptions() {
return cryptoOptions;
}
@Nullable
@CalledByNative("RTCConfiguration")
String getTurnLoggingId() {
return turnLoggingId;
}
@CalledByNative("RTCConfiguration")
boolean getEnableImplicitRollback() {
return enableImplicitRollback;
}
@CalledByNative("RTCConfiguration")
boolean getOfferExtmapAllowMixed() {
return offerExtmapAllowMixed;
}
};
private final List<MediaStream> localStreams = new ArrayList<>();
private final long nativePeerConnection;
private List<RtpSender> senders = new ArrayList<>();
private List<RtpReceiver> receivers = new ArrayList<>();
private List<RtpTransceiver> transceivers = new ArrayList<>();
/**
* Wraps a PeerConnection created by the factory. Can be used by clients that want to implement
* their PeerConnection creation in JNI.
*/
public PeerConnection(NativePeerConnectionFactory factory) {
this(factory.createNativePeerConnection());
}
PeerConnection(long nativePeerConnection) {
this.nativePeerConnection = nativePeerConnection;
}
// JsepInterface.
public SessionDescription getLocalDescription() {
return nativeGetLocalDescription();
}
public SessionDescription getRemoteDescription() {
return nativeGetRemoteDescription();
}
public RtcCertificatePem getCertificate() {
return nativeGetCertificate();
}
public DataChannel createDataChannel(String label, DataChannel.Init init) {
return nativeCreateDataChannel(label, init);
}
public void createOffer(SdpObserver observer, MediaConstraints constraints) {
nativeCreateOffer(observer, constraints);
}
public void createAnswer(SdpObserver observer, MediaConstraints constraints) {
nativeCreateAnswer(observer, constraints);
}
public void setLocalDescription(SdpObserver observer) {
nativeSetLocalDescriptionAutomatically(observer);
}
public void setLocalDescription(SdpObserver observer, SessionDescription sdp) {
nativeSetLocalDescription(observer, sdp);
}
public void setRemoteDescription(SdpObserver observer, SessionDescription sdp) {
nativeSetRemoteDescription(observer, sdp);
}
/**
* Tells the PeerConnection that ICE should be restarted.
*/
public void restartIce() {
nativeRestartIce();
}
/**
* Enables/disables playout of received audio streams. Enabled by default.
*
* Note that even if playout is enabled, streams will only be played out if
* the appropriate SDP is also applied. The main purpose of this API is to
* be able to control the exact time when audio playout starts.
*/
public void setAudioPlayout(boolean playout) {
nativeSetAudioPlayout(playout);
}
/**
* Enables/disables recording of transmitted audio streams. Enabled by default.
*
* Note that even if recording is enabled, streams will only be recorded if
* the appropriate SDP is also applied. The main purpose of this API is to
* be able to control the exact time when audio recording starts.
*/
public void setAudioRecording(boolean recording) {
nativeSetAudioRecording(recording);
}
public boolean setConfiguration(RTCConfiguration config) {
return nativeSetConfiguration(config);
}
public boolean addIceCandidate(IceCandidate candidate) {
return nativeAddIceCandidate(candidate.sdpMid, candidate.sdpMLineIndex, candidate.sdp);
}
public void addIceCandidate(IceCandidate candidate, AddIceObserver observer) {
nativeAddIceCandidateWithObserver(
candidate.sdpMid, candidate.sdpMLineIndex, candidate.sdp, observer);
}
public boolean removeIceCandidates(final IceCandidate[] candidates) {
return nativeRemoveIceCandidates(candidates);
}
/**
* Adds a new MediaStream to be sent on this peer connection.
* Note: This method is not supported with SdpSemantics.UNIFIED_PLAN. Please
* use addTrack instead.
*/
public boolean addStream(MediaStream stream) {
boolean ret = nativeAddLocalStream(stream.getNativeMediaStream());
if (!ret) {
return false;
}
localStreams.add(stream);
return true;
}
/**
* Removes the given media stream from this peer connection.
* This method is not supported with SdpSemantics.UNIFIED_PLAN. Please use
* removeTrack instead.
*/
public void removeStream(MediaStream stream) {
nativeRemoveLocalStream(stream.getNativeMediaStream());
localStreams.remove(stream);
}
/**
* Creates an RtpSender without a track.
*
* <p>This method allows an application to cause the PeerConnection to negotiate
* sending/receiving a specific media type, but without having a track to
* send yet.
*
* <p>When the application does want to begin sending a track, it can call
* RtpSender.setTrack, which doesn't require any additional SDP negotiation.
*
* <p>Example use:
* <pre>
* {@code
* audioSender = pc.createSender("audio", "stream1");
* videoSender = pc.createSender("video", "stream1");
* // Do normal SDP offer/answer, which will kick off ICE/DTLS and negotiate
* // media parameters....
* // Later, when the endpoint is ready to actually begin sending:
* audioSender.setTrack(audioTrack, false);
* videoSender.setTrack(videoTrack, false);
* }
* </pre>
* <p>Note: This corresponds most closely to "addTransceiver" in the official
* WebRTC API, in that it creates a sender without a track. It was
* implemented before addTransceiver because it provides useful
* functionality, and properly implementing transceivers would have required
* a great deal more work.
*
* <p>Note: This is only available with SdpSemantics.PLAN_B specified. Please use
* addTransceiver instead.
*
* @param kind Corresponds to MediaStreamTrack kinds (must be "audio" or
* "video").
* @param stream_id The ID of the MediaStream that this sender's track will
* be associated with when SDP is applied to the remote
* PeerConnection. If createSender is used to create an
* audio and video sender that should be synchronized, they
* should use the same stream ID.
* @return A new RtpSender object if successful, or null otherwise.
*/
public RtpSender createSender(String kind, String stream_id) {
RtpSender newSender = nativeCreateSender(kind, stream_id);
if (newSender != null) {
senders.add(newSender);
}
return newSender;
}
/**
* Gets all RtpSenders associated with this peer connection.
* Note that calling getSenders will dispose of the senders previously
* returned.
*/
public List<RtpSender> getSenders() {
for (RtpSender sender : senders) {
sender.dispose();
}
senders = nativeGetSenders();
return Collections.unmodifiableList(senders);
}
/**
* Gets all RtpReceivers associated with this peer connection.
* Note that calling getReceivers will dispose of the receivers previously
* returned.
*/
public List<RtpReceiver> getReceivers() {
for (RtpReceiver receiver : receivers) {
receiver.dispose();
}
receivers = nativeGetReceivers();
return Collections.unmodifiableList(receivers);
}
/**
* Gets all RtpTransceivers associated with this peer connection.
* Note that calling getTransceivers will dispose of the transceivers previously
* returned.
* Note: This is only available with SdpSemantics.UNIFIED_PLAN specified.
*/
public List<RtpTransceiver> getTransceivers() {
for (RtpTransceiver transceiver : transceivers) {
transceiver.dispose();
}
transceivers = nativeGetTransceivers();
return Collections.unmodifiableList(transceivers);
}
/**
* Adds a new media stream track to be sent on this peer connection, and returns
* the newly created RtpSender. If streamIds are specified, the RtpSender will
* be associated with the streams specified in the streamIds list.
*
* @throws IllegalStateException if an error accors in C++ addTrack.
* An error can occur if:
* - A sender already exists for the track.
* - The peer connection is closed.
*/
public RtpSender addTrack(MediaStreamTrack track) {
return addTrack(track, Collections.emptyList());
}
public RtpSender addTrack(MediaStreamTrack track, List<String> streamIds) {
if (track == null || streamIds == null) {
throw new NullPointerException("No MediaStreamTrack specified in addTrack.");
}
RtpSender newSender = nativeAddTrack(track.getNativeMediaStreamTrack(), streamIds);
if (newSender == null) {
throw new IllegalStateException("C++ addTrack failed.");
}
senders.add(newSender);
return newSender;
}
/**
* Stops sending media from sender. The sender will still appear in getSenders. Future
* calls to createOffer will mark the m section for the corresponding transceiver as
* receive only or inactive, as defined in JSEP. Returns true on success.
*/
public boolean removeTrack(RtpSender sender) {
if (sender == null) {
throw new NullPointerException("No RtpSender specified for removeTrack.");
}
return nativeRemoveTrack(sender.getNativeRtpSender());
}
/**
* Creates a new RtpTransceiver and adds it to the set of transceivers. Adding a
* transceiver will cause future calls to CreateOffer to add a media description
* for the corresponding transceiver.
*
* <p>The initial value of `mid` in the returned transceiver is null. Setting a
* new session description may change it to a non-null value.
*
* <p>https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-addtransceiver
*
* <p>If a MediaStreamTrack is specified then a transceiver will be added with a
* sender set to transmit the given track. The kind
* of the transceiver (and sender/receiver) will be derived from the kind of
* the track.
*
* <p>If MediaType is specified then a transceiver will be added based upon that type.
* This can be either MEDIA_TYPE_AUDIO or MEDIA_TYPE_VIDEO.
*
* <p>Optionally, an RtpTransceiverInit structure can be specified to configure
* the transceiver from construction. If not specified, the transceiver will
* default to having a direction of kSendRecv and not be part of any streams.
*
* <p>Note: These methods are only available with SdpSemantics.UNIFIED_PLAN specified.
* @throws IllegalStateException if an error accors in C++ addTransceiver
*/
public RtpTransceiver addTransceiver(MediaStreamTrack track) {
return addTransceiver(track, new RtpTransceiver.RtpTransceiverInit());
}
public RtpTransceiver addTransceiver(
MediaStreamTrack track, @Nullable RtpTransceiver.RtpTransceiverInit init) {
if (track == null) {
throw new NullPointerException("No MediaStreamTrack specified for addTransceiver.");
}
if (init == null) {
init = new RtpTransceiver.RtpTransceiverInit();
}
RtpTransceiver newTransceiver =
nativeAddTransceiverWithTrack(track.getNativeMediaStreamTrack(), init);
if (newTransceiver == null) {
throw new IllegalStateException("C++ addTransceiver failed.");
}
transceivers.add(newTransceiver);
return newTransceiver;
}
public RtpTransceiver addTransceiver(MediaStreamTrack.MediaType mediaType) {
return addTransceiver(mediaType, new RtpTransceiver.RtpTransceiverInit());
}
public RtpTransceiver addTransceiver(
MediaStreamTrack.MediaType mediaType, @Nullable RtpTransceiver.RtpTransceiverInit init) {
if (mediaType == null) {
throw new NullPointerException("No MediaType specified for addTransceiver.");
}
if (init == null) {
init = new RtpTransceiver.RtpTransceiverInit();
}
RtpTransceiver newTransceiver = nativeAddTransceiverOfType(mediaType, init);
if (newTransceiver == null) {
throw new IllegalStateException("C++ addTransceiver failed.");
}
transceivers.add(newTransceiver);
return newTransceiver;
}
// Older, non-standard implementation of getStats.
@Deprecated
public boolean getStats(StatsObserver observer, @Nullable MediaStreamTrack track) {
return nativeOldGetStats(observer, (track == null) ? 0 : track.getNativeMediaStreamTrack());
}
/**
* Gets stats using the new stats collection API, see webrtc/api/stats/. These
* will replace old stats collection API when the new API has matured enough.
*/
public void getStats(RTCStatsCollectorCallback callback) {
nativeNewGetStats(callback);
}
/**
* Limits the bandwidth allocated for all RTP streams sent by this
* PeerConnection. Pass null to leave a value unchanged.
*/
public boolean setBitrate(Integer min, Integer current, Integer max) {
return nativeSetBitrate(min, current, max);
}
/**
* Starts recording an RTC event log.
*
* Ownership of the file is transfered to the native code. If an RTC event
* log is already being recorded, it will be stopped and a new one will start
* using the provided file. Logging will continue until the stopRtcEventLog
* function is called. The max_size_bytes argument is ignored, it is added
* for future use.
*/
public boolean startRtcEventLog(int file_descriptor, int max_size_bytes) {
return nativeStartRtcEventLog(file_descriptor, max_size_bytes);
}
/**
* Stops recording an RTC event log. If no RTC event log is currently being
* recorded, this call will have no effect.
*/
public void stopRtcEventLog() {
nativeStopRtcEventLog();
}
// TODO(fischman): add support for DTMF-related methods once that API
// stabilizes.
public SignalingState signalingState() {
return nativeSignalingState();
}
public IceConnectionState iceConnectionState() {
return nativeIceConnectionState();
}
public PeerConnectionState connectionState() {
return nativeConnectionState();
}
public IceGatheringState iceGatheringState() {
return nativeIceGatheringState();
}
public void close() {
nativeClose();
}
/**
* Free native resources associated with this PeerConnection instance.
*
* This method removes a reference count from the C++ PeerConnection object,
* which should result in it being destroyed. It also calls equivalent
* "dispose" methods on the Java objects attached to this PeerConnection
* (streams, senders, receivers), such that their associated C++ objects
* will also be destroyed.
*
* <p>Note that this method cannot be safely called from an observer callback
* (PeerConnection.Observer, DataChannel.Observer, etc.). If you want to, for
* example, destroy the PeerConnection after an "ICE failed" callback, you
* must do this asynchronously (in other words, unwind the stack first). See
* <a href="https://bugs.chromium.org/p/webrtc/issues/detail?id=3721">bug
* 3721</a> for more details.
*/
public void dispose() {
close();
for (MediaStream stream : localStreams) {
nativeRemoveLocalStream(stream.getNativeMediaStream());
stream.dispose();
}
localStreams.clear();
for (RtpSender sender : senders) {
sender.dispose();
}
senders.clear();
for (RtpReceiver receiver : receivers) {
receiver.dispose();
}
for (RtpTransceiver transceiver : transceivers) {
transceiver.dispose();
}
transceivers.clear();
receivers.clear();
nativeFreeOwnedPeerConnection(nativePeerConnection);
}
/** Returns a pointer to the native webrtc::PeerConnectionInterface. */
public long getNativePeerConnection() {
return nativeGetNativePeerConnection();
}
@CalledByNative
long getNativeOwnedPeerConnection() {
return nativePeerConnection;
}
public static long createNativePeerConnectionObserver(Observer observer) {
return nativeCreatePeerConnectionObserver(observer);
}
private native long nativeGetNativePeerConnection();
private native SessionDescription nativeGetLocalDescription();
private native SessionDescription nativeGetRemoteDescription();
private native RtcCertificatePem nativeGetCertificate();
private native DataChannel nativeCreateDataChannel(String label, DataChannel.Init init);
private native void nativeCreateOffer(SdpObserver observer, MediaConstraints constraints);
private native void nativeCreateAnswer(SdpObserver observer, MediaConstraints constraints);
private native void nativeSetLocalDescriptionAutomatically(SdpObserver observer);
private native void nativeSetLocalDescription(SdpObserver observer, SessionDescription sdp);
private native void nativeSetRemoteDescription(SdpObserver observer, SessionDescription sdp);
private native void nativeRestartIce();
private native void nativeSetAudioPlayout(boolean playout);
private native void nativeSetAudioRecording(boolean recording);
private native boolean nativeSetBitrate(Integer min, Integer current, Integer max);
private native SignalingState nativeSignalingState();
private native IceConnectionState nativeIceConnectionState();
private native PeerConnectionState nativeConnectionState();
private native IceGatheringState nativeIceGatheringState();
private native void nativeClose();
private static native long nativeCreatePeerConnectionObserver(Observer observer);
private static native void nativeFreeOwnedPeerConnection(long ownedPeerConnection);
private native boolean nativeSetConfiguration(RTCConfiguration config);
private native boolean nativeAddIceCandidate(
String sdpMid, int sdpMLineIndex, String iceCandidateSdp);
private native void nativeAddIceCandidateWithObserver(
String sdpMid, int sdpMLineIndex, String iceCandidateSdp, AddIceObserver observer);
private native boolean nativeRemoveIceCandidates(final IceCandidate[] candidates);
private native boolean nativeAddLocalStream(long stream);
private native void nativeRemoveLocalStream(long stream);
private native boolean nativeOldGetStats(StatsObserver observer, long nativeTrack);
private native void nativeNewGetStats(RTCStatsCollectorCallback callback);
private native RtpSender nativeCreateSender(String kind, String stream_id);
private native List<RtpSender> nativeGetSenders();
private native List<RtpReceiver> nativeGetReceivers();
private native List<RtpTransceiver> nativeGetTransceivers();
private native RtpSender nativeAddTrack(long track, List<String> streamIds);
private native boolean nativeRemoveTrack(long sender);
private native RtpTransceiver nativeAddTransceiverWithTrack(
long track, RtpTransceiver.RtpTransceiverInit init);
private native RtpTransceiver nativeAddTransceiverOfType(
MediaStreamTrack.MediaType mediaType, RtpTransceiver.RtpTransceiverInit init);
private native boolean nativeStartRtcEventLog(int file_descriptor, int max_size_bytes);
private native void nativeStopRtcEventLog();
}