bpf: move isAtLeastX to BpfUtils.h

Partially due to:
  https://android-review.googlesource.com/c/platform/bionic/+/3497280

Test: TreeHugger
Signed-off-by: Maciej Żenczykowski <maze@google.com>
Change-Id: I74a626c45d641e226d7f71e00d0b542c5701417d
diff --git a/bpf/headers/include/bpf/BpfUtils.h b/bpf/headers/include/bpf/BpfUtils.h
index 9e8b2c7..ed08e1a 100644
--- a/bpf/headers/include/bpf/BpfUtils.h
+++ b/bpf/headers/include/bpf/BpfUtils.h
@@ -26,6 +26,7 @@
 #include <sys/socket.h>
 #include <sys/utsname.h>
 
+#include <android-base/properties.h>
 #include <log/log.h>
 
 #include "KernelUtils.h"
@@ -33,6 +34,16 @@
 namespace android {
 namespace bpf {
 
+const bool unreleased = (base::GetProperty("ro.build.version.codename", "REL") != "REL");
+const int api_level = unreleased ? 10000 : android_get_device_api_level();
+const bool isAtLeastR = (api_level >= 30);
+const bool isAtLeastS = (api_level >= 31);
+// Sv2 is 32
+const bool isAtLeastT = (api_level >= 33);
+const bool isAtLeastU = (api_level >= 34);
+const bool isAtLeastV = (api_level >= 35);
+const bool isAtLeast25Q2 = (api_level >= 36);
+
 // See kernel's net/core/sock_diag.c __sock_gen_cookie()
 // the implementation of which guarantees 0 will never be returned,
 // primarily because 0 is used to mean not yet initialized,
diff --git a/bpf/loader/NetBpfLoad.cpp b/bpf/loader/NetBpfLoad.cpp
index 40d1281..9486e75 100644
--- a/bpf/loader/NetBpfLoad.cpp
+++ b/bpf/loader/NetBpfLoad.cpp
@@ -1414,37 +1414,6 @@
 static int doLoad(char** argv, char * const envp[]) {
     const bool runningAsRoot = !getuid();  // true iff U QPR3 or V+
 
-    // Any released device will have codename REL instead of a 'real' codename.
-    // For safety: default to 'REL' so we default to unreleased=false on failure.
-    const bool unreleased = (GetProperty("ro.build.version.codename", "REL") != "REL");
-
-    // goog/main device_api_level is bumped *way* before aosp/main api level
-    // (the latter only gets bumped during the push of goog/main to aosp/main)
-    //
-    // Since we develop in AOSP, we want it to behave as if it was bumped too.
-    //
-    // Note that AOSP doesn't really have a good api level (for example during
-    // early V dev cycle, it would have *all* of T, some but not all of U, and some V).
-    // One could argue that for our purposes AOSP api level should be infinite or 10000.
-    //
-    // This could also cause api to be increased in goog/main or other branches,
-    // but I can't imagine a case where this would be a problem: the problem
-    // is rather a too low api level, rather than some ill defined high value.
-    // For example as I write this aosp is 34/U, and goog is 35/V,
-    // we want to treat both goog & aosp as 35/V, but it's harmless if we
-    // treat goog as 36 because that value isn't yet defined to mean anything,
-    // and we thus never compare against it.
-    //
-    // Also note that 'android_get_device_api_level()' is what the
-    //   //system/core/init/apex_init_util.cpp
-    // apex init .XXrc parsing code uses for XX filtering, and that code
-    // (now) similarly uses __ANDROID_API_FUTURE__ for non 'REL' codenames.
-    const int api_level = unreleased ? __ANDROID_API_FUTURE__ : android_get_device_api_level();
-    const bool isAtLeastT = (api_level >= __ANDROID_API_T__);
-    const bool isAtLeastU = (api_level >= __ANDROID_API_U__);
-    const bool isAtLeastV = (api_level >= __ANDROID_API_V__);
-    const bool isAtLeast25Q2 = (api_level > __ANDROID_API_V__);  // TODO: fix >
-
     const int first_api_level = GetIntProperty("ro.board.first_api_level", api_level);
 
     // last in U QPR2 beta1
@@ -1591,7 +1560,7 @@
         if (isArm() && (isTV() || isWear())) {
             // exempt Arm TV or Wear devices (arm32 ABI is far less problematic than x86-32)
             ALOGW("[Arm TV/Wear] 32-bit userspace unsupported on 6.2+ kernels.");
-        } else if (first_api_level <= __ANDROID_API_T__ && isArm()) {
+        } else if (first_api_level <= 33 /*T*/ && isArm()) {
             // also exempt Arm devices upgrading with major kernel rev from T-
             // might possibly be better for them to run with a newer kernel...
             ALOGW("[Arm KernelUpRev] 32-bit userspace unsupported on 6.2+ kernels.");
diff --git a/bpf/netd/BpfHandler.cpp b/bpf/netd/BpfHandler.cpp
index 125f26b..e3e508b 100644
--- a/bpf/netd/BpfHandler.cpp
+++ b/bpf/netd/BpfHandler.cpp
@@ -22,7 +22,6 @@
 #include <inttypes.h>
 
 #include <android-base/unique_fd.h>
-#include <android-modules-utils/sdk_level.h>
 #include <bpf/WaitForProgsLoaded.h>
 #include <log/log.h>
 #include <netdutils/UidConstants.h>
@@ -37,6 +36,10 @@
 using base::WaitForProperty;
 using bpf::getSocketCookie;
 using bpf::isAtLeastKernelVersion;
+using bpf::isAtLeastT;
+using bpf::isAtLeastU;
+using bpf::isAtLeastV;
+using bpf::isAtLeast25Q2;
 using bpf::queryProgram;
 using bpf::retrieveProgram;
 using netdutils::Status;
@@ -72,18 +75,11 @@
     return netdutils::status::ok;
 }
 
-// Checks if the device is running on release version of Android 25Q2 or newer.
-static bool isAtLeast25Q2() {
-    return android_get_device_api_level() >= 36 ||
-           (android_get_device_api_level() == 35 &&
-            modules::sdklevel::detail::IsAtLeastPreReleaseCodename("Baklava"));
-}
-
 static Status initPrograms(const char* cg2_path) {
     if (!cg2_path) return Status("cg2_path is NULL");
 
     // This code was mainlined in T, so this should be trivially satisfied.
-    if (!modules::sdklevel::IsAtLeastT()) return Status("S- platform is unsupported");
+    if (!isAtLeastT) return Status("S- platform is unsupported");
 
     // S requires eBPF support which was only added in 4.9, so this should be satisfied.
     if (!isAtLeastKernelVersion(4, 9, 0)) {
@@ -91,22 +87,22 @@
     }
 
     // U bumps the kernel requirement up to 4.14
-    if (modules::sdklevel::IsAtLeastU() && !isAtLeastKernelVersion(4, 14, 0)) {
+    if (isAtLeastU && !isAtLeastKernelVersion(4, 14, 0)) {
         return Status("U+ platform with kernel version < 4.14.0 is unsupported");
     }
 
     // U mandates this mount point (though it should also be the case on T)
-    if (modules::sdklevel::IsAtLeastU() && !!strcmp(cg2_path, "/sys/fs/cgroup")) {
+    if (isAtLeastU && !!strcmp(cg2_path, "/sys/fs/cgroup")) {
         return Status("U+ platform with cg2_path != /sys/fs/cgroup is unsupported");
     }
 
     // V bumps the kernel requirement up to 4.19
-    if (modules::sdklevel::IsAtLeastV() && !isAtLeastKernelVersion(4, 19, 0)) {
+    if (isAtLeastV && !isAtLeastKernelVersion(4, 19, 0)) {
         return Status("V+ platform with kernel version < 4.19.0 is unsupported");
     }
 
     // 25Q2 bumps the kernel requirement up to 5.4
-    if (isAtLeast25Q2() && !isAtLeastKernelVersion(5, 4, 0)) {
+    if (isAtLeast25Q2 && !isAtLeastKernelVersion(5, 4, 0)) {
         return Status("25Q2+ platform with kernel version < 5.4.0 is unsupported");
     }
 
@@ -135,7 +131,7 @@
                                     cg_fd, BPF_CGROUP_INET_SOCK_RELEASE));
     }
 
-    if (modules::sdklevel::IsAtLeastV()) {
+    if (isAtLeastV) {
         // V requires 4.19+, so technically this 2nd 'if' is not required, but it
         // doesn't hurt us to try to support AOSP forks that try to support older kernels.
         if (isAtLeastKernelVersion(4, 19, 0)) {
@@ -180,7 +176,7 @@
         if (queryProgram(cg_fd, BPF_CGROUP_INET_SOCK_RELEASE) <= 0) abort();
     }
 
-    if (modules::sdklevel::IsAtLeastV()) {
+    if (isAtLeastV) {
         // V requires 4.19+, so technically this 2nd 'if' is not required, but it
         // doesn't hurt us to try to support AOSP forks that try to support older kernels.
         if (isAtLeastKernelVersion(4, 19, 0)) {
@@ -266,14 +262,13 @@
     // ...unless someone changed 'exec_start bpfloader' to 'start bpfloader'
     // in the rc file.
     //
-    // TODO: should be: if (!modules::sdklevel::IsAtLeastW())
-    if (android_get_device_api_level() <= __ANDROID_API_V__) waitForBpf();
+    if (!isAtLeast25Q2) waitForBpf();
 
     RETURN_IF_NOT_OK(initPrograms(cg2_path));
     RETURN_IF_NOT_OK(initMaps());
 
-    if (android_get_device_api_level() > __ANDROID_API_V__) {
-        // make sure netd can create & write maps.  sepolicy is V+, but enough to enforce on 25Q2+
+    if (isAtLeast25Q2) {
+        // Make sure netd can create & write maps.  sepolicy is V+, but enough to enforce on 25Q2+
         int key = 1;
         int value = 123;
         unique_fd map(bpf::createMap(BPF_MAP_TYPE_ARRAY, sizeof(key), sizeof(value), 2, 0));
diff --git a/bpf/tests/mts/bpf_existence_test.cpp b/bpf/tests/mts/bpf_existence_test.cpp
index 0ecda3d..75fb8e9 100644
--- a/bpf/tests/mts/bpf_existence_test.cpp
+++ b/bpf/tests/mts/bpf_existence_test.cpp
@@ -31,6 +31,12 @@
 using std::string;
 
 using android::bpf::isAtLeastKernelVersion;
+using android::bpf::isAtLeastR;
+using android::bpf::isAtLeastS;
+using android::bpf::isAtLeastT;
+using android::bpf::isAtLeastU;
+using android::bpf::isAtLeastV;
+using android::bpf::isAtLeast25Q2;
 
 #define PLATFORM "/sys/fs/bpf/"
 #define TETHERING "/sys/fs/bpf/tethering/"
@@ -42,16 +48,6 @@
 class BpfExistenceTest : public ::testing::Test {
 };
 
-const bool unreleased = (android::base::GetProperty("ro.build.version.codename", "REL") != "REL");
-const int api_level = unreleased ? 10000 : android_get_device_api_level();
-const bool isAtLeastR = (api_level >= 30);
-const bool isAtLeastS = (api_level >= 31);
-// Sv2 is 32
-const bool isAtLeastT = (api_level >= 33);
-const bool isAtLeastU = (api_level >= 34);
-const bool isAtLeastV = (api_level >= 35);
-const bool isAtLeast25Q2 = (api_level >= 36);
-
 // Part of Android R platform (for 4.9+), but mainlined in S
 static const set<string> PLATFORM_ONLY_IN_R = {
     PLATFORM "map_offload_tether_ingress_map",
diff --git a/tests/unit/jni/Android.bp b/tests/unit/jni/Android.bp
index 1a833e1..1e9db03 100644
--- a/tests/unit/jni/Android.bp
+++ b/tests/unit/jni/Android.bp
@@ -22,6 +22,7 @@
     ],
 
     shared_libs: [
+        "libbase",
         "liblog",
         "libnativehelper",
         "libnetdutils",