Reland "Fix problem with ipv4 over ipv6 on Android"

This reverts commit 1e60490ddb11afecc796058802fbc80867d851d8.

Reason for revert: Downstream project has been fixed (127.0.0.1 is not PII)

Original change's description:
> Revert "Fix problem with ipv4 over ipv6 on Android"
>
> This reverts commit da2fd2a2b25ee4bd7b383424cb26d51fb6cc7716,
> as well as follow-up b7227a5a10f233cec04642f15a0233e7355bd340,
> "Fix handling of partial match for GetVpnUnderlyingAdapterType".
>
> Reason for revert: Breaks downstream test.
>
> First change's description:
> > Fix problem with ipv4 over ipv6 on Android
> >
> > This patch fixes a problem with using ipv4 over ipv6
> > addresses on Android. These addresses are discovered
> > using 'getifaddr' with interfaces called 'v4-wlan0' or
> > 'v4-rmnet' but the Android API does not report them.
> >
> > This leads to failure when BasicPortAllocator tries
> > to bind a socket to the ip-address, making the ipv4
> > address unusable.
> >
> > This solution does the following
> > 1) Insert BasicNetworkManager as NetworkBinderInterface
> > rather than AndroidNetworkManager.
> >
> > 2) When SocketServer calls BindSocketToNetwork,
> > BasicNetworkManager first lookup the interface name,
> > and then calls AndroidNetworkManager.
> >
> > 3) AndroidNetworkManager will then first try to bind
> > using the known ip-addresses, and if it can't find the network
> > it will instead match the interface names.
> >
> > The patch has been tested on real android devices, and works fine.
> > And everything is disabled by default, and is enabled by field trial.
> >
> > My plan is to rollout the feature, checking that it does not introduce
> > any problems, and if so, enabled for all.
> >
> > Bug: webrtc:10707
> > Change-Id: I7081ba43d4ce17077acfa5fbab44eda127ac3971
> > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/211003
> > Commit-Queue: Jonas Oreland <jonaso@webrtc.org>
> > Reviewed-by: Harald Alvestrand <hta@webrtc.org>
> > Cr-Commit-Position: refs/heads/master@{#33422}
>
> Second change's description:
> > Fix handling of partial match for GetVpnUnderlyingAdapterType
> >
> > This is a followup to https://webrtc-review.googlesource.com/c/src/+/211003
> > and fixes the problem pointed out by deadbeef@, thanks!
> >
> > Bug: webrtc:10707
> > Change-Id: I8dea842b25ba15416353ce4002356183087873c7
> > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/211344
> > Commit-Queue: Jonas Oreland <jonaso@webrtc.org>
> > Reviewed-by: Harald Alvestrand <hta@webrtc.org>
> > Cr-Commit-Position: refs/heads/master@{#33436}
>
> TBR=hta@webrtc.org,jonaso@webrtc.org
> NOTRY=True
>
> Bug: webrtc:10707
> Change-Id: Ib13127fbf087c7f34ca0ccc6ce1805706f01d19d
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/211740
> Reviewed-by: Taylor <deadbeef@webrtc.org>
> Commit-Queue: Taylor <deadbeef@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#33453}

# Not skipping CQ checks because original CL landed > 1 day ago.

Bug: webrtc:10707
Change-Id: I0a11025c366c3127e2f57cd2cd2c33cc3877d1e3
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/211862
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Jonas Oreland <jonaso@webrtc.org>
Commit-Queue: Jonas Oreland <jonaso@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#33460}
diff --git a/rtc_base/network.cc b/rtc_base/network.cc
index 07c39ae..1b0ba36 100644
--- a/rtc_base/network.cc
+++ b/rtc_base/network.cc
@@ -212,7 +212,8 @@
     return ADAPTER_TYPE_ETHERNET;
   }
 
-  if (MatchTypeNameWithIndexPattern(network_name, "wlan")) {
+  if (MatchTypeNameWithIndexPattern(network_name, "wlan") ||
+      MatchTypeNameWithIndexPattern(network_name, "v4-wlan")) {
     return ADAPTER_TYPE_WIFI;
   }
 
@@ -478,15 +479,15 @@
   return nullptr;
 }
 
-BasicNetworkManager::BasicNetworkManager()
-    : allow_mac_based_ipv6_(
-          webrtc::field_trial::IsEnabled("WebRTC-AllowMACBasedIPv6")) {}
+BasicNetworkManager::BasicNetworkManager() : BasicNetworkManager(nullptr) {}
 
 BasicNetworkManager::BasicNetworkManager(
     NetworkMonitorFactory* network_monitor_factory)
     : network_monitor_factory_(network_monitor_factory),
       allow_mac_based_ipv6_(
-          webrtc::field_trial::IsEnabled("WebRTC-AllowMACBasedIPv6")) {}
+          webrtc::field_trial::IsEnabled("WebRTC-AllowMACBasedIPv6")),
+      bind_using_ifname_(
+          webrtc::field_trial::IsEnabled("WebRTC-BindUsingInterfaceName")) {}
 
 BasicNetworkManager::~BasicNetworkManager() {}
 
@@ -865,6 +866,15 @@
     network_monitor_->SignalNetworksChanged.connect(
         this, &BasicNetworkManager::OnNetworksChanged);
   }
+
+  if (network_monitor_->SupportsBindSocketToNetwork()) {
+    // Set NetworkBinder on SocketServer so that
+    // PhysicalSocket::Bind will call
+    // BasicNetworkManager::BindSocketToNetwork(), (that will lookup interface
+    // name and then call network_monitor_->BindSocketToNetwork()).
+    thread_->socketserver()->set_network_binder(this);
+  }
+
   network_monitor_->Start();
 }
 
@@ -873,6 +883,13 @@
     return;
   }
   network_monitor_->Stop();
+
+  if (network_monitor_->SupportsBindSocketToNetwork()) {
+    // Reset NetworkBinder on SocketServer.
+    if (thread_->socketserver()->network_binder() == this) {
+      thread_->socketserver()->set_network_binder(nullptr);
+    }
+  }
 }
 
 void BasicNetworkManager::OnMessage(Message* msg) {
@@ -954,6 +971,20 @@
   }
 }
 
+NetworkBindingResult BasicNetworkManager::BindSocketToNetwork(
+    int socket_fd,
+    const IPAddress& address) {
+  RTC_DCHECK_RUN_ON(thread_);
+  std::string if_name;
+  if (bind_using_ifname_) {
+    Network* net = GetNetworkFromAddress(address);
+    if (net != nullptr) {
+      if_name = net->name();
+    }
+  }
+  return network_monitor_->BindSocketToNetwork(socket_fd, address, if_name);
+}
+
 Network::Network(const std::string& name,
                  const std::string& desc,
                  const IPAddress& prefix,
diff --git a/rtc_base/network.h b/rtc_base/network.h
index d2e3bc2..8b6b6235 100644
--- a/rtc_base/network.h
+++ b/rtc_base/network.h
@@ -194,11 +194,11 @@
   void set_default_local_addresses(const IPAddress& ipv4,
                                    const IPAddress& ipv6);
 
+  Network* GetNetworkFromAddress(const rtc::IPAddress& ip) const;
+
  private:
   friend class NetworkTest;
 
-  Network* GetNetworkFromAddress(const rtc::IPAddress& ip) const;
-
   EnumerationPermission enumeration_permission_;
 
   NetworkList networks_;
@@ -225,6 +225,7 @@
 // of networks using OS APIs.
 class RTC_EXPORT BasicNetworkManager : public NetworkManagerBase,
                                        public MessageHandlerAutoCleanup,
+                                       public NetworkBinderInterface,
                                        public sigslot::has_slots<> {
  public:
   BasicNetworkManager();
@@ -248,6 +249,15 @@
     network_ignore_list_ = list;
   }
 
+  // Bind a socket to interface that ip address belong to.
+  // Implementation look up interface name and calls
+  // BindSocketToNetwork on NetworkMonitor.
+  // The interface name is needed as e.g ipv4 over ipv6 addresses
+  // are not exposed using Android functions, but it is possible
+  // bind an ipv4 address to the interface.
+  NetworkBindingResult BindSocketToNetwork(int socket_fd,
+                                           const IPAddress& address) override;
+
  protected:
 #if defined(WEBRTC_POSIX)
   // Separated from CreateNetworks for tests.
@@ -293,7 +303,8 @@
       nullptr;
   std::unique_ptr<NetworkMonitorInterface> network_monitor_
       RTC_GUARDED_BY(thread_);
-  bool allow_mac_based_ipv6_ = false;
+  bool allow_mac_based_ipv6_ RTC_GUARDED_BY(thread_) = false;
+  bool bind_using_ifname_ RTC_GUARDED_BY(thread_) = false;
 };
 
 // Represents a Unix-type network interface, with a name and single address.
diff --git a/rtc_base/network_monitor.h b/rtc_base/network_monitor.h
index 4a3002f..dddc2f6 100644
--- a/rtc_base/network_monitor.h
+++ b/rtc_base/network_monitor.h
@@ -36,6 +36,8 @@
 
 const char* NetworkPreferenceToString(NetworkPreference preference);
 
+// This interface is set onto a socket server,
+// where only the ip address is known at the time of binding.
 class NetworkBinderInterface {
  public:
   // Binds a socket to the network that is attached to |address| so that all
@@ -83,6 +85,19 @@
   virtual NetworkPreference GetNetworkPreference(
       const std::string& interface_name) = 0;
 
+  // Does |this| NetworkMonitorInterface implement BindSocketToNetwork?
+  // Only Android returns true.
+  virtual bool SupportsBindSocketToNetwork() const { return false; }
+
+  // Bind a socket to an interface specified by ip address and/or interface
+  // name. Only implemented on Android.
+  virtual NetworkBindingResult BindSocketToNetwork(
+      int socket_fd,
+      const IPAddress& address,
+      const std::string& interface_name) {
+    return NetworkBindingResult::NOT_IMPLEMENTED;
+  }
+
   // Is this interface available to use? WebRTC shouldn't attempt to use it if
   // this returns false.
   //
diff --git a/rtc_base/network_unittest.cc b/rtc_base/network_unittest.cc
index 73ddd81..abad479 100644
--- a/rtc_base/network_unittest.cc
+++ b/rtc_base/network_unittest.cc
@@ -76,9 +76,35 @@
     unavailable_adapters_ = unavailable_adapters;
   }
 
+  bool SupportsBindSocketToNetwork() const override { return true; }
+
+  NetworkBindingResult BindSocketToNetwork(
+      int socket_fd,
+      const IPAddress& address,
+      const std::string& if_name) override {
+    if (absl::c_count(addresses_, address) > 0) {
+      return NetworkBindingResult::SUCCESS;
+    }
+
+    for (auto const& iter : adapters_) {
+      if (if_name.find(iter) != std::string::npos) {
+        return NetworkBindingResult::SUCCESS;
+      }
+    }
+    return NetworkBindingResult::ADDRESS_NOT_FOUND;
+  }
+
+  void set_ip_addresses(std::vector<IPAddress> addresses) {
+    addresses_ = addresses;
+  }
+
+  void set_adapters(std::vector<std::string> adapters) { adapters_ = adapters; }
+
  private:
   bool started_ = false;
+  std::vector<std::string> adapters_;
   std::vector<std::string> unavailable_adapters_;
+  std::vector<IPAddress> addresses_;
 };
 
 class FakeNetworkMonitorFactory : public NetworkMonitorFactory {
@@ -1279,4 +1305,48 @@
 }
 #endif
 
+#if defined(WEBRTC_POSIX)
+TEST_F(NetworkTest, WebRTC_BindUsingInterfaceName) {
+  webrtc::test::ScopedFieldTrials field_trials(
+      "WebRTC-BindUsingInterfaceName/Enabled/");
+
+  char if_name1[20] = "wlan0";
+  char if_name2[20] = "v4-wlan0";
+  ifaddrs* list = nullptr;
+  list = AddIpv6Address(list, if_name1, "1000:2000:3000:4000:0:0:0:1",
+                        "FFFF:FFFF:FFFF:FFFF::", 0);
+  list = AddIpv4Address(list, if_name2, "192.168.0.2", "255.255.255.255");
+  NetworkManager::NetworkList result;
+
+  // Sanity check that both interfaces are included by default.
+  FakeNetworkMonitorFactory factory;
+  BasicNetworkManager manager(&factory);
+  manager.StartUpdating();
+  CallConvertIfAddrs(manager, list, /*include_ignored=*/false, &result);
+  EXPECT_EQ(2u, result.size());
+  ReleaseIfAddrs(list);
+  bool changed;
+  // This ensures we release the objects created in CallConvertIfAddrs.
+  MergeNetworkList(manager, result, &changed);
+  result.clear();
+
+  FakeNetworkMonitor* network_monitor = GetNetworkMonitor(manager);
+
+  IPAddress ipv6;
+  EXPECT_TRUE(IPFromString("1000:2000:3000:4000:0:0:0:1", &ipv6));
+  IPAddress ipv4;
+  EXPECT_TRUE(IPFromString("192.168.0.2", &ipv4));
+
+  // The network monitor only knwos about the ipv6 address, interface.
+  network_monitor->set_adapters({"wlan0"});
+  network_monitor->set_ip_addresses({ipv6});
+  EXPECT_EQ(manager.BindSocketToNetwork(/* fd */ 77, ipv6),
+            NetworkBindingResult::SUCCESS);
+
+  // But it will bind anyway using string matching...
+  EXPECT_EQ(manager.BindSocketToNetwork(/* fd */ 77, ipv4),
+            NetworkBindingResult::SUCCESS);
+}
+#endif
+
 }  // namespace rtc
diff --git a/sdk/android/native_unittests/android_network_monitor_unittest.cc b/sdk/android/native_unittests/android_network_monitor_unittest.cc
index e7a2d7d..20e756a 100644
--- a/sdk/android/native_unittests/android_network_monitor_unittest.cc
+++ b/sdk/android/native_unittests/android_network_monitor_unittest.cc
@@ -74,7 +74,7 @@
   network_monitor_->SetNetworkInfos(net_infos);
 
   auto network_handle =
-      network_monitor_->FindNetworkHandleFromAddress(ipv4_address);
+      network_monitor_->FindNetworkHandleFromAddressOrName(ipv4_address, "");
 
   ASSERT_TRUE(network_handle.has_value());
   EXPECT_EQ(ipv4_handle, *network_handle);
@@ -91,9 +91,9 @@
   network_monitor_->SetNetworkInfos(net_infos);
 
   auto network_handle1 =
-      network_monitor_->FindNetworkHandleFromAddress(ipv6_address1);
+      network_monitor_->FindNetworkHandleFromAddressOrName(ipv6_address1, "");
   auto network_handle2 =
-      network_monitor_->FindNetworkHandleFromAddress(ipv6_address2);
+      network_monitor_->FindNetworkHandleFromAddressOrName(ipv6_address2, "");
 
   ASSERT_TRUE(network_handle1.has_value());
   EXPECT_EQ(ipv6_handle, *network_handle1);
@@ -116,9 +116,9 @@
   network_monitor_->SetNetworkInfos(net_infos);
 
   auto network_handle1 =
-      network_monitor_->FindNetworkHandleFromAddress(ipv6_address1);
+      network_monitor_->FindNetworkHandleFromAddressOrName(ipv6_address1, "");
   auto network_handle2 =
-      network_monitor_->FindNetworkHandleFromAddress(ipv6_address2);
+      network_monitor_->FindNetworkHandleFromAddressOrName(ipv6_address2, "");
 
   ASSERT_TRUE(network_handle1.has_value());
   EXPECT_EQ(ipv6_handle, *network_handle1);
@@ -126,5 +126,47 @@
   EXPECT_EQ(ipv6_handle, *network_handle2);
 }
 
+TEST_F(AndroidNetworkMonitorTest, TestFindNetworkHandleUsingIfName) {
+  ScopedFieldTrials field_trials("WebRTC-BindUsingInterfaceName/Enabled/");
+  // Start() updates the states introduced by the field trial.
+  network_monitor_->Start();
+  jni::NetworkHandle ipv6_handle = 200;
+  rtc::IPAddress ipv6_address1 = GetIpAddressFromIpv6String(kTestIpv6Address1);
+
+  // Set up an IPv6 network.
+  jni::NetworkInformation net_info =
+      CreateNetworkInformation("wlan0", ipv6_handle, ipv6_address1);
+  std::vector<jni::NetworkInformation> net_infos(1, net_info);
+  network_monitor_->SetNetworkInfos(net_infos);
+
+  rtc::IPAddress ipv4_address(kTestIpv4Address);
+
+  // Search using ip address only...
+  auto network_handle1 =
+      network_monitor_->FindNetworkHandleFromAddressOrName(ipv4_address, "");
+
+  // Search using ip address AND if_name (for typical ipv4 over ipv6 tunnel).
+  auto network_handle2 = network_monitor_->FindNetworkHandleFromAddressOrName(
+      ipv4_address, "v4-wlan0");
+
+  ASSERT_FALSE(network_handle1.has_value());
+  ASSERT_TRUE(network_handle2.has_value());
+  EXPECT_EQ(ipv6_handle, *network_handle2);
+}
+
+TEST_F(AndroidNetworkMonitorTest, TestUnderlyingVpnType) {
+  ScopedFieldTrials field_trials("WebRTC-BindUsingInterfaceName/Enabled/");
+  jni::NetworkHandle ipv4_handle = 100;
+  rtc::IPAddress ipv4_address(kTestIpv4Address);
+  jni::NetworkInformation net_info =
+      CreateNetworkInformation("wlan0", ipv4_handle, ipv4_address);
+  net_info.type = jni::NETWORK_VPN;
+  net_info.underlying_type_for_vpn = jni::NETWORK_WIFI;
+  network_monitor_->SetNetworkInfos({net_info});
+
+  EXPECT_EQ(rtc::ADAPTER_TYPE_WIFI,
+            network_monitor_->GetVpnUnderlyingAdapterType("v4-wlan0"));
+}
+
 }  // namespace test
 }  // namespace webrtc
diff --git a/sdk/android/src/jni/android_network_monitor.cc b/sdk/android/src/jni/android_network_monitor.cc
index cb6bce2..0367513 100644
--- a/sdk/android/src/jni/android_network_monitor.cc
+++ b/sdk/android/src/jni/android_network_monitor.cc
@@ -247,11 +247,8 @@
   find_network_handle_without_ipv6_temporary_part_ =
       webrtc::field_trial::IsEnabled(
           "WebRTC-FindNetworkHandleWithoutIpv6TemporaryPart");
-
-  // This is kind of magic behavior, but doing this allows the SocketServer to
-  // use this as a NetworkBinder to bind sockets on a particular network when
-  // it creates sockets.
-  network_thread_->socketserver()->set_network_binder(this);
+  bind_using_ifname_ =
+      webrtc::field_trial::IsEnabled("WebRTC-BindUsingInterfaceName");
 
   // Needed for restart after Stop().
   safety_flag_->SetAlive();
@@ -285,7 +282,8 @@
 // https://cs.chromium.org/chromium/src/net/udp/udp_socket_posix.cc
 rtc::NetworkBindingResult AndroidNetworkMonitor::BindSocketToNetwork(
     int socket_fd,
-    const rtc::IPAddress& address) {
+    const rtc::IPAddress& address,
+    const std::string& if_name) {
   RTC_DCHECK_RUN_ON(network_thread_);
 
   // Android prior to Lollipop didn't have support for binding sockets to
@@ -303,12 +301,18 @@
   }
 
   absl::optional<NetworkHandle> network_handle =
-      FindNetworkHandleFromAddress(address);
+      FindNetworkHandleFromAddressOrName(address, if_name);
   if (!network_handle) {
+    RTC_LOG(LS_WARNING)
+        << "BindSocketToNetwork unable to find network handle for"
+        << " addr: " << address.ToSensitiveString() << " ifname: " << if_name;
     return rtc::NetworkBindingResult::ADDRESS_NOT_FOUND;
   }
 
   if (*network_handle == 0 /* NETWORK_UNSPECIFIED */) {
+    RTC_LOG(LS_WARNING) << "BindSocketToNetwork 0 network handle for"
+                        << " addr: " << address.ToSensitiveString()
+                        << " ifname: " << if_name;
     return rtc::NetworkBindingResult::NOT_IMPLEMENTED;
   }
 
@@ -375,11 +379,19 @@
   // ERR_NETWORK_CHANGED, rather than MapSystemError(ENONET) which gives back
   // the less descriptive ERR_FAILED.
   if (rv == 0) {
+    RTC_LOG(LS_VERBOSE) << "BindSocketToNetwork bound network handle for"
+                        << " addr: " << address.ToSensitiveString()
+                        << " ifname: " << if_name;
     return rtc::NetworkBindingResult::SUCCESS;
   }
+
+  RTC_LOG(LS_WARNING) << "BindSocketToNetwork got error: " << rv
+                      << " addr: " << address.ToSensitiveString()
+                      << " ifname: " << if_name;
   if (rv == ENONET) {
     return rtc::NetworkBindingResult::NETWORK_CHANGED;
   }
+
   return rtc::NetworkBindingResult::FAILURE;
 }
 
@@ -402,8 +414,9 @@
 }
 
 absl::optional<NetworkHandle>
-AndroidNetworkMonitor::FindNetworkHandleFromAddress(
-    const rtc::IPAddress& ip_address) const {
+AndroidNetworkMonitor::FindNetworkHandleFromAddressOrName(
+    const rtc::IPAddress& ip_address,
+    const std::string& if_name) const {
   RTC_DCHECK_RUN_ON(network_thread_);
   RTC_LOG(LS_INFO) << "Find network handle.";
   if (find_network_handle_without_ipv6_temporary_part_) {
@@ -417,14 +430,31 @@
         return absl::make_optional(iter.first);
       }
     }
-    return absl::nullopt;
   } else {
     auto iter = network_handle_by_address_.find(ip_address);
-    if (iter == network_handle_by_address_.end()) {
-      return absl::nullopt;
+    if (iter != network_handle_by_address_.end()) {
+      return absl::make_optional(iter->second);
     }
-    return absl::make_optional(iter->second);
   }
+
+  return FindNetworkHandleFromIfname(if_name);
+}
+
+absl::optional<NetworkHandle>
+AndroidNetworkMonitor::FindNetworkHandleFromIfname(
+    const std::string& if_name) const {
+  RTC_DCHECK_RUN_ON(network_thread_);
+  if (bind_using_ifname_) {
+    for (auto const& iter : network_info_by_handle_) {
+      if (if_name.find(iter.second.interface_name) != std::string::npos) {
+        // Use partial match so that e.g if_name="v4-wlan0" is matched
+        // agains iter.first="wlan0"
+        return absl::make_optional(iter.first);
+      }
+    }
+  }
+
+  return absl::nullopt;
 }
 
 void AndroidNetworkMonitor::OnNetworkDisconnected_n(NetworkHandle handle) {
@@ -470,6 +500,18 @@
   rtc::AdapterType type = (iter == adapter_type_by_name_.end())
                               ? rtc::ADAPTER_TYPE_UNKNOWN
                               : iter->second;
+
+  if (type == rtc::ADAPTER_TYPE_UNKNOWN && bind_using_ifname_) {
+    for (auto const& iter : adapter_type_by_name_) {
+      // Use partial match so that e.g if_name="v4-wlan0" is matched
+      // agains iter.first="wlan0"
+      if (if_name.find(iter.first) != std::string::npos) {
+        type = iter.second;
+        break;
+      }
+    }
+  }
+
   if (type == rtc::ADAPTER_TYPE_UNKNOWN) {
     RTC_LOG(LS_WARNING) << "Get an unknown type for the interface " << if_name;
   }
@@ -483,6 +525,17 @@
   rtc::AdapterType type = (iter == vpn_underlying_adapter_type_by_name_.end())
                               ? rtc::ADAPTER_TYPE_UNKNOWN
                               : iter->second;
+  if (type == rtc::ADAPTER_TYPE_UNKNOWN && bind_using_ifname_) {
+    // Use partial match so that e.g if_name="v4-wlan0" is matched
+    // agains iter.first="wlan0"
+    for (auto const& iter : vpn_underlying_adapter_type_by_name_) {
+      if (if_name.find(iter.first) != std::string::npos) {
+        type = iter.second;
+        break;
+      }
+    }
+  }
+
   return type;
 }
 
diff --git a/sdk/android/src/jni/android_network_monitor.h b/sdk/android/src/jni/android_network_monitor.h
index f6edf1b..6349a11 100644
--- a/sdk/android/src/jni/android_network_monitor.h
+++ b/sdk/android/src/jni/android_network_monitor.h
@@ -64,8 +64,7 @@
   std::string ToString() const;
 };
 
-class AndroidNetworkMonitor : public rtc::NetworkMonitorInterface,
-                              public rtc::NetworkBinderInterface {
+class AndroidNetworkMonitor : public rtc::NetworkMonitorInterface {
  public:
   AndroidNetworkMonitor(JNIEnv* env,
                         const JavaRef<jobject>& j_application_context);
@@ -77,9 +76,14 @@
   void Start() override;
   void Stop() override;
 
+  // Does |this| NetworkMonitorInterface implement BindSocketToNetwork?
+  // Only Android returns true.
+  virtual bool SupportsBindSocketToNetwork() const override { return true; }
+
   rtc::NetworkBindingResult BindSocketToNetwork(
       int socket_fd,
-      const rtc::IPAddress& address) override;
+      const rtc::IPAddress& address,
+      const std::string& if_name) override;
   rtc::AdapterType GetAdapterType(const std::string& if_name) override;
   rtc::AdapterType GetVpnUnderlyingAdapterType(
       const std::string& if_name) override;
@@ -106,8 +110,9 @@
                                  jint preference);
 
   // Visible for testing.
-  absl::optional<NetworkHandle> FindNetworkHandleFromAddress(
-      const rtc::IPAddress& address) const;
+  absl::optional<NetworkHandle> FindNetworkHandleFromAddressOrName(
+      const rtc::IPAddress& address,
+      const std::string& ifname) const;
 
  private:
   void OnNetworkConnected_n(const NetworkInformation& network_info);
@@ -115,6 +120,9 @@
   void OnNetworkPreference_n(NetworkType type,
                              rtc::NetworkPreference preference);
 
+  absl::optional<NetworkHandle> FindNetworkHandleFromIfname(
+      const std::string& ifname) const;
+
   const int android_sdk_int_;
   ScopedJavaGlobalRef<jobject> j_application_context_;
   ScopedJavaGlobalRef<jobject> j_network_monitor_;
@@ -133,6 +141,14 @@
   bool find_network_handle_without_ipv6_temporary_part_
       RTC_GUARDED_BY(network_thread_) = false;
   bool surface_cellular_types_ RTC_GUARDED_BY(network_thread_) = false;
+
+  // NOTE: if bind_using_ifname_ is TRUE
+  // then the adapter name is used with substring matching as follows:
+  // An adapater name repored by android as 'wlan0'
+  // will be matched with 'v4-wlan0' ("v4-wlan0".find("wlan0") != npos).
+  // This applies to adapter_type_by_name_, vpn_underlying_adapter_type_by_name_
+  // and FindNetworkHandleFromIfname.
+  bool bind_using_ifname_ RTC_GUARDED_BY(network_thread_) = true;
   const rtc::scoped_refptr<PendingTaskSafetyFlag> safety_flag_
       RTC_PT_GUARDED_BY(network_thread_);
 };