Connectivity: Add capability to allow tethering to use VPN upstreams [2/3]

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
This commit is contained in:
Oliver Scott 2021-11-08 15:37:55 -05:00 committed by fazilsheik96
parent 3fa88a221c
commit 5c13fcc575
2 changed files with 38 additions and 1 deletions

View File

@ -26,6 +26,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.CONNECTIVITY_SCOPE_LOCAL;
@ -450,6 +451,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
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 {
@ -2244,6 +2256,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);
}

View File

@ -38,6 +38,7 @@ import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.util.SharedLog;
import android.os.Handler;
import android.provider.Settings;
import android.util.Log;
import android.util.SparseIntArray;
@ -55,7 +56,6 @@ import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
/**
* A class to centralize all the network and link properties information
* pertaining to the current and any potential upstream network.
@ -136,6 +136,8 @@ public class UpstreamNetworkMonitor {
// 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 +194,7 @@ public class UpstreamNetworkMonitor {
mListenAllCallback = null;
mTetheringUpstreamNetwork = null;
mVpnInternetNetwork = null;
mNetworkMap.clear();
}
@ -323,6 +326,12 @@ public class UpstreamNetworkMonitor {
* 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;
@ -369,6 +378,7 @@ 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
@ -433,6 +443,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
@ -653,6 +667,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) {