Merge "Drop path property from cpp filegroup modules" into main
diff --git a/netd/BpfHandler.cpp b/netd/BpfHandler.cpp
index a090a54..fa92f10 100644
--- a/netd/BpfHandler.cpp
+++ b/netd/BpfHandler.cpp
@@ -129,6 +129,15 @@
         RETURN_IF_NOT_OK(
                 attachProgramToCgroup(CGROUP_SOCKET_PROG_PATH, cg_fd, BPF_CGROUP_INET_SOCK_CREATE));
     }
+
+    // This should trivially pass, since we just attached up above,
+    // but BPF_PROG_QUERY is only implemented on 4.19+ kernels.
+    if (bpf::isAtLeastKernelVersion(4, 19, 0)) {
+        if (bpf::queryProgram(cg_fd, BPF_CGROUP_INET_EGRESS) <= 0) abort();
+        if (bpf::queryProgram(cg_fd, BPF_CGROUP_INET_INGRESS) <= 0) abort();
+        if (bpf::queryProgram(cg_fd, BPF_CGROUP_INET_SOCK_CREATE) <= 0) abort();
+    }
+
     return netdutils::status::ok;
 }
 
diff --git a/staticlibs/device/com/android/net/module/util/BpfUtils.java b/staticlibs/device/com/android/net/module/util/BpfUtils.java
index 94af11b..f1546c0 100644
--- a/staticlibs/device/com/android/net/module/util/BpfUtils.java
+++ b/staticlibs/device/com/android/net/module/util/BpfUtils.java
@@ -66,4 +66,6 @@
             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/native/bpf_headers/include/bpf/BpfClassic.h b/staticlibs/native/bpf_headers/include/bpf/BpfClassic.h
index f7ffddb..1ae671e 100644
--- a/staticlibs/native/bpf_headers/include/bpf/BpfClassic.h
+++ b/staticlibs/native/bpf_headers/include/bpf/BpfClassic.h
@@ -22,9 +22,15 @@
 // Reject the packet
 #define BPF_REJECT BPF_STMT(BPF_RET | BPF_K, 0)
 
+// Note arguments to BPF_JUMP(opcode, operand, true_offset, false_offset)
+
+// If not equal, jump over count instructions
+#define BPF_JUMP_IF_NOT_EQUAL(v, count) \
+	BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, (v), 0, (count))
+
 // *TWO* instructions: compare and if not equal jump over the accept statement
 #define BPF2_ACCEPT_IF_EQUAL(v) \
-	BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, (v), 0, 1), \
+	BPF_JUMP_IF_NOT_EQUAL((v), 1), \
 	BPF_ACCEPT
 
 // *TWO* instructions: compare and if equal jump over the reject statement
@@ -32,6 +38,22 @@
 	BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, (v), 1, 0), \
 	BPF_REJECT
 
+// *TWO* instructions: compare and if greater or equal jump over the reject statement
+#define BPF2_REJECT_IF_LESS_THAN(v) \
+	BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, (v), 1, 0), \
+	BPF_REJECT
+
+// *TWO* instructions: compare and if *NOT* greater jump over the reject statement
+#define BPF2_REJECT_IF_GREATER_THAN(v) \
+	BPF_JUMP(BPF_JMP | BPF_JGT | BPF_K, (v), 0, 1), \
+	BPF_REJECT
+
+// *THREE* instructions: compare and if *NOT* in range [lo, hi], jump over the reject statement
+#define BPF3_REJECT_IF_NOT_IN_RANGE(lo, hi) \
+	BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, (lo), 0, 1), \
+	BPF_JUMP(BPF_JMP | BPF_JGT | BPF_K, (hi), 0, 1), \
+	BPF_REJECT
+
 // *TWO* instructions: compare and if none of the bits are set jump over the reject statement
 #define BPF2_REJECT_IF_ANY_MASKED_BITS_SET(v) \
 	BPF_JUMP(BPF_JMP | BPF_JSET | BPF_K, (v), 0, 1), \
diff --git a/staticlibs/native/bpf_syscall_wrappers/include/BpfSyscallWrappers.h b/staticlibs/native/bpf_syscall_wrappers/include/BpfSyscallWrappers.h
index 13f7cb3..9995cb9 100644
--- a/staticlibs/native/bpf_syscall_wrappers/include/BpfSyscallWrappers.h
+++ b/staticlibs/native/bpf_syscall_wrappers/include/BpfSyscallWrappers.h
@@ -44,6 +44,11 @@
     return syscall(__NR_bpf, cmd, &attr, sizeof(attr));
 }
 
+// this version is meant for use with cmd's which mutate the argument
+inline int bpf(enum bpf_cmd cmd, bpf_attr *attr) {
+    return syscall(__NR_bpf, cmd, attr, sizeof(*attr));
+}
+
 inline int createMap(bpf_map_type map_type, uint32_t key_size, uint32_t value_size,
                      uint32_t max_entries, uint32_t map_flags) {
     return bpf(BPF_MAP_CREATE, {
@@ -160,6 +165,27 @@
                                 });
 }
 
+inline int queryProgram(const BPF_FD_TYPE cg_fd,
+                        enum bpf_attach_type attach_type,
+                        __u32 query_flags = 0,
+                        __u32 attach_flags = 0) {
+    int prog_id = -1;  // equivalent to an array of one integer.
+    bpf_attr arg = {
+            .query = {
+                    .target_fd = BPF_FD_TO_U32(cg_fd),
+                    .attach_type = attach_type,
+                    .query_flags = query_flags,
+                    .attach_flags = attach_flags,
+                    .prog_ids = ptr_to_u64(&prog_id),  // pointer to output array
+                    .prog_cnt = 1,  // in: space - nr of ints in the array, out: used
+            }
+    };
+    int v = bpf(BPF_PROG_QUERY, &arg);
+    if (v) return v;  // error case
+    if (!arg.query.prog_cnt) return 0;  // no program, kernel never returns zero id
+    return prog_id;  // return actual id
+}
+
 inline int detachSingleProgram(bpf_attach_type type, const BPF_FD_TYPE prog_fd,
                                const BPF_FD_TYPE cg_fd) {
     return bpf(BPF_PROG_DETACH, {
diff --git a/staticlibs/native/bpfmapjni/com_android_net_module_util_TcUtils.cpp b/staticlibs/native/bpfmapjni/com_android_net_module_util_TcUtils.cpp
index cb06afb..ab83da6 100644
--- a/staticlibs/native/bpfmapjni/com_android_net_module_util_TcUtils.cpp
+++ b/staticlibs/native/bpfmapjni/com_android_net_module_util_TcUtils.cpp
@@ -27,7 +27,7 @@
 }
 
 static jboolean com_android_net_module_util_TcUtils_isEthernet(JNIEnv *env,
-                                                               jobject clazz,
+                                                               jclass clazz,
                                                                jstring iface) {
   ScopedUtfChars interface(env, iface);
   bool result = false;
@@ -43,7 +43,7 @@
 // tc filter add dev .. in/egress prio 1 protocol ipv6/ip bpf object-pinned
 // /sys/fs/bpf/... direct-action
 static void com_android_net_module_util_TcUtils_tcFilterAddDevBpf(
-    JNIEnv *env, jobject clazz, jint ifIndex, jboolean ingress, jshort prio,
+    JNIEnv *env, jclass clazz, jint ifIndex, jboolean ingress, jshort prio,
     jshort proto, jstring bpfProgPath) {
   ScopedUtfChars pathname(env, bpfProgPath);
   int error = tcAddBpfFilter(ifIndex, ingress, prio, proto, pathname.c_str());
@@ -59,7 +59,7 @@
 //     action bpf object-pinned .. \
 //     drop
 static void com_android_net_module_util_TcUtils_tcFilterAddDevIngressPolice(
-    JNIEnv *env, jobject clazz, jint ifIndex, jshort prio, jshort proto,
+    JNIEnv *env, jclass clazz, jint ifIndex, jshort prio, jshort proto,
     jint rateInBytesPerSec, jstring bpfProgPath) {
   ScopedUtfChars pathname(env, bpfProgPath);
   int error = tcAddIngressPoliceFilter(ifIndex, prio, proto, rateInBytesPerSec,
@@ -74,7 +74,7 @@
 
 // tc filter del dev .. in/egress prio .. protocol ..
 static void com_android_net_module_util_TcUtils_tcFilterDelDev(
-    JNIEnv *env, jobject clazz, jint ifIndex, jboolean ingress, jshort prio,
+    JNIEnv *env, jclass clazz, jint ifIndex, jboolean ingress, jshort prio,
     jshort proto) {
   int error = tcDeleteFilter(ifIndex, ingress, prio, proto);
   if (error) {
@@ -86,7 +86,7 @@
 
 // tc qdisc add dev .. clsact
 static void com_android_net_module_util_TcUtils_tcQdiscAddDevClsact(JNIEnv *env,
-                                                                    jobject clazz,
+                                                                    jclass clazz,
                                                                     jint ifIndex) {
   int error = tcAddQdiscClsact(ifIndex);
   if (error) {
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 0f2ebbd..cf09379 100644
--- a/staticlibs/native/bpfutiljni/com_android_net_module_util_BpfUtils.cpp
+++ b/staticlibs/native/bpfutiljni/com_android_net_module_util_BpfUtils.cpp
@@ -32,7 +32,7 @@
 
 // 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) {
+        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));
@@ -62,7 +62,7 @@
 
 // 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) {
+        jclass clazz, jint type, jstring cgroupPath) {
 
     ScopedUtfChars dirPath(env, cgroupPath);
     unique_fd cg_fd(open(dirPath.c_str(), O_DIRECTORY | O_RDONLY | O_CLOEXEC));
@@ -83,7 +83,7 @@
 
 // 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) {
+        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));
@@ -110,6 +110,29 @@
     return true;
 }
 
+static jint com_android_net_module_util_BpfUtil_getProgramIdFromCgroup(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 -1;
+    }
+
+    int id = bpf::queryProgram(cg_fd, (bpf_attach_type) type);
+    if (id < 0) {
+        jniThrowExceptionFmt(env, "java/io/IOException",
+                             "Failed to query bpf program %d at %s: %s",
+                             type, dirPath.c_str(), strerror(errno));
+        return -1;
+    }
+    return id;  // may return 0 meaning none
+}
+
+
 /*
  * JNI registration.
  */
@@ -121,6 +144,8 @@
         (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 },
 };
 
 int register_com_android_net_module_util_BpfUtils(JNIEnv* env, char const* class_name) {
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
index 89a55a7..b9ed56a 100644
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
@@ -198,7 +198,8 @@
     protected void tearDown() throws Exception {
         executeShellCommand("cmd netpolicy stop-watching");
         mServiceClient.unbind();
-        if (mLock.isHeld()) mLock.release();
+        final PowerManager.WakeLock lock = mLock;
+        if (null != lock && lock.isHeld()) lock.release();
     }
 
     protected int getUid(String packageName) throws Exception {
diff --git a/tests/integration/AndroidManifest.xml b/tests/integration/AndroidManifest.xml
index 50f02d3..cea83c7 100644
--- a/tests/integration/AndroidManifest.xml
+++ b/tests/integration/AndroidManifest.xml
@@ -40,6 +40,8 @@
     <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
     <!-- Querying the resources package -->
     <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
+    <!-- Register UidFrozenStateChangedCallback -->
+    <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"/>
     <application android:debuggable="true">
         <uses-library android:name="android.test.runner"/>