TestNetworkService: use IFF_NO_CARRIER to bring up iface without carrier

This will be supported in kernels >= 6.0.

Test: TH
Bug: 249611919
Change-Id: Ie84e2cd4f1b5181bd29b9ccbd96775c6c5572eac
diff --git a/framework/src/android/net/TestNetworkManager.java b/framework/src/android/net/TestNetworkManager.java
index b64299f..416c6de 100644
--- a/framework/src/android/net/TestNetworkManager.java
+++ b/framework/src/android/net/TestNetworkManager.java
@@ -260,7 +260,7 @@
     /**
      * Create a tap interface with or without carrier for testing purposes.
      *
-     * Note: setting carrierUp = false is not supported until kernel version 5.0.
+     * Note: setting carrierUp = false is not supported until kernel version 6.0.
      *
      * @param carrierUp whether the created interface has a carrier or not.
      * @param bringUp whether to bring up the interface before returning it.
@@ -280,6 +280,8 @@
     /**
      * Create a tap interface for testing purposes.
      *
+     * Note: setting carrierUp = false is not supported until kernel version 6.0.
+     *
      * @param carrierUp whether the created interface has a carrier or not.
      * @param bringUp whether to bring up the interface before returning it.
      * @param disableIpv6ProvisioningDelay whether to disable DAD and RS delay.
diff --git a/service/jni/com_android_server_TestNetworkService.cpp b/service/jni/com_android_server_TestNetworkService.cpp
index bd74d54..f925732 100644
--- a/service/jni/com_android_server_TestNetworkService.cpp
+++ b/service/jni/com_android_server_TestNetworkService.cpp
@@ -38,9 +38,14 @@
 #include "jni.h"
 #include <android-base/stringprintf.h>
 #include <android-base/unique_fd.h>
+#include <bpf/KernelVersion.h>
 #include <nativehelper/JNIHelp.h>
 #include <nativehelper/ScopedUtfChars.h>
 
+#ifndef IFF_NO_CARRIER
+#define IFF_NO_CARRIER 0x0040
+#endif
+
 namespace android {
 
 //------------------------------------------------------------------------------
@@ -66,17 +71,21 @@
 
     // Allocate interface.
     ifr.ifr_flags = (isTun ? IFF_TUN : IFF_TAP) | IFF_NO_PI;
+    if (!hasCarrier) {
+        // Using IFF_NO_CARRIER is supported starting in kernel version >= 6.0
+        // Up until then, unsupported flags are ignored.
+        if (!bpf::isAtLeastKernelVersion(6, 0, 0)) {
+            throwException(env, EOPNOTSUPP, "IFF_NO_CARRIER not supported", ifr.ifr_name);
+            return -1;
+        }
+        ifr.ifr_flags |= IFF_NO_CARRIER;
+    }
     strlcpy(ifr.ifr_name, iface, IFNAMSIZ);
     if (ioctl(tun.get(), TUNSETIFF, &ifr)) {
         throwException(env, errno, "allocating", ifr.ifr_name);
         return -1;
     }
 
-    if (!hasCarrier) {
-        // disable carrier before setting IFF_UP
-        setTunTapCarrierEnabledImpl(env, iface, tun.get(), hasCarrier);
-    }
-
     // Mark some TAP interfaces as supporting multicast
     if (setIffMulticast && !isTun) {
         base::unique_fd inet6CtrlSock(socket(AF_INET6, SOCK_DGRAM, 0));