Merge "[Thread] make the Manager and Controller class 'final'" into main
diff --git a/netbpfload/NetBpfLoad.cpp b/netbpfload/NetBpfLoad.cpp
index d150373..6152287 100644
--- a/netbpfload/NetBpfLoad.cpp
+++ b/netbpfload/NetBpfLoad.cpp
@@ -38,6 +38,7 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 
+#include <android/api-level.h>
 #include <android-base/logging.h>
 #include <android-base/macros.h>
 #include <android-base/properties.h>
@@ -172,6 +173,9 @@
     (void)argc;
     android::base::InitLogging(argv, &android::base::KernelLogger);
 
+    const int device_api_level = android_get_device_api_level();
+    const bool isAtLeastU = (device_api_level >= __ANDROID_API_U__);
+
     if (!android::bpf::isAtLeastKernelVersion(4, 19, 0)) {
         ALOGE("Android U QPR2 requires kernel 4.19.");
         return 1;
@@ -208,24 +212,27 @@
         return 1;
     }
 
-    // Linux 5.16-rc1 changed the default to 2 (disabled but changeable), but we need 0 (enabled)
-    // (this writeFile is known to fail on at least 4.19, but always defaults to 0 on pre-5.13,
-    // on 5.13+ it depends on CONFIG_BPF_UNPRIV_DEFAULT_OFF)
-    if (writeProcSysFile("/proc/sys/kernel/unprivileged_bpf_disabled", "0\n") &&
-        android::bpf::isAtLeastKernelVersion(5, 13, 0)) return 1;
+    if (isAtLeastU) {
+        // Linux 5.16-rc1 changed the default to 2 (disabled but changeable),
+        // but we need 0 (enabled)
+        // (this writeFile is known to fail on at least 4.19, but always defaults to 0 on
+        // pre-5.13, on 5.13+ it depends on CONFIG_BPF_UNPRIV_DEFAULT_OFF)
+        if (writeProcSysFile("/proc/sys/kernel/unprivileged_bpf_disabled", "0\n") &&
+            android::bpf::isAtLeastKernelVersion(5, 13, 0)) return 1;
 
-    // Enable the eBPF JIT -- but do note that on 64-bit kernels it is likely
-    // already force enabled by the kernel config option BPF_JIT_ALWAYS_ON.
-    // (Note: this (open) will fail with ENOENT 'No such file or directory' if
-    //  kernel does not have CONFIG_BPF_JIT=y)
-    // BPF_JIT is required by R VINTF (which means 4.14/4.19/5.4 kernels),
-    // but 4.14/4.19 were released with P & Q, and only 5.4 is new in R+.
-    if (writeProcSysFile("/proc/sys/net/core/bpf_jit_enable", "1\n")) return 1;
+        // Enable the eBPF JIT -- but do note that on 64-bit kernels it is likely
+        // already force enabled by the kernel config option BPF_JIT_ALWAYS_ON.
+        // (Note: this (open) will fail with ENOENT 'No such file or directory' if
+        //  kernel does not have CONFIG_BPF_JIT=y)
+        // BPF_JIT is required by R VINTF (which means 4.14/4.19/5.4 kernels),
+        // but 4.14/4.19 were released with P & Q, and only 5.4 is new in R+.
+        if (writeProcSysFile("/proc/sys/net/core/bpf_jit_enable", "1\n")) return 1;
 
-    // Enable JIT kallsyms export for privileged users only
-    // (Note: this (open) will fail with ENOENT 'No such file or directory' if
-    //  kernel does not have CONFIG_HAVE_EBPF_JIT=y)
-    if (writeProcSysFile("/proc/sys/net/core/bpf_jit_kallsyms", "1\n")) return 1;
+        // Enable JIT kallsyms export for privileged users only
+        // (Note: this (open) will fail with ENOENT 'No such file or directory' if
+        //  kernel does not have CONFIG_HAVE_EBPF_JIT=y)
+        if (writeProcSysFile("/proc/sys/net/core/bpf_jit_kallsyms", "1\n")) return 1;
+    }
 
     // Create all the pin subdirectories
     // (this must be done first to allow selinux_context and pin_subdir functionality,
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index c559fa3..c4cb4c7 100755
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -1538,9 +1538,9 @@
         /**
          * Get BPF program Id from CGROUP. See {@link BpfUtils#getProgramId}.
          */
-        public int getBpfProgramId(final int attachType, @NonNull final String cgroupPath)
+        public int getBpfProgramId(final int attachType)
                 throws IOException {
-            return BpfUtils.getProgramId(attachType, cgroupPath);
+            return BpfUtils.getProgramId(attachType);
         }
 
         /**
@@ -3274,15 +3274,15 @@
         pw.increaseIndent();
         try {
             pw.print("CGROUP_INET_INGRESS: ");
-            pw.println(mDeps.getBpfProgramId(BPF_CGROUP_INET_INGRESS, BpfUtils.CGROUP_PATH));
+            pw.println(mDeps.getBpfProgramId(BPF_CGROUP_INET_INGRESS));
             pw.print("CGROUP_INET_EGRESS: ");
-            pw.println(mDeps.getBpfProgramId(BPF_CGROUP_INET_EGRESS, BpfUtils.CGROUP_PATH));
+            pw.println(mDeps.getBpfProgramId(BPF_CGROUP_INET_EGRESS));
             pw.print("CGROUP_INET_SOCK_CREATE: ");
-            pw.println(mDeps.getBpfProgramId(BPF_CGROUP_INET_SOCK_CREATE, BpfUtils.CGROUP_PATH));
+            pw.println(mDeps.getBpfProgramId(BPF_CGROUP_INET_SOCK_CREATE));
             pw.print("CGROUP_INET4_BIND: ");
-            pw.println(mDeps.getBpfProgramId(BPF_CGROUP_INET4_BIND, BpfUtils.CGROUP_PATH));
+            pw.println(mDeps.getBpfProgramId(BPF_CGROUP_INET4_BIND));
             pw.print("CGROUP_INET6_BIND: ");
-            pw.println(mDeps.getBpfProgramId(BPF_CGROUP_INET6_BIND, BpfUtils.CGROUP_PATH));
+            pw.println(mDeps.getBpfProgramId(BPF_CGROUP_INET6_BIND));
         } catch (IOException e) {
             pw.println("  IOException");
         }
@@ -10816,7 +10816,7 @@
                         // If type can't be parsed, this throws NumberFormatException, which
                         // is passed back to adb who prints it.
                         final int type = Integer.parseInt(getNextArg());
-                        final int ret = BpfUtils.getProgramId(type, BpfUtils.CGROUP_PATH);
+                        final int ret = BpfUtils.getProgramId(type);
                         pw.println(ret);
                         return 0;
                     }
diff --git a/staticlibs/device/com/android/net/module/util/BpfMap.java b/staticlibs/device/com/android/net/module/util/BpfMap.java
index d45cace..595ac74 100644
--- a/staticlibs/device/com/android/net/module/util/BpfMap.java
+++ b/staticlibs/device/com/android/net/module/util/BpfMap.java
@@ -187,12 +187,6 @@
         return nativeDeleteMapEntry(mMapFd.getFd(), key.writeToBytes());
     }
 
-    /** Returns {@code true} if this map contains no elements. */
-    @Override
-    public boolean isEmpty() throws ErrnoException {
-        return getFirstKey() == null;
-    }
-
     private K getNextKeyInternal(@Nullable K key) throws ErrnoException {
         byte[] rawKey = new byte[mKeySize];
 
@@ -245,49 +239,6 @@
         return Struct.parse(mValueClass, buffer);
     }
 
-    /**
-     * Iterate through the map and handle each key -> value retrieved base on the given BiConsumer.
-     * The given BiConsumer may to delete the passed-in entry, but is not allowed to perform any
-     * other structural modifications to the map, such as adding entries or deleting other entries.
-     * Otherwise, iteration will result in undefined behaviour.
-     */
-    @Override
-    public void forEach(ThrowingBiConsumer<K, V> action) throws ErrnoException {
-        @Nullable K nextKey = getFirstKey();
-
-        while (nextKey != null) {
-            @NonNull final K curKey = nextKey;
-            @NonNull final V value = getValue(curKey);
-
-            nextKey = getNextKey(curKey);
-            action.accept(curKey, value);
-        }
-    }
-
-    /* Empty implementation to implement AutoCloseable, so we can use BpfMaps
-     * with try with resources, but due to persistent FD cache, there is no actual
-     * need to close anything.  File descriptors will actually be closed when we
-     * unlock the BpfMap class and destroy the ParcelFileDescriptor objects.
-     */
-    @Override
-    public void close() throws IOException {
-    }
-
-    /**
-     * Clears the map. The map may already be empty.
-     *
-     * @throws ErrnoException if the map is already closed, if an error occurred during iteration,
-     *                        or if a non-ENOENT error occurred when deleting a key.
-     */
-    @Override
-    public void clear() throws ErrnoException {
-        K key = getFirstKey();
-        while (key != null) {
-            deleteEntry(key);  // ignores ENOENT.
-            key = getFirstKey();
-        }
-    }
-
     private static native int nativeBpfFdGet(String path, int mode, int keySize, int valueSize)
             throws ErrnoException, NullPointerException;
 
diff --git a/staticlibs/device/com/android/net/module/util/BpfUtils.java b/staticlibs/device/com/android/net/module/util/BpfUtils.java
index 6116a5f..10a8f60 100644
--- a/staticlibs/device/com/android/net/module/util/BpfUtils.java
+++ b/staticlibs/device/com/android/net/module/util/BpfUtils.java
@@ -41,49 +41,18 @@
     public static final String CGROUP_PATH = "/sys/fs/cgroup/";
 
     /**
-     * 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);
-    }
-
-    /**
      * Get BPF program Id from CGROUP.
      *
      * Note: This requires a 4.19 kernel which is only guaranteed on V+.
      *
      * @param attachType Bpf attach type. See bpf_attach_type in include/uapi/linux/bpf.h.
-     * @param cgroupPath Path of cgroup.
      * @return Positive integer for a Program Id. 0 if no program is attached.
      * @throws IOException if failed to open the cgroup directory or query bpf program.
      */
-    public static int getProgramId(int attachType, @NonNull String cgroupPath) throws IOException {
-        return native_getProgramIdFromCgroup(attachType, cgroupPath);
+    public static int getProgramId(int attachType) throws IOException {
+        return native_getProgramIdFromCgroup(attachType, CGROUP_PATH);
     }
 
-    /**
-     * 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;
     private static native int native_getProgramIdFromCgroup(int type, String cgroupPath)
             throws IOException;
 }
diff --git a/staticlibs/device/com/android/net/module/util/IBpfMap.java b/staticlibs/device/com/android/net/module/util/IBpfMap.java
index 83ff875..ca56830 100644
--- a/staticlibs/device/com/android/net/module/util/IBpfMap.java
+++ b/staticlibs/device/com/android/net/module/util/IBpfMap.java
@@ -18,6 +18,7 @@
 import android.system.ErrnoException;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 
 import java.io.IOException;
 import java.util.NoSuchElementException;
@@ -49,15 +50,17 @@
     /** Remove existing key from eBpf map. Return true if something was deleted. */
     boolean deleteEntry(K key) throws ErrnoException;
 
-    /** Returns {@code true} if this map contains no elements. */
-    boolean isEmpty() throws ErrnoException;
-
     /** Get the key after the passed-in key. */
     K getNextKey(@NonNull K key) throws ErrnoException;
 
     /** Get the first key of the eBpf map. */
     K getFirstKey() throws ErrnoException;
 
+    /** Returns {@code true} if this map contains no elements. */
+    default boolean isEmpty() throws ErrnoException {
+        return getFirstKey() == null;
+    }
+
     /** Check whether a key exists in the map. */
     boolean containsKey(@NonNull K key) throws ErrnoException;
 
@@ -70,13 +73,38 @@
 
     /**
      * Iterate through the map and handle each key -> value retrieved base on the given BiConsumer.
+     * The given BiConsumer may to delete the passed-in entry, but is not allowed to perform any
+     * other structural modifications to the map, such as adding entries or deleting other entries.
+     * Otherwise, iteration will result in undefined behaviour.
      */
-    void forEach(ThrowingBiConsumer<K, V> action) throws ErrnoException;
+    default public void forEach(ThrowingBiConsumer<K, V> action) throws ErrnoException {
+        @Nullable K nextKey = getFirstKey();
 
-    /** Clears the map. */
-    void clear() throws ErrnoException;
+        while (nextKey != null) {
+            @NonNull final K curKey = nextKey;
+            @NonNull final V value = getValue(curKey);
+
+            nextKey = getNextKey(curKey);
+            action.accept(curKey, value);
+        }
+    }
+
+    /**
+     * Clears the map. The map may already be empty.
+     *
+     * @throws ErrnoException if the map is already closed, if an error occurred during iteration,
+     *                        or if a non-ENOENT error occurred when deleting a key.
+     */
+    default public void clear() throws ErrnoException {
+        K key = getFirstKey();
+        while (key != null) {
+            deleteEntry(key);  // ignores ENOENT.
+            key = getFirstKey();
+        }
+    }
 
     /** Close for AutoCloseable. */
     @Override
-    void close() throws IOException;
+    default void close() throws IOException {
+    };
 }
diff --git a/staticlibs/native/bpfutiljni/com_android_net_module_util_BpfUtils.cpp b/staticlibs/native/bpfutiljni/com_android_net_module_util_BpfUtils.cpp
index cf09379..bcc3ded 100644
--- a/staticlibs/native/bpfutiljni/com_android_net_module_util_BpfUtils.cpp
+++ b/staticlibs/native/bpfutiljni/com_android_net_module_util_BpfUtils.cpp
@@ -30,86 +30,6 @@
 
 using base::unique_fd;
 
-// If attach fails throw error and return false.
-static jboolean com_android_net_module_util_BpfUtil_attachProgramToCgroup(JNIEnv *env,
-        jclass 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,
-        jclass 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,
-        jclass 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;
-}
-
 static jint com_android_net_module_util_BpfUtil_getProgramIdFromCgroup(JNIEnv *env,
         jclass clazz, jint type, jstring cgroupPath) {
 
@@ -138,12 +58,6 @@
  */
 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 },
     { "native_getProgramIdFromCgroup", "(ILjava/lang/String;)I",
         (void*) com_android_net_module_util_BpfUtil_getProgramIdFromCgroup },
 };
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index 194cec3..11cece1 100755
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -2299,7 +2299,7 @@
         }
 
         @Override
-        public int getBpfProgramId(final int attachType, @NonNull final String cgroupPath) {
+        public int getBpfProgramId(final int attachType) {
             return 0;
         }