Merge "Add DisableConfigSyncTargetPreparer"
diff --git a/staticlibs/Android.bp b/staticlibs/Android.bp
index a311eb5..0e4dac2 100644
--- a/staticlibs/Android.bp
+++ b/staticlibs/Android.bp
@@ -112,6 +112,7 @@
     srcs: [
         "device/com/android/net/module/util/BpfBitmap.java",
         "device/com/android/net/module/util/BpfMap.java",
+        "device/com/android/net/module/util/BpfUtils.java",
         "device/com/android/net/module/util/HexDump.java",
         "device/com/android/net/module/util/IBpfMap.java",
         "device/com/android/net/module/util/JniUtil.java",
@@ -235,7 +236,7 @@
     libs: [
         "framework-annotations-lib",
         "framework-connectivity.stubs.module_lib",
-        "framework-connectivity-tiramisu.stubs.module_lib",
+        "framework-connectivity-t.stubs.module_lib",
     ],
     jarjar_rules: "jarjar-rules-shared.txt",
     visibility: [
@@ -286,9 +287,15 @@
         "framework-annotations-lib",
         "framework-connectivity",
     ],
+    // TODO: remove "apex_available:platform".
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.tethering",
+    ],
     visibility: [
         // TODO: remove after NetworkStatsService moves to the module.
         "//frameworks/base/services/net",
+        "//packages/modules/Connectivity/service",
         "//packages/modules/Connectivity/tests:__subpackages__",
         "//packages/modules/Bluetooth/android/app",
     ],
diff --git a/staticlibs/device/com/android/net/module/util/BpfUtils.java b/staticlibs/device/com/android/net/module/util/BpfUtils.java
new file mode 100644
index 0000000..94af11b
--- /dev/null
+++ b/staticlibs/device/com/android/net/module/util/BpfUtils.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.net.module.util;
+
+import androidx.annotation.NonNull;
+
+import java.io.IOException;
+
+/**
+ * The classes and the methods for BPF utilization.
+ *
+ * {@hide}
+ */
+public class BpfUtils {
+    static {
+        System.loadLibrary(JniUtil.getJniLibraryName(BpfUtils.class.getPackage()));
+    }
+
+    // Defined in include/uapi/linux/bpf.h. Only adding the CGROUPS currently being used for now.
+    public static final int BPF_CGROUP_INET_INGRESS = 0;
+    public static final int BPF_CGROUP_INET_EGRESS = 1;
+    public static final int BPF_CGROUP_INET4_BIND = 8;
+    public static final int BPF_CGROUP_INET6_BIND = 9;
+
+
+    /**
+     * Attach BPF program to CGROUP
+     */
+    public static void attachProgram(int type, @NonNull String programPath,
+            @NonNull String cgroupPath, int flags) throws IOException {
+        native_attachProgramToCgroup(type, programPath, cgroupPath, flags);
+    }
+
+    /**
+     * Detach BPF program from CGROUP
+     */
+    public static void detachProgram(int type, @NonNull String cgroupPath)
+            throws IOException {
+        native_detachProgramFromCgroup(type, cgroupPath);
+    }
+
+    /**
+     * Detach single BPF program from CGROUP
+     */
+    public static void detachSingleProgram(int type, @NonNull String programPath,
+            @NonNull String cgroupPath) throws IOException {
+        native_detachSingleProgramFromCgroup(type, programPath, cgroupPath);
+    }
+
+    private static native boolean native_attachProgramToCgroup(int type, String programPath,
+            String cgroupPath, int flags) throws IOException;
+    private static native boolean native_detachProgramFromCgroup(int type, String cgroupPath)
+            throws IOException;
+    private static native boolean native_detachSingleProgramFromCgroup(int type,
+            String programPath, String cgroupPath) throws IOException;
+}
diff --git a/staticlibs/native/bpf_headers/include/bpf/BpfUtils.h b/staticlibs/native/bpf_headers/include/bpf/BpfUtils.h
index 265d4b6..8f1b9a2 100644
--- a/staticlibs/native/bpf_headers/include/bpf/BpfUtils.h
+++ b/staticlibs/native/bpf_headers/include/bpf/BpfUtils.h
@@ -112,38 +112,28 @@
     return kernelVersion() >= KVER(major, minor, sub);
 }
 
-#define SKIP_IF_BPF_SUPPORTED                                                    \
-    do {                                                                         \
-        if (android::bpf::isAtLeastKernelVersion(4, 9, 0)) {                     \
-            GTEST_LOG_(INFO) << "This test is skipped since bpf is supported\n"; \
-            return;                                                              \
-        }                                                                        \
+#define SKIP_IF_BPF_SUPPORTED                              \
+    do {                                                   \
+        if (android::bpf::isAtLeastKernelVersion(4, 9, 0)) \
+            GTEST_SKIP() << "Skip: bpf is supported.";     \
     } while (0)
 
-#define SKIP_IF_BPF_NOT_SUPPORTED                                                    \
-    do {                                                                             \
-        if (!android::bpf::isAtLeastKernelVersion(4, 9, 0)) {                        \
-            GTEST_LOG_(INFO) << "This test is skipped since bpf is not supported\n"; \
-            return;                                                                  \
-        }                                                                            \
+#define SKIP_IF_BPF_NOT_SUPPORTED                           \
+    do {                                                    \
+        if (!android::bpf::isAtLeastKernelVersion(4, 9, 0)) \
+            GTEST_SKIP() << "Skip: bpf is not supported.";  \
     } while (0)
 
-#define SKIP_IF_EXTENDED_BPF_NOT_SUPPORTED                                        \
-    do {                                                                          \
-        if (!android::bpf::isAtLeastKernelVersion(4, 14, 0)) {                    \
-            GTEST_LOG_(INFO) << "This test is skipped since extended bpf feature" \
-                             << "not supported\n";                                \
-            return;                                                               \
-        }                                                                         \
+#define SKIP_IF_EXTENDED_BPF_NOT_SUPPORTED                               \
+    do {                                                                 \
+        if (!android::bpf::isAtLeastKernelVersion(4, 14, 0))             \
+            GTEST_SKIP() << "Skip: extended bpf feature not supported."; \
     } while (0)
 
-#define SKIP_IF_XDP_NOT_SUPPORTED                                \
-    do {                                                         \
-        if (!android::bpf::isAtLeastKernelVersion(5, 9, 0)) {    \
-            GTEST_LOG_(INFO) << "This test is skipped since xdp" \
-                             << "not supported\n";               \
-            return;                                              \
-        }                                                        \
+#define SKIP_IF_XDP_NOT_SUPPORTED                           \
+    do {                                                    \
+        if (!android::bpf::isAtLeastKernelVersion(5, 9, 0)) \
+            GTEST_SKIP() << "Skip: xdp not supported.";     \
     } while (0)
 
 }  // namespace bpf
diff --git a/staticlibs/native/bpfutiljni/Android.bp b/staticlibs/native/bpfutiljni/Android.bp
new file mode 100644
index 0000000..39a2795
--- /dev/null
+++ b/staticlibs/native/bpfutiljni/Android.bp
@@ -0,0 +1,44 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_library_static {
+    name: "libnet_utils_device_common_bpfutils",
+    srcs: ["com_android_net_module_util_BpfUtils.cpp"],
+    header_libs: [
+        "bpf_syscall_wrappers",
+        "jni_headers",
+    ],
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libnativehelper_compat_libc++",
+    ],
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wno-unused-parameter",
+    ],
+    min_sdk_version: "30",
+    apex_available: [
+        "com.android.tethering",
+        "//apex_available:platform",
+    ],
+    visibility: [
+        "//packages/modules/Connectivity/service",
+    ],
+}
diff --git a/staticlibs/native/bpfutiljni/com_android_net_module_util_BpfUtils.cpp b/staticlibs/native/bpfutiljni/com_android_net_module_util_BpfUtils.cpp
new file mode 100644
index 0000000..0f2ebbd
--- /dev/null
+++ b/staticlibs/native/bpfutiljni/com_android_net_module_util_BpfUtils.cpp
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/unique_fd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <jni.h>
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedLocalRef.h>
+#include <nativehelper/scoped_utf_chars.h>
+#include <string.h>
+#include <sys/socket.h>
+
+#include "BpfSyscallWrappers.h"
+
+namespace android {
+
+using base::unique_fd;
+
+// If attach fails throw error and return false.
+static jboolean com_android_net_module_util_BpfUtil_attachProgramToCgroup(JNIEnv *env,
+        jobject clazz, jint type, jstring bpfProgPath, jstring cgroupPath, jint flags) {
+
+    ScopedUtfChars dirPath(env, cgroupPath);
+    unique_fd cg_fd(open(dirPath.c_str(), O_DIRECTORY | O_RDONLY | O_CLOEXEC));
+    if (cg_fd == -1) {
+        jniThrowExceptionFmt(env, "java/io/IOException",
+                             "Failed to open the cgroup directory %s: %s",
+                             dirPath.c_str(), strerror(errno));
+        return false;
+    }
+
+    ScopedUtfChars bpfProg(env, bpfProgPath);
+    unique_fd bpf_fd(bpf::retrieveProgram(bpfProg.c_str()));
+    if (bpf_fd == -1) {
+        jniThrowExceptionFmt(env, "java/io/IOException",
+                             "Failed to retrieve bpf program from %s: %s",
+                             bpfProg.c_str(), strerror(errno));
+        return false;
+    }
+    if (bpf::attachProgram((bpf_attach_type) type, bpf_fd, cg_fd, flags)) {
+        jniThrowExceptionFmt(env, "java/io/IOException",
+                             "Failed to attach bpf program %s to %s: %s",
+                             bpfProg.c_str(), dirPath.c_str(), strerror(errno));
+        return false;
+    }
+    return true;
+}
+
+// If detach fails throw error and return false.
+static jboolean com_android_net_module_util_BpfUtil_detachProgramFromCgroup(JNIEnv *env,
+        jobject clazz, jint type, jstring cgroupPath) {
+
+    ScopedUtfChars dirPath(env, cgroupPath);
+    unique_fd cg_fd(open(dirPath.c_str(), O_DIRECTORY | O_RDONLY | O_CLOEXEC));
+    if (cg_fd == -1) {
+        jniThrowExceptionFmt(env, "java/io/IOException",
+                             "Failed to open the cgroup directory %s: %s",
+                             dirPath.c_str(), strerror(errno));
+        return false;
+    }
+
+    if (bpf::detachProgram((bpf_attach_type) type, cg_fd)) {
+        jniThrowExceptionFmt(env, "Failed to detach bpf program from %s: %s",
+                dirPath.c_str(), strerror(errno));
+        return false;
+    }
+    return true;
+}
+
+// If detach single program fails throw error and return false.
+static jboolean com_android_net_module_util_BpfUtil_detachSingleProgramFromCgroup(JNIEnv *env,
+        jobject clazz, jint type, jstring bpfProgPath, jstring cgroupPath) {
+
+    ScopedUtfChars dirPath(env, cgroupPath);
+    unique_fd cg_fd(open(dirPath.c_str(), O_DIRECTORY | O_RDONLY | O_CLOEXEC));
+    if (cg_fd == -1) {
+        jniThrowExceptionFmt(env, "java/io/IOException",
+                             "Failed to open the cgroup directory %s: %s",
+                             dirPath.c_str(), strerror(errno));
+        return false;
+    }
+
+    ScopedUtfChars bpfProg(env, bpfProgPath);
+    unique_fd bpf_fd(bpf::retrieveProgram(bpfProg.c_str()));
+    if (bpf_fd == -1) {
+        jniThrowExceptionFmt(env, "java/io/IOException",
+                             "Failed to retrieve bpf program from %s: %s",
+                             bpfProg.c_str(), strerror(errno));
+        return false;
+    }
+    if (bpf::detachSingleProgram((bpf_attach_type) type, bpf_fd, cg_fd)) {
+        jniThrowExceptionFmt(env, "Failed to detach bpf program %s from %s: %s",
+                bpfProg.c_str(), dirPath.c_str(), strerror(errno));
+        return false;
+    }
+    return true;
+}
+
+/*
+ * JNI registration.
+ */
+static const JNINativeMethod gMethods[] = {
+    /* name, signature, funcPtr */
+    { "native_attachProgramToCgroup", "(ILjava/lang/String;Ljava/lang/String;I)Z",
+        (void*) com_android_net_module_util_BpfUtil_attachProgramToCgroup },
+    { "native_detachProgramFromCgroup", "(ILjava/lang/String;)Z",
+        (void*) com_android_net_module_util_BpfUtil_detachProgramFromCgroup },
+    { "native_detachSingleProgramFromCgroup", "(ILjava/lang/String;Ljava/lang/String;)Z",
+        (void*) com_android_net_module_util_BpfUtil_detachSingleProgramFromCgroup },
+};
+
+int register_com_android_net_module_util_BpfUtils(JNIEnv* env, char const* class_name) {
+    return jniRegisterNativeMethods(env,
+            class_name,
+            gMethods, NELEM(gMethods));
+}
+
+}; // namespace android
diff --git a/staticlibs/tests/unit/src/com/android/net/module/util/InterfaceParamsTest.java b/staticlibs/tests/unit/src/com/android/net/module/util/InterfaceParamsTest.java
new file mode 100644
index 0000000..a1d8c10
--- /dev/null
+++ b/staticlibs/tests/unit/src/com/android/net/module/util/InterfaceParamsTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.net.module.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class InterfaceParamsTest {
+    @Test
+    public void testNullInterfaceReturnsNull() {
+        assertNull(InterfaceParams.getByName(null));
+    }
+
+    @Test
+    public void testNonExistentInterfaceReturnsNull() {
+        assertNull(InterfaceParams.getByName("doesnotexist0"));
+    }
+
+    @Test
+    public void testLoopback() {
+        final InterfaceParams ifParams = InterfaceParams.getByName("lo");
+        assertNotNull(ifParams);
+        assertEquals("lo", ifParams.name);
+        assertTrue(ifParams.index > 0);
+        assertNotNull(ifParams.macAddr);
+        assertFalse(ifParams.hasMacAddress);
+        assertTrue(ifParams.defaultMtu >= NetworkStackConstants.ETHER_MTU);
+    }
+}
diff --git a/staticlibs/testutils/devicetests/com/android/testutils/TestableNetworkCallback.kt b/staticlibs/testutils/devicetests/com/android/testutils/TestableNetworkCallback.kt
index acbb227..dffdbe8 100644
--- a/staticlibs/testutils/devicetests/com/android/testutils/TestableNetworkCallback.kt
+++ b/staticlibs/testutils/devicetests/com/android/testutils/TestableNetworkCallback.kt
@@ -41,6 +41,7 @@
 
 object NULL_NETWORK : Network(-1)
 object ANY_NETWORK : Network(-2)
+fun anyNetwork() = ANY_NETWORK
 
 private val Int.capabilityName get() = NetworkCapabilities.capabilityNameOf(this)
 
@@ -389,7 +390,7 @@
         val network = n ?: NULL_NETWORK
         // TODO : remove this .java access if the tests ever use kotlin-reflect. At the time of
         // this writing this would be the only use of this library in the tests.
-        assertTrue(type.java.isInstance(it) && it.network == network,
+        assertTrue(type.java.isInstance(it) && (ANY_NETWORK === n || it.network == network),
                 "Unexpected callback : $it, expected ${type.java} with Network[$network]")
     } as T