Merge cherrypicks of ['googleplex-android-review.googlesource.com/29062464', 'googleplex-android-review.googlesource.com/29062465'] into 24Q3-platform-release.

Change-Id: I791286bb4cc2fb105dcbcc97739474866382de81
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index 5186203..492351c 100755
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -9343,8 +9343,10 @@
      * interfaces.
      * Ingress discard rule is added to the address iff
      *   1. The address is not a link local address
-     *   2. The address is used by a single VPN interface and not used by any other
-     *      interfaces even non-VPN ones
+     *   2. The address is used by a single interface of VPN whose VPN type is not TYPE_VPN_LEGACY
+     *      or TYPE_VPN_OEM and the address is not used by any other interfaces even non-VPN ones
+     * Ingress discard rule is not be added to TYPE_VPN_LEGACY or TYPE_VPN_OEM VPN since these VPNs
+     * might need to receive packet to VPN address via non-VPN interface.
      * This method can be called during network disconnects, when nai has already been removed from
      * mNetworkAgentInfos.
      *
@@ -9379,7 +9381,10 @@
         // for different network.
         final Set<Pair<InetAddress, String>> ingressDiscardRules = new ArraySet<>();
         for (final NetworkAgentInfo agent : nais) {
-            if (!agent.isVPN() || agent.isDestroyed()) {
+            final int vpnType = getVpnType(agent);
+            if (!agent.isVPN() || agent.isDestroyed()
+                    || vpnType == VpnManager.TYPE_VPN_LEGACY
+                    || vpnType == VpnManager.TYPE_VPN_OEM) {
                 continue;
             }
             final LinkProperties agentLp = (nai == agent) ? lp : agent.linkProperties;
diff --git a/tests/unit/java/com/android/server/connectivityservice/CSIngressDiscardRuleTests.kt b/tests/unit/java/com/android/server/connectivityservice/CSIngressDiscardRuleTests.kt
index 93f6e81..77b06b2 100644
--- a/tests/unit/java/com/android/server/connectivityservice/CSIngressDiscardRuleTests.kt
+++ b/tests/unit/java/com/android/server/connectivityservice/CSIngressDiscardRuleTests.kt
@@ -26,7 +26,9 @@
 import android.net.NetworkCapabilities.TRANSPORT_VPN
 import android.net.NetworkCapabilities.TRANSPORT_WIFI
 import android.net.NetworkRequest
+import android.net.VpnManager.TYPE_VPN_OEM
 import android.net.VpnManager.TYPE_VPN_SERVICE
+import android.net.VpnManager.TYPE_VPN_LEGACY
 import android.net.VpnTransportInfo
 import android.os.Build
 import androidx.test.filters.SmallTest
@@ -49,19 +51,19 @@
 private const val TIMEOUT_MS = 1_000L
 private const val LONG_TIMEOUT_MS = 5_000
 
-private fun vpnNc() = NetworkCapabilities.Builder()
-        .addTransportType(TRANSPORT_VPN)
-        .removeCapability(NET_CAPABILITY_NOT_VPN)
-        .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
-        .setTransportInfo(
-                VpnTransportInfo(
-                        TYPE_VPN_SERVICE,
-                        "MySession12345",
-                        false /* bypassable */,
-                        false /* longLivedTcpConnectionsExpensive */
-                )
-        )
-        .build()
+private fun vpnNc(vpnType: Int = TYPE_VPN_SERVICE) = NetworkCapabilities.Builder().apply {
+    addTransportType(TRANSPORT_VPN)
+    removeCapability(NET_CAPABILITY_NOT_VPN)
+    addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
+    setTransportInfo(
+            VpnTransportInfo(
+                    vpnType,
+                    "MySession12345",
+                    false /* bypassable */,
+                    false /* longLivedTcpConnectionsExpensive */
+            )
+    )
+}.build()
 
 private fun wifiNc() = NetworkCapabilities.Builder()
         .addTransportType(TRANSPORT_WIFI)
@@ -310,4 +312,38 @@
         // IngressDiscardRule should not be added since feature is disabled
         verify(bpfNetMaps, never()).setIngressDiscardRule(any(), any())
     }
+
+    fun doTestVpnIngressDiscardRule_VpnType(vpnType: Int, expectAddRule: Boolean) {
+        val nr = nr(TRANSPORT_VPN)
+        val cb = TestableNetworkCallback()
+        cm.registerNetworkCallback(nr, cb)
+        val nc = vpnNc(vpnType)
+        val lp = lp(VPN_IFNAME, IPV6_LINK_ADDRESS, LOCAL_IPV6_LINK_ADDRRESS)
+        val agent = Agent(nc = nc, lp = lp)
+        agent.connect()
+        cb.expectAvailableCallbacks(agent.network, validated = false)
+
+        if (expectAddRule) {
+            verify(bpfNetMaps).setIngressDiscardRule(IPV6_ADDRESS, VPN_IFNAME)
+        } else {
+            verify(bpfNetMaps, never()).setIngressDiscardRule(any(), any())
+        }
+    }
+
+    @Test
+    fun testVpnIngressDiscardRule_ServiceVpn() {
+        doTestVpnIngressDiscardRule_VpnType(TYPE_VPN_SERVICE, expectAddRule = true)
+    }
+
+    @Test
+    fun testVpnIngressDiscardRule_LegacyVpn() {
+        // IngressDiscardRule should not be added to Legacy VPN
+        doTestVpnIngressDiscardRule_VpnType(TYPE_VPN_LEGACY, expectAddRule = false)
+    }
+
+    @Test
+    fun testVpnIngressDiscardRule_OemVpn() {
+        // IngressDiscardRule should not be added to OEM VPN
+        doTestVpnIngressDiscardRule_VpnType(TYPE_VPN_OEM, expectAddRule = false)
+    }
 }