Merge "Save uid netd network permissions"
diff --git a/Tethering/Android.bp b/Tethering/Android.bp
index 3c49383..e934d6d 100644
--- a/Tethering/Android.bp
+++ b/Tethering/Android.bp
@@ -179,7 +179,11 @@
 
 android_app {
     name: "TetheringNext",
-    defaults: ["TetheringAppDefaults", "TetheringApiLevel"],
+    defaults: [
+        "TetheringAppDefaults",
+        "TetheringApiLevel",
+        "ConnectivityNextEnableDefaults",
+    ],
     static_libs: ["TetheringApiCurrentLib"],
     certificate: "networkstack",
     manifest: "AndroidManifest.xml",
diff --git a/Tethering/apex/Android.bp b/Tethering/apex/Android.bp
index a5216f7..7863572 100644
--- a/Tethering/apex/Android.bp
+++ b/Tethering/apex/Android.bp
@@ -18,8 +18,26 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
+// Defaults to enable/disable java targets which uses development APIs. "enabled" may have a
+// different value depending on the branch.
+java_defaults {
+    name: "ConnectivityNextEnableDefaults",
+    enabled: true,
+}
+apex_defaults {
+    name: "ConnectivityApexDefaults",
+    // Tethering app to include in the AOSP apex. Branches that disable the "next" targets may use
+    // a stable tethering app instead, but will generally override the AOSP apex to use updatable
+    // package names and keys, so that apex will be unused anyway.
+    apps: ["TetheringNext"], // Replace to "Tethering" if ConnectivityNextEnableDefaults is false.
+}
+// This is a placeholder comment to avoid merge conflicts
+// as the above target may have different "enabled" values
+// depending on the branch
+
 apex {
     name: "com.android.tethering",
+    defaults: ["ConnectivityApexDefaults"],
     compile_multilib: "both",
     updatable: true,
     min_sdk_version: "30",
@@ -43,7 +61,6 @@
     ],
     apps: [
         "ServiceConnectivityResources",
-        "TetheringNext",
     ],
     prebuilts: ["current_sdkinfo"],
     manifest: "manifest.json",
diff --git a/Tethering/jni/com_android_networkstack_tethering_BpfUtils.cpp b/Tethering/jni/com_android_networkstack_tethering_BpfUtils.cpp
index 9838bf1..f9e4824 100644
--- a/Tethering/jni/com_android_networkstack_tethering_BpfUtils.cpp
+++ b/Tethering/jni/com_android_networkstack_tethering_BpfUtils.cpp
@@ -26,6 +26,7 @@
 #include <net/if.h>
 #include <stdio.h>
 #include <sys/socket.h>
+#include <sys/utsname.h>
 
 // TODO: use unique_fd.
 #define BPF_FD_JUST_USE_INT
@@ -158,6 +159,37 @@
     return rv;
 }
 
+// -----------------------------------------------------------------------------
+// TODO - just use BpfUtils.h once that is available in sc-mainline-prod and has kernelVersion()
+//
+// In the mean time copying verbatim from:
+//   system/bpf/libbpf_android/include/bpf/BpfUtils.h
+// and
+//   system/bpf/libbpf_android/BpfUtils.cpp
+
+#define KVER(a, b, c) (((a) << 24) + ((b) << 16) + (c))
+
+static unsigned kernelVersion() {
+    struct utsname buf;
+    int ret = uname(&buf);
+    if (ret) return 0;
+
+    unsigned kver_major;
+    unsigned kver_minor;
+    unsigned kver_sub;
+    char discard;
+    ret = sscanf(buf.release, "%u.%u.%u%c", &kver_major, &kver_minor, &kver_sub, &discard);
+    // Check the device kernel version
+    if (ret < 3) return 0;
+
+    return KVER(kver_major, kver_minor, kver_sub);
+}
+
+static inline bool isAtLeastKernelVersion(unsigned major, unsigned minor, unsigned sub) {
+    return kernelVersion() >= KVER(major, minor, sub);
+}
+// -----------------------------------------------------------------------------
+
 static jboolean com_android_networkstack_tethering_BpfUtils_isEthernet(JNIEnv* env, jobject clazz,
                                                                        jstring iface) {
     ScopedUtfChars interface(env, iface);
@@ -170,13 +202,30 @@
         return false;
     }
 
+    // Backwards compatibility with pre-GKI kernels that use various custom
+    // ARPHRD_* for their cellular interface
+    switch (rv) {
+        // ARPHRD_PUREIP on at least some Mediatek Android kernels
+        // example: wembley with 4.19 kernel
+        case 520:
+        // in Linux 4.14+ rmnet support was upstreamed and ARHRD_RAWIP became 519,
+        // but it is 530 on at least some Qualcomm Android 4.9 kernels with rmnet
+        // example: Pixel 3 family
+        case 530:
+            // >5.4 kernels are GKI2.0 and thus upstream compatible, however 5.10
+            // shipped with Android S, so (for safety) let's limit ourselves to
+            // >5.10, ie. 5.11+ as a guarantee we're on Android T+ and thus no
+            // longer need this non-upstream compatibility logic
+            static bool is_pre_5_11_kernel = !isAtLeastKernelVersion(5, 11, 0);
+            if (is_pre_5_11_kernel) return false;
+    }
+
     switch (rv) {
         case ARPHRD_ETHER:
             return true;
         case ARPHRD_NONE:
         case ARPHRD_PPP:
-        case ARPHRD_RAWIP:  // in Linux 4.14+ rmnet support was upstreamed and this is 519
-        case 530:           // this is ARPHRD_RAWIP on some Android 4.9 kernels with rmnet
+        case ARPHRD_RAWIP:
             return false;
         default:
             jniThrowExceptionFmt(env, "java/io/IOException",
diff --git a/Tethering/tests/privileged/Android.bp b/Tethering/tests/privileged/Android.bp
index 214b014..c890197 100644
--- a/Tethering/tests/privileged/Android.bp
+++ b/Tethering/tests/privileged/Android.bp
@@ -34,6 +34,7 @@
     name: "TetheringPrivilegedTests",
     defaults: [
         "TetheringPrivilegedTestsJniDefaults",
+        "ConnectivityNextEnableDefaults",
     ],
     srcs: [
         "src/**/*.java",
diff --git a/Tethering/tests/unit/Android.bp b/Tethering/tests/unit/Android.bp
index 228f3fd..5150d39 100644
--- a/Tethering/tests/unit/Android.bp
+++ b/Tethering/tests/unit/Android.bp
@@ -49,7 +49,6 @@
         "src/**/*.kt",
     ],
     static_libs: [
-        "TetheringApiCurrentLib",
         "TetheringCommonTests",
         "androidx.test.rules",
         "frameworks-base-testutils",
@@ -85,6 +84,9 @@
 android_library {
     name: "TetheringTestsLatestSdkLib",
     defaults: ["TetheringTestsDefaults"],
+    static_libs: [
+        "TetheringApiStableLib",
+    ],
     target_sdk_version: "30",
     visibility: [
         "//packages/modules/Connectivity/tests:__subpackages__",
@@ -99,7 +101,13 @@
         "device-tests",
         "mts-tethering",
     ],
-    defaults: ["TetheringTestsDefaults"],
+    defaults: [
+        "TetheringTestsDefaults",
+        "ConnectivityNextEnableDefaults",
+    ],
+    static_libs: [
+        "TetheringApiCurrentLib",
+    ],
     compile_multilib: "both",
     jarjar_rules: ":TetheringTestsJarJarRules",
 }
diff --git a/service/src/com/android/server/ConnectivityServiceInitializer.java b/service/src/com/android/server/ConnectivityServiceInitializer.java
index 2465479..b1a56ae 100644
--- a/service/src/com/android/server/ConnectivityServiceInitializer.java
+++ b/service/src/com/android/server/ConnectivityServiceInitializer.java
@@ -31,7 +31,6 @@
         super(context);
         // Load JNI libraries used by ConnectivityService and its dependencies
         System.loadLibrary("service-connectivity");
-        // TODO: Define formal APIs to get the needed services.
         mConnectivity = new ConnectivityService(context);
     }
 
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java
index 311b3f0..3abc4fb 100755
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java
@@ -727,11 +727,15 @@
     @Test
     public void testDefault() throws Exception {
         if (!supportedHardware()) return;
-        // If adb TCP port opened, this test may running by adb over network.
-        // All of socket would be destroyed in this test. So this test don't
-        // support adb over network, see b/119382723.
-        if (SystemProperties.getInt("persist.adb.tcp.port", -1) > -1
-                || SystemProperties.getInt("service.adb.tcp.port", -1) > -1) {
+        if (!SdkLevel.isAtLeastS() && (
+                SystemProperties.getInt("persist.adb.tcp.port", -1) > -1
+                        || SystemProperties.getInt("service.adb.tcp.port", -1) > -1)) {
+            // If adb TCP port opened, this test may running by adb over network.
+            // All of socket would be destroyed in this test. So this test don't
+            // support adb over network, see b/119382723.
+            // This is fixed in S, but still affects previous Android versions,
+            // and this test must be backwards compatible.
+            // TODO: Delete this code entirely when R is no longer supported.
             Log.i(TAG, "adb is running over the network, so skip this test");
             return;
         }
@@ -842,11 +846,16 @@
         FileDescriptor remoteFd = openSocketFdInOtherApp(TEST_HOST, 80, TIMEOUT_MS);
 
         String disallowedApps = mRemoteSocketFactoryClient.getPackageName() + "," + mPackageName;
-        // If adb TCP port opened, this test may running by adb over TCP.
-        // Add com.android.shell appllication into blacklist to exclude adb socket for VPN test,
-        // see b/119382723.
-        // Note: The test don't support running adb over network for root device
-        disallowedApps = disallowedApps + ",com.android.shell";
+        if (!SdkLevel.isAtLeastS()) {
+            // If adb TCP port opened, this test may running by adb over TCP.
+            // Add com.android.shell application into disallowedApps to exclude adb socket for VPN
+            // test, see b/119382723 (the test doesn't support adb over TCP when adb runs as root).
+            //
+            // This is fixed in S, but still affects previous Android versions,
+            // and this test must be backwards compatible.
+            // TODO: Delete this code entirely when R is no longer supported.
+            disallowedApps = disallowedApps + ",com.android.shell";
+        }
         Log.i(TAG, "Append shell app to disallowedApps: " + disallowedApps);
         startVpn(new String[] {"192.0.2.2/32", "2001:db8:1:2::ffe/128"},
                  new String[] {"192.0.2.0/24", "2001:db8::/32"},
@@ -930,11 +939,17 @@
         if (!supportedHardware()) return;
         ProxyInfo initialProxy = mCM.getDefaultProxy();
 
-        // If adb TCP port opened, this test may running by adb over TCP.
-        // Add com.android.shell appllication into blacklist to exclude adb socket for VPN test,
-        // see b/119382723.
-        // Note: The test don't support running adb over network for root device
-        String disallowedApps = mPackageName + ",com.android.shell";
+        String disallowedApps = mPackageName;
+        if (!SdkLevel.isAtLeastS()) {
+            // If adb TCP port opened, this test may running by adb over TCP.
+            // Add com.android.shell application into disallowedApps to exclude adb socket for VPN
+            // test, see b/119382723 (the test doesn't support adb over TCP when adb runs as root).
+            //
+            // This is fixed in S, but still affects previous Android versions,
+            // and this test must be backwards compatible.
+            // TODO: Delete this code entirely when R is no longer supported.
+            disallowedApps += ",com.android.shell";
+        }
         ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("10.0.0.1", 8888);
         startVpn(new String[] {"192.0.2.2/32", "2001:db8:1:2::ffe/128"},
                 new String[] {"0.0.0.0/0", "::/0"}, "", disallowedApps,