Merge "remove duplicate jni include"
diff --git a/Tethering/apishim/30/com/android/networkstack/tethering/apishim/api30/BpfCoordinatorShimImpl.java b/Tethering/apishim/30/com/android/networkstack/tethering/apishim/api30/BpfCoordinatorShimImpl.java
index 18ef631..898b124 100644
--- a/Tethering/apishim/30/com/android/networkstack/tethering/apishim/api30/BpfCoordinatorShimImpl.java
+++ b/Tethering/apishim/30/com/android/networkstack/tethering/apishim/api30/BpfCoordinatorShimImpl.java
@@ -168,13 +168,13 @@
     }
 
     @Override
-    public boolean attachProgram(String iface, boolean downstream) {
+    public boolean attachProgram(String iface, boolean downstream, boolean ipv4) {
         /* no op */
         return true;
     }
 
     @Override
-    public boolean detachProgram(String iface) {
+    public boolean detachProgram(String iface, boolean ipv4) {
         /* no op */
         return true;
     }
diff --git a/Tethering/apishim/31/com/android/networkstack/tethering/apishim/api31/BpfCoordinatorShimImpl.java b/Tethering/apishim/31/com/android/networkstack/tethering/apishim/api31/BpfCoordinatorShimImpl.java
index fd9dab5..776832f 100644
--- a/Tethering/apishim/31/com/android/networkstack/tethering/apishim/api31/BpfCoordinatorShimImpl.java
+++ b/Tethering/apishim/31/com/android/networkstack/tethering/apishim/api31/BpfCoordinatorShimImpl.java
@@ -425,11 +425,11 @@
     }
 
     @Override
-    public boolean attachProgram(String iface, boolean downstream) {
+    public boolean attachProgram(String iface, boolean downstream, boolean ipv4) {
         if (!isInitialized()) return false;
 
         try {
-            BpfUtils.attachProgram(iface, downstream);
+            BpfUtils.attachProgram(iface, downstream, ipv4);
         } catch (IOException e) {
             mLog.e("Could not attach program: " + e);
             return false;
@@ -438,11 +438,11 @@
     }
 
     @Override
-    public boolean detachProgram(String iface) {
+    public boolean detachProgram(String iface, boolean ipv4) {
         if (!isInitialized()) return false;
 
         try {
-            BpfUtils.detachProgram(iface);
+            BpfUtils.detachProgram(iface, ipv4);
         } catch (IOException e) {
             mLog.e("Could not detach program: " + e);
             return false;
diff --git a/Tethering/apishim/common/com/android/networkstack/tethering/apishim/common/BpfCoordinatorShim.java b/Tethering/apishim/common/com/android/networkstack/tethering/apishim/common/BpfCoordinatorShim.java
index 69cbab5..51cecfe 100644
--- a/Tethering/apishim/common/com/android/networkstack/tethering/apishim/common/BpfCoordinatorShim.java
+++ b/Tethering/apishim/common/com/android/networkstack/tethering/apishim/common/BpfCoordinatorShim.java
@@ -172,16 +172,24 @@
     /**
      * Attach BPF program.
      *
+     * @param iface the interface name to attach program.
+     * @param downstream indicate the datapath. true if downstream, false if upstream.
+     * @param ipv4 indicate the protocol family. true if ipv4, false if ipv6.
+     *
      * TODO: consider using InterfaceParams to replace interface name.
      */
-    public abstract boolean attachProgram(@NonNull String iface, boolean downstream);
+    public abstract boolean attachProgram(@NonNull String iface, boolean downstream,
+            boolean ipv4);
 
     /**
      * Detach BPF program.
      *
+     * @param iface the interface name to detach program.
+     * @param ipv4 indicate the protocol family. true if ipv4, false if ipv6.
+     *
      * TODO: consider using InterfaceParams to replace interface name.
      */
-    public abstract boolean detachProgram(@NonNull String iface);
+    public abstract boolean detachProgram(@NonNull String iface, boolean ipv4);
 
     /**
      * Add interface index mapping.
diff --git a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
index f8169cb..7e0a589 100644
--- a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
+++ b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
@@ -895,6 +895,28 @@
         }
     }
 
+    private boolean is464XlatInterface(@NonNull String ifaceName) {
+        return ifaceName.startsWith("v4-");
+    }
+
+    private void maybeAttachProgramImpl(@NonNull String iface, boolean downstream) {
+        mBpfCoordinatorShim.attachProgram(iface, downstream, true /* ipv4 */);
+
+        // Ignore 464xlat interface because it is IPv4 only.
+        if (!is464XlatInterface(iface)) {
+            mBpfCoordinatorShim.attachProgram(iface, downstream, false /* ipv4 */);
+        }
+    }
+
+    private void maybeDetachProgramImpl(@NonNull String iface) {
+        mBpfCoordinatorShim.detachProgram(iface, true /* ipv4 */);
+
+        // Ignore 464xlat interface because it is IPv4 only.
+        if (!is464XlatInterface(iface)) {
+            mBpfCoordinatorShim.detachProgram(iface, false /* ipv4 */);
+        }
+    }
+
     /**
      * Attach BPF program
      *
@@ -913,11 +935,11 @@
         // Ex: IPv6 only interface has two forwarding pair, iface and v4-iface, on the
         // same downstream.
         if (firstUpstreamForThisDownstream) {
-            mBpfCoordinatorShim.attachProgram(intIface, UPSTREAM);
+            maybeAttachProgramImpl(intIface, UPSTREAM);
         }
         // Attach if the upstream is the first time to be used in a forwarding pair.
         if (firstDownstreamForThisUpstream) {
-            mBpfCoordinatorShim.attachProgram(extIface, DOWNSTREAM);
+            maybeAttachProgramImpl(extIface, DOWNSTREAM);
         }
     }
 
@@ -929,11 +951,11 @@
 
         // Detaching program may fail because the interface has been removed already.
         if (!isAnyForwardingPairOnDownstream(intIface)) {
-            mBpfCoordinatorShim.detachProgram(intIface);
+            maybeDetachProgramImpl(intIface);
         }
         // Detach if no more forwarding pair is using the upstream.
         if (!isAnyForwardingPairOnUpstream(extIface)) {
-            mBpfCoordinatorShim.detachProgram(extIface);
+            maybeDetachProgramImpl(extIface);
         }
     }
 
diff --git a/Tethering/src/com/android/networkstack/tethering/BpfUtils.java b/Tethering/src/com/android/networkstack/tethering/BpfUtils.java
index 3d2dfaa..12a0c96 100644
--- a/Tethering/src/com/android/networkstack/tethering/BpfUtils.java
+++ b/Tethering/src/com/android/networkstack/tethering/BpfUtils.java
@@ -74,7 +74,7 @@
      *
      * TODO: use interface index to replace interface name.
      */
-    public static void attachProgram(@NonNull String iface, boolean downstream)
+    public static void attachProgram(@NonNull String iface, boolean downstream, boolean ipv4)
             throws IOException {
         final InterfaceParams params = InterfaceParams.getByName(iface);
         if (params == null) {
@@ -88,24 +88,26 @@
             throw new IOException("isEthernet(" + params.index + "[" + iface + "]) failure: " + e);
         }
 
-        try {
-            // tc filter add dev .. ingress prio 1 protocol ipv6 bpf object-pinned /sys/fs/bpf/...
-            // direct-action
-            TcUtils.tcFilterAddDevBpf(params.index, INGRESS, PRIO_TETHER6, (short) ETH_P_IPV6,
-                    makeProgPath(downstream, 6, ether));
-        } catch (IOException e) {
-            throw new IOException("tc filter add dev (" + params.index + "[" + iface
-                    + "]) ingress prio PRIO_TETHER6 protocol ipv6 failure: " + e);
-        }
-
-        try {
-            // tc filter add dev .. ingress prio 2 protocol ip bpf object-pinned /sys/fs/bpf/...
-            // direct-action
-            TcUtils.tcFilterAddDevBpf(params.index, INGRESS, PRIO_TETHER4, (short) ETH_P_IP,
-                    makeProgPath(downstream, 4, ether));
-        } catch (IOException e) {
-            throw new IOException("tc filter add dev (" + params.index + "[" + iface
-                    + "]) ingress prio PRIO_TETHER4 protocol ip failure: " + e);
+        if (ipv4) {
+            try {
+                // tc filter add dev .. ingress prio 2 protocol ip bpf object-pinned /sys/fs/bpf/...
+                // direct-action
+                TcUtils.tcFilterAddDevBpf(params.index, INGRESS, PRIO_TETHER4, (short) ETH_P_IP,
+                        makeProgPath(downstream, 4, ether));
+            } catch (IOException e) {
+                throw new IOException("tc filter add dev (" + params.index + "[" + iface
+                        + "]) ingress prio PRIO_TETHER4 protocol ip failure: " + e);
+            }
+        } else {
+            try {
+                // tc filter add dev .. ingress prio 1 protocol ipv6 bpf object-pinned
+                // /sys/fs/bpf/... direct-action
+                TcUtils.tcFilterAddDevBpf(params.index, INGRESS, PRIO_TETHER6, (short) ETH_P_IPV6,
+                        makeProgPath(downstream, 6, ether));
+            } catch (IOException e) {
+                throw new IOException("tc filter add dev (" + params.index + "[" + iface
+                        + "]) ingress prio PRIO_TETHER6 protocol ipv6 failure: " + e);
+            }
         }
     }
 
@@ -114,26 +116,28 @@
      *
      * TODO: use interface index to replace interface name.
      */
-    public static void detachProgram(@NonNull String iface) throws IOException {
+    public static void detachProgram(@NonNull String iface, boolean ipv4) throws IOException {
         final InterfaceParams params = InterfaceParams.getByName(iface);
         if (params == null) {
             throw new IOException("Fail to get interface params for interface " + iface);
         }
 
-        try {
-            // tc filter del dev .. ingress prio 1 protocol ipv6
-            TcUtils.tcFilterDelDev(params.index, INGRESS, PRIO_TETHER6, (short) ETH_P_IPV6);
-        } catch (IOException e) {
-            throw new IOException("tc filter del dev (" + params.index + "[" + iface
-                    + "]) ingress prio PRIO_TETHER6 protocol ipv6 failure: " + e);
-        }
-
-        try {
-            // tc filter del dev .. ingress prio 2 protocol ip
-            TcUtils.tcFilterDelDev(params.index, INGRESS, PRIO_TETHER4, (short) ETH_P_IP);
-        } catch (IOException e) {
-            throw new IOException("tc filter del dev (" + params.index + "[" + iface
-                    + "]) ingress prio PRIO_TETHER4 protocol ip failure: " + e);
+        if (ipv4) {
+            try {
+                // tc filter del dev .. ingress prio 2 protocol ip
+                TcUtils.tcFilterDelDev(params.index, INGRESS, PRIO_TETHER4, (short) ETH_P_IP);
+            } catch (IOException e) {
+                throw new IOException("tc filter del dev (" + params.index + "[" + iface
+                        + "]) ingress prio PRIO_TETHER4 protocol ip failure: " + e);
+            }
+        } else {
+            try {
+                // tc filter del dev .. ingress prio 1 protocol ipv6
+                TcUtils.tcFilterDelDev(params.index, INGRESS, PRIO_TETHER6, (short) ETH_P_IPV6);
+            } catch (IOException e) {
+                throw new IOException("tc filter del dev (" + params.index + "[" + iface
+                        + "]) ingress prio PRIO_TETHER6 protocol ipv6 failure: " + e);
+            }
         }
     }
 }
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
index 788673a..63bb731 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
@@ -59,6 +59,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyLong;
 import static org.mockito.Matchers.anyString;
@@ -141,6 +142,9 @@
     @Rule
     public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule();
 
+    private static final boolean IPV4 = true;
+    private static final boolean IPV6 = false;
+
     private static final int TEST_NET_ID = 24;
     private static final int TEST_NET_ID2 = 25;
 
@@ -1286,8 +1290,10 @@
             // [1] Add the forwarding pair <wlan1, rmnet_data0>. Expect that attach both wlan1 and
             // rmnet_data0.
             coordinator.maybeAttachProgram(intIface1, extIface1);
-            ExtendedMockito.verify(() -> BpfUtils.attachProgram(extIface1, DOWNSTREAM));
-            ExtendedMockito.verify(() -> BpfUtils.attachProgram(intIface1, UPSTREAM));
+            ExtendedMockito.verify(() -> BpfUtils.attachProgram(extIface1, DOWNSTREAM, IPV4));
+            ExtendedMockito.verify(() -> BpfUtils.attachProgram(extIface1, DOWNSTREAM, IPV6));
+            ExtendedMockito.verify(() -> BpfUtils.attachProgram(intIface1, UPSTREAM, IPV4));
+            ExtendedMockito.verify(() -> BpfUtils.attachProgram(intIface1, UPSTREAM, IPV6));
             ExtendedMockito.verifyNoMoreInteractions(mockMarkerBpfUtils);
             ExtendedMockito.clearInvocations(mockMarkerBpfUtils);
 
@@ -1298,42 +1304,49 @@
 
             // [3] Add the forwarding pair <rndis0, rmnet_data0>. Expect that attach rndis0 only.
             coordinator.maybeAttachProgram(intIface2, extIface1);
-            ExtendedMockito.verify(() -> BpfUtils.attachProgram(intIface2, UPSTREAM));
+            ExtendedMockito.verify(() -> BpfUtils.attachProgram(intIface2, UPSTREAM, IPV4));
+            ExtendedMockito.verify(() -> BpfUtils.attachProgram(intIface2, UPSTREAM, IPV6));
             ExtendedMockito.verifyNoMoreInteractions(mockMarkerBpfUtils);
             ExtendedMockito.clearInvocations(mockMarkerBpfUtils);
 
             // [4] Add the forwarding pair <rndis0, v4-rmnet_data0>. Expect that attach
-            // v4-rmnet_data0 only.
+            // v4-rmnet_data0 IPv4 program only.
             coordinator.maybeAttachProgram(intIface2, extIface2);
-            ExtendedMockito.verify(() -> BpfUtils.attachProgram(extIface2, DOWNSTREAM));
+            ExtendedMockito.verify(() -> BpfUtils.attachProgram(extIface2, DOWNSTREAM, IPV4));
+            ExtendedMockito.verify(() -> BpfUtils.attachProgram(extIface2, DOWNSTREAM, IPV6),
+                    never());
             ExtendedMockito.verifyNoMoreInteractions(mockMarkerBpfUtils);
             ExtendedMockito.clearInvocations(mockMarkerBpfUtils);
 
             // [5] Remove the forwarding pair <rndis0, v4-rmnet_data0>. Expect detach
-            // v4-rmnet_data0 only.
+            // v4-rmnet_data0 IPv4 program only.
             coordinator.maybeDetachProgram(intIface2, extIface2);
-            ExtendedMockito.verify(() -> BpfUtils.detachProgram(extIface2));
+            ExtendedMockito.verify(() -> BpfUtils.detachProgram(extIface2, IPV4));
+            ExtendedMockito.verify(() -> BpfUtils.detachProgram(extIface2, IPV6), never());
             ExtendedMockito.verifyNoMoreInteractions(mockMarkerBpfUtils);
             ExtendedMockito.clearInvocations(mockMarkerBpfUtils);
 
             // [6] Remove the forwarding pair <rndis0, rmnet_data0>. Expect detach rndis0 only.
             coordinator.maybeDetachProgram(intIface2, extIface1);
-            ExtendedMockito.verify(() -> BpfUtils.detachProgram(intIface2));
+            ExtendedMockito.verify(() -> BpfUtils.detachProgram(intIface2, IPV4));
+            ExtendedMockito.verify(() -> BpfUtils.detachProgram(intIface2, IPV6));
             ExtendedMockito.verifyNoMoreInteractions(mockMarkerBpfUtils);
             ExtendedMockito.clearInvocations(mockMarkerBpfUtils);
 
             // [7] Remove the forwarding pair <wlan1, rmnet_data0>. Expect that detach both wlan1
             // and rmnet_data0.
             coordinator.maybeDetachProgram(intIface1, extIface1);
-            ExtendedMockito.verify(() -> BpfUtils.detachProgram(extIface1));
-            ExtendedMockito.verify(() -> BpfUtils.detachProgram(intIface1));
+            ExtendedMockito.verify(() -> BpfUtils.detachProgram(extIface1, IPV4));
+            ExtendedMockito.verify(() -> BpfUtils.detachProgram(extIface1, IPV6));
+            ExtendedMockito.verify(() -> BpfUtils.detachProgram(intIface1, IPV4));
+            ExtendedMockito.verify(() -> BpfUtils.detachProgram(intIface1, IPV6));
             ExtendedMockito.verifyNoMoreInteractions(mockMarkerBpfUtils);
             ExtendedMockito.clearInvocations(mockMarkerBpfUtils);
 
             // [8] Skip attaching if upstream is virtual interface.
             coordinator.maybeAttachProgram(intIface1, virtualIface);
-            ExtendedMockito.verify(() -> BpfUtils.attachProgram(extIface1, DOWNSTREAM), never());
-            ExtendedMockito.verify(() -> BpfUtils.attachProgram(intIface1, UPSTREAM), never());
+            ExtendedMockito.verify(() ->
+                    BpfUtils.attachProgram(anyString(), anyBoolean(), anyBoolean()), never());
             ExtendedMockito.verifyNoMoreInteractions(mockMarkerBpfUtils);
             ExtendedMockito.clearInvocations(mockMarkerBpfUtils);
 
diff --git a/bpf_progs/clatd.c b/bpf_progs/clatd.c
index 66e9616..a2214dc 100644
--- a/bpf_progs/clatd.c
+++ b/bpf_progs/clatd.c
@@ -342,4 +342,4 @@
 }
 
 LICENSE("Apache 2.0");
-CRITICAL("netd");
+CRITICAL("Connectivity");
diff --git a/bpf_progs/netd.c b/bpf_progs/netd.c
index 44f76de..eb78cb3 100644
--- a/bpf_progs/netd.c
+++ b/bpf_progs/netd.c
@@ -432,4 +432,4 @@
 }
 
 LICENSE("Apache 2.0");
-CRITICAL("netd");
+CRITICAL("Connectivity and netd");
diff --git a/bpf_progs/offload.c b/bpf_progs/offload.c
index cb83b92..898f2e2 100644
--- a/bpf_progs/offload.c
+++ b/bpf_progs/offload.c
@@ -864,4 +864,4 @@
 }
 
 LICENSE("Apache 2.0");
-CRITICAL("tethering");
+CRITICAL("Connectivity (Tethering)");
diff --git a/service/jni/com_android_server_BpfNetMaps.cpp b/service/jni/com_android_server_BpfNetMaps.cpp
index 2780044..11ba235 100644
--- a/service/jni/com_android_server_BpfNetMaps.cpp
+++ b/service/jni/com_android_server_BpfNetMaps.cpp
@@ -26,6 +26,8 @@
 #include <nativehelper/ScopedPrimitiveArray.h>
 #include <netjniutils/netjniutils.h>
 #include <net/if.h>
+#include <private/android_filesystem_config.h>
+#include <unistd.h>
 #include <vector>
 
 
@@ -48,6 +50,12 @@
 static void native_init(JNIEnv* env, jclass clazz) {
   Status status = mTc.start();
   CHECK_LOG(status);
+  if (!isOk(status)) {
+    uid_t uid = getuid();
+    ALOGE("BpfNetMaps jni init failure as uid=%d", uid);
+    // TODO: Fix tests to not use this jni lib, so we can unconditionally abort()
+    if (uid == AID_SYSTEM || uid == AID_NETWORK_STACK) abort();
+  }
 }
 
 static jint native_addNaughtyApp(JNIEnv* env, jobject self, jint uid) {
diff --git a/tests/cts/net/util/java/android/net/cts/util/CtsNetUtils.java b/tests/cts/net/util/java/android/net/cts/util/CtsNetUtils.java
index 7254319..f035f72 100644
--- a/tests/cts/net/util/java/android/net/cts/util/CtsNetUtils.java
+++ b/tests/cts/net/util/java/android/net/cts/util/CtsNetUtils.java
@@ -16,11 +16,13 @@
 
 package android.net.cts.util;
 
+import static android.Manifest.permission.NETWORK_SETTINGS;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
 import static android.net.NetworkCapabilities.TRANSPORT_TEST;
 
 import static com.android.compatibility.common.util.PropertyUtil.getFirstApiLevel;
+import static com.android.testutils.TestPermissionUtil.runAsShell;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
@@ -288,7 +290,8 @@
         filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
         mContext.registerReceiver(receiver, filter);
 
-        final WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
+        final WifiInfo wifiInfo = runAsShell(NETWORK_SETTINGS,
+                () -> mWifiManager.getConnectionInfo());
         final boolean wasWifiConnected = wifiInfo != null && wifiInfo.getNetworkId() != -1;
         // Assert that we can establish a TCP connection on wifi.
         Socket wifiBoundSocket = null;