Merge tag 'android-14.0.0_r50' into leaf-3.2

Android 14.0.0 Release 50 (AP2A.240605.024)

* tag 'android-14.0.0_r50': (327 commits)
  Import translations. DO NOT MERGE ANYWHERE
  Add testAllowedUids for devices without FEATURE_TELEPHONY_SUBSCRIPTION
  Fix flakes due to networks obtained via sync APIs
  Import translations. DO NOT MERGE ANYWHERE
  Revert "24Q2: use mainline netbpfload from apex"
  24Q2: use mainline netbpfload from apex
  Fix the ignore_on_* flags for egress tracing.
  Remove unused library visibility
  Connect to IBluetoothFinder and use it
  Update the imports to androidx.test.filters.*
  Move VpnManagerServiceTest and VpnTest to frameworks
  Use a TAP test network for MeshCoP service test cases
  Fix flaky multicast tests in Thread E2E test.
  NetBpfLoader: create /sys/fs/bpf/loader dir
  Revert "Use a TAP test network for MeshCoP service test cases"
  Use a TAP test network for MeshCoP service test cases
  [mdns] add service-side impl for NSD service TTL support
  Adding additional transport satellite support at getSubIdForMobile()
  netbpfload: fail if platform exec of apex fails
  [Thread] make Thread state customisable via resource overlay
  ...

Change-Id: Ie343e88e5ec7307265c6166e8a41c7be455c08a7
diff --git a/Tethering/src/com/android/networkstack/tethering/Tethering.java b/Tethering/src/com/android/networkstack/tethering/Tethering.java
index 873961a..6085a00 100644
--- a/Tethering/src/com/android/networkstack/tethering/Tethering.java
+++ b/Tethering/src/com/android/networkstack/tethering/Tethering.java
@@ -26,6 +26,7 @@
 import static android.net.ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED;
 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
 import static android.net.ConnectivityManager.EXTRA_NETWORK_INFO;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
 import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
 import static android.net.TetheringManager.ACTION_TETHER_STATE_CHANGED;
 import static android.net.TetheringManager.CONNECTIVITY_SCOPE_LOCAL;
@@ -501,6 +502,17 @@
         }
 
         startTrackDefaultNetwork();
+
+        // Listen for allowing tethering upstream via VPN settings changes
+        final ContentObserver vpnSettingObserver = new ContentObserver(mHandler) {
+            @Override
+            public void onChange(boolean self) {
+                // Reconsider tethering upstream
+                mTetherMainSM.sendMessage(TetherMainSM.CMD_UPSTREAM_CHANGED);
+            }
+        };
+        mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
+                Settings.Secure.TETHERING_ALLOW_VPN_UPSTREAMS), false, vpnSettingObserver);
     }
 
     private class TetheringThreadExecutor implements Executor {
@@ -2305,6 +2317,12 @@
             }
 
             public void updateUpstreamNetworkState(UpstreamNetworkState ns) {
+                // Disable hw offload on vpn upstream interfaces.
+                // setUpstreamLinkProperties() interprets null as disable.
+                if (ns != null && ns.networkCapabilities != null
+                        && !ns.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_VPN)) {
+                    ns = null;
+                }
                 mOffloadController.setUpstreamLinkProperties(
                         (ns != null) ? ns.linkProperties : null);
             }
diff --git a/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java b/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
index 7a05d74..68e1352 100644
--- a/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
+++ b/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
@@ -37,6 +37,7 @@
 import android.net.NetworkCapabilities;
 import android.net.NetworkRequest;
 import android.os.Handler;
+import android.provider.Settings;
 import android.util.Log;
 import android.util.SparseIntArray;
 
@@ -132,6 +133,8 @@
     // The current system default network (not really used yet).
     private Network mDefaultInternetNetwork;
     private boolean mPreferTestNetworks;
+    // Set if the Internet is considered reachable via a VPN network
+    private Network mVpnInternetNetwork;
 
     public UpstreamNetworkMonitor(Context ctx, Handler h, SharedLog log, EventListener listener) {
         mContext = ctx;
@@ -186,6 +189,7 @@
         releaseCallback(mListenAllCallback);
         mListenAllCallback = null;
 
+        mVpnInternetNetwork = null;
         mNetworkMap.clear();
     }
 
@@ -317,6 +321,12 @@
      * Returns null if no current upstream is available.
      */
     public UpstreamNetworkState getCurrentPreferredUpstream() {
+        // Use VPN upstreams if hotspot settings allow.
+        if (mVpnInternetNetwork != null &&
+                Settings.Secure.getInt(mContext.getContentResolver(),
+                        Settings.Secure.TETHERING_ALLOW_VPN_UPSTREAMS, 0) == 1) {
+            return mNetworkMap.get(mVpnInternetNetwork);
+        }
         final UpstreamNetworkState dfltState = (mDefaultInternetNetwork != null)
                 ? mNetworkMap.get(mDefaultInternetNetwork)
                 : null;
@@ -358,6 +368,7 @@
     }
 
     private void handleNetCap(Network network, NetworkCapabilities newNc) {
+        if (isVpnInternetNetwork(newNc)) mVpnInternetNetwork = network;
         final UpstreamNetworkState prev = mNetworkMap.get(network);
         if (prev == null || newNc.equals(prev.networkCapabilities)) {
             // Ignore notifications about networks for which we have not yet
@@ -423,6 +434,10 @@
         //     - deletes the entry from the map only when the LISTEN_ALL
         //       callback gets notified.
 
+        if (network.equals(mVpnInternetNetwork)) {
+            mVpnInternetNetwork = null;
+        }
+
         if (!mNetworkMap.containsKey(network)) {
             // Ignore loss of networks about which we had not previously
             // learned any information or for which we have already processed
@@ -636,6 +651,11 @@
                && !isCellular(ns.networkCapabilities);
     }
 
+    private static boolean isVpnInternetNetwork(NetworkCapabilities nc) {
+        return (nc != null) && !nc.hasCapability(NET_CAPABILITY_NOT_VPN) &&
+                nc.hasCapability(NET_CAPABILITY_INTERNET);
+    }
+
     private static UpstreamNetworkState findFirstDunNetwork(
             Iterable<UpstreamNetworkState> netStates) {
         for (UpstreamNetworkState ns : netStates) {
diff --git a/netbpfload/NetBpfLoad.cpp b/netbpfload/NetBpfLoad.cpp
index ed7d048..8f25593 100644
--- a/netbpfload/NetBpfLoad.cpp
+++ b/netbpfload/NetBpfLoad.cpp
@@ -289,16 +289,15 @@
     }
 
     if (isAtLeastT && !android::bpf::isAtLeastKernelVersion(4, 9, 0)) {
-        ALOGE("Android T requires kernel 4.9.");
-        return 1;
+        ALOGW("Android T requires kernel 4.9.");
     }
 
     if (isAtLeastU && !android::bpf::isAtLeastKernelVersion(4, 14, 0)) {
-        ALOGE("Android U requires kernel 4.14.");
-        return 1;
+        ALOGW("Android U requires kernel 4.14.");
     }
 
-    if (isAtLeastV && !android::bpf::isAtLeastKernelVersion(4, 19, 0)) {
+    if (isAtLeastV && !android::bpf::isAtLeastKernelVersion(4, 19, 0) &&
+        android::bpf::isAtLeastKernelVersion(4, 14, 0)) {
         ALOGE("Android V requires kernel 4.19.");
         return 1;
     }
@@ -353,12 +352,14 @@
         //  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;
+        if (writeProcSysFile("/proc/sys/net/core/bpf_jit_enable", "1\n") &&
+            android::bpf::isAtLeastKernelVersion(4, 14, 0)) 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;
+        if (writeProcSysFile("/proc/sys/net/core/bpf_jit_kallsyms", "1\n") &&
+            android::bpf::isAtLeastKernelVersion(4, 14, 0)) return 1;
     }
 
     // Create all the pin subdirectories
diff --git a/netbpfload/loader.cpp b/netbpfload/loader.cpp
index c534b2c..d9d3b50 100644
--- a/netbpfload/loader.cpp
+++ b/netbpfload/loader.cpp
@@ -574,6 +574,14 @@
 
 static bool mapMatchesExpectations(const unique_fd& fd, const string& mapName,
                                    const struct bpf_map_def& mapDef, const enum bpf_map_type type) {
+    // bpfGetFd... family of functions require at minimum a 4.14 kernel,
+    // so on 4.9-T kernels just pretend the map matches our expectations.
+    // Additionally we'll get almost equivalent test coverage on newer devices/kernels.
+    // This is because the primary failure mode we're trying to detect here
+    // is either a source code misconfiguration (which is likely kernel independent)
+    // or a newly introduced kernel feature/bug (which is unlikely to get backported to 4.9).
+    if (!isAtLeastKernelVersion(4, 14, 0)) return true;
+
     // Assuming fd is a valid Bpf Map file descriptor then
     // all the following should always succeed on a 4.14+ kernel.
     // If they somehow do fail, they'll return -1 (and set errno),
@@ -711,6 +719,16 @@
         }
 
         enum bpf_map_type type = md[i].type;
+        if (type == BPF_MAP_TYPE_DEVMAP && !isAtLeastKernelVersion(4, 14, 0)) {
+            // On Linux Kernels older than 4.14 this map type doesn't exist, but it can kind
+            // of be approximated: ARRAY has the same userspace api, though it is not usable
+            // by the same ebpf programs.  However, that's okay because the bpf_redirect_map()
+            // helper doesn't exist on 4.9-T anyway (so the bpf program would fail to load,
+            // and thus needs to be tagged as 4.14+ either way), so there's nothing useful you
+            // could do with a DEVMAP anyway (that isn't already provided by an ARRAY)...
+            // Hence using an ARRAY instead of a DEVMAP simply makes life easier for userspace.
+            type = BPF_MAP_TYPE_ARRAY;
+        }
         if (type == BPF_MAP_TYPE_DEVMAP_HASH && !isAtLeastKernelVersion(5, 4, 0)) {
             // On Linux Kernels older than 5.4 this map type doesn't exist, but it can kind
             // of be approximated: HASH has the same userspace visible api.
@@ -766,7 +784,8 @@
               .max_entries = max_entries,
               .map_flags = md[i].map_flags,
             };
-            strlcpy(req.map_name, mapNames[i].c_str(), sizeof(req.map_name));
+            if (isAtLeastKernelVersion(4, 14, 0))
+                strlcpy(req.map_name, mapNames[i].c_str(), sizeof(req.map_name));
             fd.reset(bpf(BPF_MAP_CREATE, req));
             saved_errno = errno;
             ALOGD("bpf_create_map name %s, ret: %d", mapNames[i].c_str(), fd.get());
@@ -1008,7 +1027,8 @@
               .log_size = static_cast<__u32>(log_buf.size()),
               .expected_attach_type = cs[i].expected_attach_type,
             };
-            strlcpy(req.prog_name, cs[i].name.c_str(), sizeof(req.prog_name));
+            if (isAtLeastKernelVersion(4, 14, 0))
+                strlcpy(req.prog_name, cs[i].name.c_str(), sizeof(req.prog_name));
             fd.reset(bpf(BPF_PROG_LOAD, req));
 
             ALOGD("BPF_PROG_LOAD call for %s (%s) returned fd: %d (%s)", elfPath,
diff --git a/netd/BpfHandler.cpp b/netd/BpfHandler.cpp
index a00c363..2252e07 100644
--- a/netd/BpfHandler.cpp
+++ b/netd/BpfHandler.cpp
@@ -75,16 +75,6 @@
     // This code was mainlined in T, so this should be trivially satisfied.
     if (!modules::sdklevel::IsAtLeastT()) return Status("S- platform is unsupported");
 
-    // S requires eBPF support which was only added in 4.9, so this should be satisfied.
-    if (!bpf::isAtLeastKernelVersion(4, 9, 0)) {
-        return Status("kernel version < 4.9.0 is unsupported");
-    }
-
-    // U bumps the kernel requirement up to 4.14
-    if (modules::sdklevel::IsAtLeastU() && !bpf::isAtLeastKernelVersion(4, 14, 0)) {
-        return Status("U+ platform with kernel version < 4.14.0 is unsupported");
-    }
-
     if (modules::sdklevel::IsAtLeastV()) {
         // V bumps the kernel requirement up to 4.19
         // see also: //system/netd/tests/kernel_test.cpp TestKernel419