Expose RTCConfiguration to java JNI and add an option to disable TCP

BUG=4585, 4589
R=glaznev@webrtc.org, juberti@google.com, pthatcher@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/49809004

Cr-Commit-Position: refs/heads/master@{#9125}
diff --git a/talk/app/webrtc/java/jni/classreferenceholder.cc b/talk/app/webrtc/java/jni/classreferenceholder.cc
index 0c25575..7ff48b9 100644
--- a/talk/app/webrtc/java/jni/classreferenceholder.cc
+++ b/talk/app/webrtc/java/jni/classreferenceholder.cc
@@ -92,8 +92,11 @@
   LoadClass(jni, "org/webrtc/MediaSource$State");
   LoadClass(jni, "org/webrtc/MediaStream");
   LoadClass(jni, "org/webrtc/MediaStreamTrack$State");
+  LoadClass(jni, "org/webrtc/PeerConnection$BundlePolicy");
   LoadClass(jni, "org/webrtc/PeerConnection$IceConnectionState");
   LoadClass(jni, "org/webrtc/PeerConnection$IceGatheringState");
+  LoadClass(jni, "org/webrtc/PeerConnection$IceTransportsType");
+  LoadClass(jni, "org/webrtc/PeerConnection$TcpCandidatePolicy");
   LoadClass(jni, "org/webrtc/PeerConnection$SignalingState");
   LoadClass(jni, "org/webrtc/SessionDescription");
   LoadClass(jni, "org/webrtc/SessionDescription$Type");
diff --git a/talk/app/webrtc/java/jni/peerconnection_jni.cc b/talk/app/webrtc/java/jni/peerconnection_jni.cc
index 4d13c41..460ad7e 100644
--- a/talk/app/webrtc/java/jni/peerconnection_jni.cc
+++ b/talk/app/webrtc/java/jni/peerconnection_jni.cc
@@ -1164,6 +1164,76 @@
   factory->SetOptions(options_to_set);
 }
 
+static std::string
+GetJavaEnumName(JNIEnv* jni, const std::string& className, jobject j_enum) {
+  jclass enumClass = FindClass(jni, className.c_str());
+  jmethodID nameMethod =
+      GetMethodID(jni, enumClass, "name", "()Ljava/lang/String;");
+  jstring name =
+      reinterpret_cast<jstring>(jni->CallObjectMethod(j_enum, nameMethod));
+  CHECK_EXCEPTION(jni) << "error during CallObjectMethod for "
+                       << className << ".name";
+  return JavaToStdString(jni, name);
+}
+
+static PeerConnectionInterface::IceTransportsType
+JavaIceTransportsTypeToNativeType(JNIEnv* jni, jobject j_ice_transports_type) {
+  std::string enum_name = GetJavaEnumName(
+      jni, "org/webrtc/PeerConnection$IceTransportsType",
+      j_ice_transports_type);
+
+  if (enum_name == "ALL")
+    return PeerConnectionInterface::kAll;
+
+  if (enum_name == "RELAY")
+    return PeerConnectionInterface::kRelay;
+
+  if (enum_name == "NOHOST")
+    return PeerConnectionInterface::kNoHost;
+
+  if (enum_name == "NONE")
+    return PeerConnectionInterface::kNone;
+
+  CHECK(false) << "Unexpected IceTransportsType enum_name " << enum_name;
+  return PeerConnectionInterface::kAll;
+}
+
+static PeerConnectionInterface::BundlePolicy
+JavaBundlePolicyToNativeType(JNIEnv* jni, jobject j_bundle_policy) {
+  std::string enum_name = GetJavaEnumName(
+      jni, "org/webrtc/PeerConnection$BundlePolicy",
+      j_bundle_policy);
+
+  if (enum_name == "BALANCED")
+    return PeerConnectionInterface::kBundlePolicyBalanced;
+
+  if (enum_name == "MAXBUNDLE")
+    return PeerConnectionInterface::kBundlePolicyMaxBundle;
+
+  if (enum_name == "MAXCOMPAT")
+    return PeerConnectionInterface::kBundlePolicyMaxCompat;
+
+  CHECK(false) << "Unexpected BundlePolicy enum_name " << enum_name;
+  return PeerConnectionInterface::kBundlePolicyBalanced;
+}
+
+static PeerConnectionInterface::TcpCandidatePolicy
+JavaTcpCandidatePolicyToNativeType(
+    JNIEnv* jni, jobject j_tcp_candidate_policy) {
+  std::string enum_name = GetJavaEnumName(
+      jni, "org/webrtc/PeerConnection$TcpCandidatePolicy",
+      j_tcp_candidate_policy);
+
+  if (enum_name == "ENABLED")
+    return PeerConnectionInterface::kTcpCandidatePolicyEnabled;
+
+  if (enum_name == "DISABLED")
+    return PeerConnectionInterface::kTcpCandidatePolicyDisabled;
+
+  CHECK(false) << "Unexpected TcpCandidatePolicy enum_name " << enum_name;
+  return PeerConnectionInterface::kTcpCandidatePolicyEnabled;
+}
+
 static void JavaIceServersToJsepIceServers(
     JNIEnv* jni, jobject j_ice_servers,
     PeerConnectionInterface::IceServers* ice_servers) {
@@ -1203,17 +1273,50 @@
 }
 
 JOW(jlong, PeerConnectionFactory_nativeCreatePeerConnection)(
-    JNIEnv *jni, jclass, jlong factory, jobject j_ice_servers,
+    JNIEnv *jni, jclass, jlong factory, jobject j_rtc_config,
     jobject j_constraints, jlong observer_p) {
   rtc::scoped_refptr<PeerConnectionFactoryInterface> f(
       reinterpret_cast<PeerConnectionFactoryInterface*>(
           factoryFromJava(factory)));
-  PeerConnectionInterface::IceServers servers;
-  JavaIceServersToJsepIceServers(jni, j_ice_servers, &servers);
+
+  jclass j_rtc_config_class = GetObjectClass(jni, j_rtc_config);
+
+  jfieldID j_ice_transports_type_id = GetFieldID(
+      jni, j_rtc_config_class, "iceTransportsType",
+      "Lorg/webrtc/PeerConnection$IceTransportsType;");
+  jobject j_ice_transports_type = GetObjectField(
+      jni, j_rtc_config, j_ice_transports_type_id);
+
+  jfieldID j_bundle_policy_id = GetFieldID(
+      jni, j_rtc_config_class, "bundlePolicy",
+      "Lorg/webrtc/PeerConnection$BundlePolicy;");
+  jobject j_bundle_policy = GetObjectField(
+      jni, j_rtc_config, j_bundle_policy_id);
+
+  jfieldID j_tcp_candidate_policy_id = GetFieldID(
+      jni, j_rtc_config_class, "tcpCandidatePolicy",
+      "Lorg/webrtc/PeerConnection$TcpCandidatePolicy;");
+  jobject j_tcp_candidate_policy = GetObjectField(
+      jni, j_rtc_config, j_tcp_candidate_policy_id);
+
+  jfieldID j_ice_servers_id = GetFieldID(
+      jni, j_rtc_config_class, "iceServers",
+      "Ljava/util/List;");
+  jobject j_ice_servers = GetObjectField(jni, j_rtc_config, j_ice_servers_id);
+
+  PeerConnectionInterface::RTCConfiguration rtc_config;
+
+  rtc_config.type =
+      JavaIceTransportsTypeToNativeType(jni, j_ice_transports_type);
+  rtc_config.bundle_policy = JavaBundlePolicyToNativeType(jni, j_bundle_policy);
+  rtc_config.tcp_candidate_policy =
+      JavaTcpCandidatePolicyToNativeType(jni, j_tcp_candidate_policy);
+  JavaIceServersToJsepIceServers(jni, j_ice_servers, &rtc_config.servers);
+
   PCOJava* observer = reinterpret_cast<PCOJava*>(observer_p);
   observer->SetConstraints(new ConstraintsWrapper(jni, j_constraints));
   rtc::scoped_refptr<PeerConnectionInterface> pc(f->CreatePeerConnection(
-      servers, observer->constraints(), NULL, NULL, observer));
+      rtc_config, observer->constraints(), NULL, NULL, observer));
   return (jlong)pc.release();
 }
 
diff --git a/talk/app/webrtc/java/src/org/webrtc/PeerConnection.java b/talk/app/webrtc/java/src/org/webrtc/PeerConnection.java
index d419f2e..8fcc975 100644
--- a/talk/app/webrtc/java/src/org/webrtc/PeerConnection.java
+++ b/talk/app/webrtc/java/src/org/webrtc/PeerConnection.java
@@ -28,6 +28,7 @@
 
 package org.webrtc;
 
+import java.util.ArrayList;
 import java.util.LinkedList;
 import java.util.List;
 
@@ -106,6 +107,36 @@
     }
   }
 
+  /** 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.BundlePolicy */
+  public enum TcpCandidatePolicy {
+    ENABLED, DISABLED
+  };
+
+  /** Java version of PeerConnectionInterface.RTCConfiguration */
+  public static class RTCConfiguration {
+    public IceTransportsType iceTransportsType;
+    public List<IceServer> iceServers;
+    public BundlePolicy bundlePolicy;
+    public TcpCandidatePolicy tcpCandidatePolicy;
+
+    public RTCConfiguration(List<IceServer> iceServers) {
+      iceTransportsType = IceTransportsType.ALL;
+      bundlePolicy = BundlePolicy.BALANCED;
+      tcpCandidatePolicy = TcpCandidatePolicy.ENABLED;
+      this.iceServers = iceServers;
+    }
+  };
+
   private final List<MediaStream> localStreams;
   private final long nativePeerConnection;
   private final long nativeObserver;
diff --git a/talk/app/webrtc/java/src/org/webrtc/PeerConnectionFactory.java b/talk/app/webrtc/java/src/org/webrtc/PeerConnectionFactory.java
index 0925290..841c681 100644
--- a/talk/app/webrtc/java/src/org/webrtc/PeerConnectionFactory.java
+++ b/talk/app/webrtc/java/src/org/webrtc/PeerConnectionFactory.java
@@ -77,7 +77,7 @@
   }
 
   public PeerConnection createPeerConnection(
-      List<PeerConnection.IceServer> iceServers,
+      PeerConnection.RTCConfiguration rtcConfig,
       MediaConstraints constraints,
       PeerConnection.Observer observer) {
     long nativeObserver = nativeCreateObserver(observer);
@@ -85,13 +85,22 @@
       return null;
     }
     long nativePeerConnection = nativeCreatePeerConnection(
-        nativeFactory, iceServers, constraints, nativeObserver);
+        nativeFactory, rtcConfig, constraints, nativeObserver);
     if (nativePeerConnection == 0) {
       return null;
     }
     return new PeerConnection(nativePeerConnection, nativeObserver);
   }
 
+  public PeerConnection createPeerConnection(
+      List<PeerConnection.IceServer> iceServers,
+      MediaConstraints constraints,
+      PeerConnection.Observer observer) {
+    PeerConnection.RTCConfiguration rtcConfig =
+        new PeerConnection.RTCConfiguration(iceServers);
+    return createPeerConnection(rtcConfig, constraints, observer);
+  }
+
   public MediaStream createLocalMediaStream(String label) {
     return new MediaStream(
         nativeCreateLocalMediaStream(nativeFactory, label));
@@ -133,7 +142,7 @@
       PeerConnection.Observer observer);
 
   private static native long nativeCreatePeerConnection(
-      long nativeFactory, List<PeerConnection.IceServer> iceServers,
+      long nativeFactory, PeerConnection.RTCConfiguration rtcConfig,
       MediaConstraints constraints, long nativeObserver);
 
   private static native long nativeCreateLocalMediaStream(
diff --git a/talk/app/webrtc/peerconnection.cc b/talk/app/webrtc/peerconnection.cc
index 457007a..39284c1 100644
--- a/talk/app/webrtc/peerconnection.cc
+++ b/talk/app/webrtc/peerconnection.cc
@@ -359,6 +359,11 @@
     portallocator_flags &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6);
   }
 
+  if (configuration.tcp_candidate_policy == kTcpCandidatePolicyDisabled) {
+    portallocator_flags |= cricket::PORTALLOCATOR_DISABLE_TCP;
+    LOG(LS_INFO) << "TCP candidates are disabled.";
+  }
+
   port_allocator_->set_flags(portallocator_flags);
   // No step delay is used while allocating ports.
   port_allocator_->set_step_delay(cricket::kMinimumStepDelay);
diff --git a/talk/app/webrtc/peerconnectioninterface.h b/talk/app/webrtc/peerconnectioninterface.h
index 6f6eb24..ed4f5b3 100644
--- a/talk/app/webrtc/peerconnectioninterface.h
+++ b/talk/app/webrtc/peerconnectioninterface.h
@@ -197,6 +197,11 @@
     kBundlePolicyMaxCompat
   };
 
+  enum TcpCandidatePolicy {
+    kTcpCandidatePolicyEnabled,
+    kTcpCandidatePolicyDisabled
+  };
+
   struct RTCConfiguration {
     // TODO(pthatcher): Rename this ice_transport_type, but update
     // Chromium at the same time.
@@ -205,8 +210,12 @@
     // at the same time.
     IceServers servers;
     BundlePolicy bundle_policy;
+    TcpCandidatePolicy tcp_candidate_policy;
 
-    RTCConfiguration() : type(kAll), bundle_policy(kBundlePolicyBalanced) {}
+    RTCConfiguration()
+        : type(kAll),
+          bundle_policy(kBundlePolicyBalanced),
+          tcp_candidate_policy(kTcpCandidatePolicyEnabled) {}
   };
 
   struct RTCOfferAnswerOptions {
diff --git a/talk/examples/android/src/org/appspot/apprtc/PeerConnectionClient.java b/talk/examples/android/src/org/appspot/apprtc/PeerConnectionClient.java
index 76235a8..967a2ea 100644
--- a/talk/examples/android/src/org/appspot/apprtc/PeerConnectionClient.java
+++ b/talk/examples/android/src/org/appspot/apprtc/PeerConnectionClient.java
@@ -413,8 +413,14 @@
     }
     queuedRemoteCandidates = new LinkedList<IceCandidate>();
 
+    PeerConnection.RTCConfiguration rtcConfig =
+        new PeerConnection.RTCConfiguration(signalingParameters.iceServers);
+    // TCP candidates are only useful when connecting to a server that supports
+    // ICE-TCP.
+    rtcConfig.tcpCandidatePolicy = PeerConnection.TcpCandidatePolicy.DISABLED;
+
     peerConnection = factory.createPeerConnection(
-        signalingParameters.iceServers, pcConstraints, pcObserver);
+        rtcConfig, pcConstraints, pcObserver);
     isInitiator = false;
 
     // Set default WebRTC tracing and INFO libjingle logging.