Merge tag 'android-13.0.0_r35' into staging/lineage-20.0_merge-android-13.0.0_r35

Android 13.0.0 release 35

# -----BEGIN PGP SIGNATURE-----
#
# iF0EABECAB0WIQRDQNE1cO+UXoOBCWTorT+BmrEOeAUCZA9jwAAKCRDorT+BmrEO
# eKFkAKCI1VSeMbiVzWNC1yNrGfWZfT0i1wCfVbdg/i5gOMb7om0fkFoiEyhV6mg=
# =GHVk
# -----END PGP SIGNATURE-----
# gpg: Signature made Mon Mar 13 19:56:16 2023 EET
# gpg:                using DSA key 4340D13570EF945E83810964E8AD3F819AB10E78
# gpg: Good signature from "The Android Open Source Project <initial-contribution@android.com>" [marginal]
# gpg: initial-contribution@android.com: Verified 1588 signatures in the past
#      16 months.  Encrypted 4 messages in the past 14 months.
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg:          It is not certain that the signature belongs to the owner.
# Primary key fingerprint: 4340 D135 70EF 945E 8381  0964 E8AD 3F81 9AB1 0E78

# By Bill Yi (10) and Brian Delwiche (1)
# Via Android Build Coastguard Worker (9) and others
* tag 'android-13.0.0_r35':
  Import translations. DO NOT MERGE ANYWHERE
  Import translations. DO NOT MERGE ANYWHERE
  Import translations. DO NOT MERGE ANYWHERE
  Import translations. DO NOT MERGE ANYWHERE
  Import translations. DO NOT MERGE ANYWHERE
  [RESTRICT AUTOMERGE] Restrict halfsheet cancel broadcast
  Import translations. DO NOT MERGE ANYWHERE
  Import translations. DO NOT MERGE ANYWHERE
  Import translations. DO NOT MERGE ANYWHERE
  Import translations. DO NOT MERGE ANYWHERE
  Import translations. DO NOT MERGE ANYWHERE

Change-Id: I71aa9b0142f916af4b771c0380d617e5e14168a3
diff --git a/Tethering/Android.bp b/Tethering/Android.bp
index 2c7b868..4cff456 100644
--- a/Tethering/Android.bp
+++ b/Tethering/Android.bp
@@ -48,6 +48,7 @@
         "net-utils-device-common-netlink",
         "netd-client",
         "tetheringstatsprotos",
+        "org.lineageos.platform.lineagesettings",
     ],
     libs: [
         "framework-connectivity",
diff --git a/Tethering/src/com/android/networkstack/tethering/Tethering.java b/Tethering/src/com/android/networkstack/tethering/Tethering.java
index 35a394d..81baa8e 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;
@@ -161,6 +162,8 @@
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
 
+import lineageos.providers.LineageSettings;
+
 /**
  *
  * This class holds much of the business logic to allow Android devices
@@ -450,6 +453,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(LineageSettings.Secure.getUriFor(
+                LineageSettings.Secure.TETHERING_ALLOW_VPN_UPSTREAMS), false, vpnSettingObserver);
     }
 
     private class TetheringThreadExecutor implements Executor {
@@ -2244,6 +2258,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/TetheringConfiguration.java b/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
index 7c36054..705a052 100644
--- a/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
+++ b/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
@@ -16,7 +16,6 @@
 
 package com.android.networkstack.tethering;
 
-import static android.content.Context.TELEPHONY_SERVICE;
 import static android.net.ConnectivityManager.TYPE_ETHERNET;
 import static android.net.ConnectivityManager.TYPE_MOBILE;
 import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
@@ -36,7 +35,6 @@
 import android.provider.Settings;
 import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -408,10 +406,7 @@
 
     /** Check whether dun is required. */
     public static boolean checkDunRequired(Context ctx) {
-        final TelephonyManager tm = (TelephonyManager) ctx.getSystemService(TELEPHONY_SERVICE);
-        // TelephonyManager would uses the active data subscription, which should be the one used
-        // by tethering.
-        return (tm != null) ? tm.isTetheringApnRequired() : false;
+        return false;
     }
 
     public int getOffloadPollInterval() {
diff --git a/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java b/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
index f8dd673..da9f8c9 100644
--- a/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
+++ b/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
@@ -55,6 +55,8 @@
 import java.util.Objects;
 import java.util.Set;
 
+import lineageos.providers.LineageSettings;
+
 
 /**
  * A class to centralize all the network and link properties information
@@ -136,6 +138,8 @@
     // The current upstream network used for tethering.
     private Network mTetheringUpstreamNetwork;
     private boolean mPreferTestNetworks;
+    // Set if the Internet is considered reachable via a VPN network
+    private Network mVpnInternetNetwork;
 
     public UpstreamNetworkMonitor(Context ctx, StateMachine tgt, SharedLog log, int what) {
         mContext = ctx;
@@ -192,6 +196,7 @@
         mListenAllCallback = null;
 
         mTetheringUpstreamNetwork = null;
+        mVpnInternetNetwork = null;
         mNetworkMap.clear();
     }
 
@@ -323,6 +328,12 @@
      * Returns null if no current upstream is available.
      */
     public UpstreamNetworkState getCurrentPreferredUpstream() {
+        // Use VPN upstreams if hotspot settings allow.
+        if (mVpnInternetNetwork != null &&
+                LineageSettings.Secure.getInt(mContext.getContentResolver(),
+                        LineageSettings.Secure.TETHERING_ALLOW_VPN_UPSTREAMS, 0) == 1) {
+            return mNetworkMap.get(mVpnInternetNetwork);
+        }
         final UpstreamNetworkState dfltState = (mDefaultInternetNetwork != null)
                 ? mNetworkMap.get(mDefaultInternetNetwork)
                 : null;
@@ -369,6 +380,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
@@ -433,6 +445,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
@@ -653,6 +669,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/bpf_progs/bpf_shared.h b/bpf_progs/bpf_shared.h
index fd449a3..dbf0a9f 100644
--- a/bpf_progs/bpf_shared.h
+++ b/bpf_progs/bpf_shared.h
@@ -95,13 +95,13 @@
 
 // 'static' - otherwise these constants end up in .rodata in the resulting .o post compilation
 static const int COOKIE_UID_MAP_SIZE = 10000;
-static const int UID_COUNTERSET_MAP_SIZE = 2000;
+static const int UID_COUNTERSET_MAP_SIZE = 4000;
 static const int APP_STATS_MAP_SIZE = 10000;
 static const int STATS_MAP_SIZE = 5000;
 static const int IFACE_INDEX_NAME_MAP_SIZE = 1000;
 static const int IFACE_STATS_MAP_SIZE = 1000;
 static const int CONFIGURATION_MAP_SIZE = 2;
-static const int UID_OWNER_MAP_SIZE = 2000;
+static const int UID_OWNER_MAP_SIZE = 4000;
 
 #ifdef __cplusplus
 
diff --git a/framework/src/android/net/ConnectivitySettingsManager.java b/framework/src/android/net/ConnectivitySettingsManager.java
index 822e67d..32f8319 100644
--- a/framework/src/android/net/ConnectivitySettingsManager.java
+++ b/framework/src/android/net/ConnectivitySettingsManager.java
@@ -1050,7 +1050,7 @@
     }
 
     private static boolean isCallingFromSystem() {
-        final int uid = Binder.getCallingUid();
+        final int uid = UserHandle.getAppId(Binder.getCallingUid());
         final int pid = Binder.getCallingPid();
         if (uid == Process.SYSTEM_UID && pid == Process.myPid()) {
             return true;
diff --git a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
index ba836b2..cfe8171 100644
--- a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
+++ b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
@@ -87,7 +87,8 @@
 
 // Picks a random interface ID that is checksum neutral with the IPv4 address and the NAT64 prefix.
 jstring com_android_server_connectivity_ClatCoordinator_generateIpv6Address(
-        JNIEnv* env, jobject clazz, jstring ifaceStr, jstring v4Str, jstring prefix64Str) {
+        JNIEnv* env, jobject clazz, jstring ifaceStr, jstring v4Str, jstring prefix64Str,
+        jint mark) {
     ScopedUtfChars iface(env, ifaceStr);
     ScopedUtfChars addr4(env, v4Str);
     ScopedUtfChars prefix64(env, prefix64Str);
@@ -111,7 +112,7 @@
     }
 
     in6_addr v6;
-    if (net::clat::generateIpv6Address(iface.c_str(), v4, nat64Prefix, &v6)) {
+    if (net::clat::generateIpv6Address(iface.c_str(), v4, nat64Prefix, &v6, mark)) {
         jniThrowExceptionFmt(env, "java/io/IOException",
                              "Unable to find global source address on %s for %s", iface.c_str(),
                              prefix64.c_str());
@@ -498,7 +499,7 @@
         {"native_selectIpv4Address", "(Ljava/lang/String;I)Ljava/lang/String;",
          (void*)com_android_server_connectivity_ClatCoordinator_selectIpv4Address},
         {"native_generateIpv6Address",
-         "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
+         "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)Ljava/lang/String;",
          (void*)com_android_server_connectivity_ClatCoordinator_generateIpv6Address},
         {"native_createTunInterface", "(Ljava/lang/String;)I",
          (void*)com_android_server_connectivity_ClatCoordinator_createTunInterface},
diff --git a/service/native/libs/libclat/clatutils.cpp b/service/native/libs/libclat/clatutils.cpp
index 4a125ba..be86612 100644
--- a/service/native/libs/libclat/clatutils.cpp
+++ b/service/native/libs/libclat/clatutils.cpp
@@ -126,10 +126,19 @@
 
 // Picks a random interface ID that is checksum neutral with the IPv4 address and the NAT64 prefix.
 int generateIpv6Address(const char* iface, const in_addr v4, const in6_addr& nat64Prefix,
-                        in6_addr* v6) {
+                        in6_addr* v6, uint32_t mark) {
     int s = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
     if (s == -1) return -errno;
 
+    // Socket's mark affects routing decisions (network selection)
+    // An fwmark is necessary for clat to bypass the VPN during initialization.
+    if ((mark != MARK_UNSET) && setsockopt(s, SOL_SOCKET, SO_MARK, &mark, sizeof(mark))) {
+        int ret = errno;
+        ALOGE("setsockopt(SOL_SOCKET, SO_MARK) failed: %s", strerror(errno));
+        close(s);
+        return -ret;
+    }
+
     if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, iface, strlen(iface) + 1) == -1) {
         close(s);
         return -errno;
diff --git a/service/native/libs/libclat/include/libclat/clatutils.h b/service/native/libs/libclat/include/libclat/clatutils.h
index 812c86e..991b193 100644
--- a/service/native/libs/libclat/include/libclat/clatutils.h
+++ b/service/native/libs/libclat/include/libclat/clatutils.h
@@ -24,7 +24,7 @@
 in_addr_t selectIpv4Address(const in_addr ip, int16_t prefixlen);
 void makeChecksumNeutral(in6_addr* v6, const in_addr v4, const in6_addr& nat64Prefix);
 int generateIpv6Address(const char* iface, const in_addr v4, const in6_addr& nat64Prefix,
-                        in6_addr* v6);
+                        in6_addr* v6, uint32_t mark);
 int detect_mtu(const struct in6_addr* plat_subnet, uint32_t plat_suffix, uint32_t mark);
 int configure_packet_socket(int sock, in6_addr* addr, int ifindex);
 
diff --git a/service/src/com/android/server/connectivity/ClatCoordinator.java b/service/src/com/android/server/connectivity/ClatCoordinator.java
index 3272075..08c1fce 100644
--- a/service/src/com/android/server/connectivity/ClatCoordinator.java
+++ b/service/src/com/android/server/connectivity/ClatCoordinator.java
@@ -173,8 +173,8 @@
          */
         @NonNull
         public String generateIpv6Address(@NonNull String iface, @NonNull String v4,
-                @NonNull String prefix64) throws IOException {
-            return native_generateIpv6Address(iface, v4, prefix64);
+                @NonNull String prefix64, int mark) throws IOException {
+            return native_generateIpv6Address(iface, v4, prefix64, mark);
         }
 
         /**
@@ -529,10 +529,11 @@
         }
 
         // [2] Generate a checksum-neutral IID.
+        final Integer fwmark = getFwmark(netId);
         final String pfx96Str = nat64Prefix.getAddress().getHostAddress();
         final String v6Str;
         try {
-            v6Str = mDeps.generateIpv6Address(iface, v4Str, pfx96Str);
+            v6Str = mDeps.generateIpv6Address(iface, v4Str, pfx96Str, fwmark);
         } catch (IOException e) {
             throw new IOException("no IPv6 addresses were available for clat: " + e);
         }
@@ -570,7 +571,6 @@
         }
 
         // Detect ipv4 mtu.
-        final Integer fwmark = getFwmark(netId);
         final int detectedMtu = mDeps.detectMtu(pfx96Str,
                 ByteBuffer.wrap(GOOGLE_DNS_4.getAddress()).getInt(), fwmark);
         final int mtu = adjustMtu(detectedMtu);
@@ -819,7 +819,7 @@
     private static native String native_selectIpv4Address(String v4addr, int prefixlen)
             throws IOException;
     private static native String native_generateIpv6Address(String iface, String v4,
-            String prefix64) throws IOException;
+            String prefix64, int mark) throws IOException;
     private static native int native_createTunInterface(String tuniface) throws IOException;
     private static native int native_detectMtu(String platSubnet, int platSuffix, int mark)
             throws IOException;
diff --git a/service/src/com/android/server/connectivity/PermissionMonitor.java b/service/src/com/android/server/connectivity/PermissionMonitor.java
index e4a2c20..0e265f9 100755
--- a/service/src/com/android/server/connectivity/PermissionMonitor.java
+++ b/service/src/com/android/server/connectivity/PermissionMonitor.java
@@ -495,7 +495,6 @@
         // TODO : remove carryover package check in the future(b/31479477). All apps should just
         //  request the appropriate permission for their use case since android Q.
         return isCarryoverPackage(app.applicationInfo)
-                || isUidAllowedOnRestrictedNetworks(app.applicationInfo)
                 || hasPermission(app, PERMISSION_MAINLINE_NETWORK_STACK)
                 || hasPermission(app, NETWORK_STACK)
                 || hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS);
diff --git a/tests/unit/java/com/android/server/connectivity/ClatCoordinatorTest.java b/tests/unit/java/com/android/server/connectivity/ClatCoordinatorTest.java
index 7c18ecb..5f0703f 100644
--- a/tests/unit/java/com/android/server/connectivity/ClatCoordinatorTest.java
+++ b/tests/unit/java/com/android/server/connectivity/ClatCoordinatorTest.java
@@ -202,12 +202,12 @@
          */
         @Override
         public String generateIpv6Address(@NonNull String iface, @NonNull String v4,
-                @NonNull String prefix64) throws IOException {
+                @NonNull String prefix64, int mark) throws IOException {
             if (BASE_IFACE.equals(iface) && XLAT_LOCAL_IPV4ADDR_STRING.equals(v4)
                     && NAT64_PREFIX_STRING.equals(prefix64)) {
                 return XLAT_LOCAL_IPV6ADDR_STRING;
             }
-            fail("unsupported args: " + iface + ", " + v4 + ", " + prefix64);
+            fail("unsupported args: " + iface + ", " + v4 + ", " + prefix64 + ", " + mark);
             return null;
         }
 
@@ -408,7 +408,7 @@
 
         // Generate a checksum-neutral IID.
         inOrder.verify(mDeps).generateIpv6Address(eq(BASE_IFACE),
-                eq(XLAT_LOCAL_IPV4ADDR_STRING), eq(NAT64_PREFIX_STRING));
+                eq(XLAT_LOCAL_IPV4ADDR_STRING), eq(NAT64_PREFIX_STRING), eq(MARK));
 
         // Open, configure and bring up the tun interface.
         inOrder.verify(mDeps).createTunInterface(eq(STACKED_IFACE));