Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 969918bf authored by Sam Mortimer's avatar Sam Mortimer
Browse files

fw/b: Add capability to allow tethering to use VPN upstreams

Squash of:

Author: Sam Mortimer <sam@mortimer.me.uk>
Date:   Thu Aug 15 19:40:55 2019 -0700

    fw/b: Add capability to allow tethering to use VPN upstreams

    * Toggled on/off at runtime via a new hotspot lineage setting.

    * Dynamically updates the tethering upstream for existing hotspot
      clients as VPNs are brought up / down or the hotspot setting
      is changed.

    * This implementation depends on fw/b config_tether_upstream_automatic
      being set to true.

    Change-Id: I2ac0b4acc0ea686dfdf54561cb3428808e337160

Change-Id: I2363e9baa007eac25be04ce23f0de41b80c5da42

----

Author: Sam Mortimer <sam@mortimer.me.uk>
Date:   Fri Sep 13 16:27:37 2019 -0700

    fw/b: Prevent trying to enable hw offload for tethering via VPN upstreams

    * Tethering via VPN upstream requires a sw path.

    * hw offload setup happened to be being disabled anyway owing to a fail
      return code from setDataLimit().  However, it was causing offload to be
      disabled entirely (until next hotspot off / on event).

    * Gracefully skip hw offload for vpn upstreams so that it is automatically
      used again when a vpn is disconnected.

    Change-Id: I4df13f02889305560903b7b1e919eedc7af78c07

[mkbestas]: Remove LineageSettings dependency & port to android 11

[uldiniad]: Replaced Settings.Secure private APIs and variables with alternatives

Change-Id: I77ed0142e653f4993486eea44e4dac21e3f67f17
parent fb08f60a
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ java_defaults {
        "android.hardware.tetheroffload.config-V1.0-java",
        "android.hardware.tetheroffload.control-V1.0-java",
        "net-utils-framework-common",
        "org.lineageos.platform.lineagesettings",
    ],
    libs: [
        "framework-statsd.stubs.module_lib",
+21 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
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.EXTRA_ACTIVE_LOCAL_ONLY;
@@ -74,6 +75,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.hardware.usb.UsbManager;
import android.net.ConnectivityManager;
import android.net.EthernetManager;
@@ -133,6 +135,8 @@ import com.android.internal.util.MessageUtils;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;

import lineageos.providers.LineageSettings;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.net.InetAddress;
@@ -393,6 +397,17 @@ public class Tethering {
        }

        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
                mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
            }
        };
        mContext.getContentResolver().registerContentObserver(LineageSettings.Secure.getUriFor(
                LineageSettings.Secure.TETHERING_ALLOW_VPN_UPSTREAMS), false, vpnSettingObserver);
    }

    private class TetheringThreadExecutor implements Executor {
@@ -1979,6 +1994,12 @@ public class Tethering {
            }

            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);
            }
+25 −0
Original line number Diff line number Diff line
@@ -45,6 +45,8 @@ import android.util.SparseIntArray;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.StateMachine;

import lineageos.providers.LineageSettings;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
@@ -122,6 +124,9 @@ public class UpstreamNetworkMonitor {
    // The current upstream network used for tethering.
    private Network mTetheringUpstreamNetwork;

    // 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;
        mTarget = tgt;
@@ -183,6 +188,8 @@ public class UpstreamNetworkMonitor {
    public void stop() {
        releaseMobileNetworkRequest();

        mVpnInternetNetwork = null;

        releaseCallback(mListenAllCallback);
        mListenAllCallback = null;

@@ -302,6 +309,13 @@ public class UpstreamNetworkMonitor {
     * 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;
@@ -343,6 +357,8 @@ public class UpstreamNetworkMonitor {
    }

    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
@@ -394,6 +410,10 @@ public class UpstreamNetworkMonitor {
        //     - 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
@@ -570,6 +590,11 @@ public class UpstreamNetworkMonitor {
               && !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) {