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

Commit a6ce6f4c authored by Uldiniad's avatar Uldiniad Committed by Rashed Abdel-Tawab
Browse files

[BACKPORT]NetworkManagement : Add ability to restrict app vpn usage

Cherry-picked from https://review.lineageos.org/#/c/LineageOS/android_frameworks_base/+/232796/

VPN restriction independent from WiFi and mobile data.

Change-Id: I18728542e4a22733f4e096dc429386e61f2a3a06
parent 79f54038
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -52,6 +52,8 @@ public class NetworkPolicyManager {
    public static final int POLICY_REJECT_ON_WIFI = 0x8000;
    /** Reject application network traffic on cellular network **/
    public static final int POLICY_REJECT_ON_DATA = 0x10000;
    /** Reject application network traffic on virtual private network */
    public static final int POLICY_REJECT_ON_VPN = 0x02000;

    /*
     * Rules defining whether an uid has access to a network given its type (metered / non-metered).
+1 −0
Original line number Diff line number Diff line
@@ -470,4 +470,5 @@ interface INetworkManagementService
     */
    void restrictAppOnData(int uid, boolean restrict);
    void restrictAppOnWifi(int uid, boolean restrict);
    void restrictAppOnVpn(int uid, boolean restrict);
}
+75 −0
Original line number Diff line number Diff line
@@ -219,7 +219,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub
    private INetd mNetdService;

    private String mWifiInterfaceName, mDataInterfaceName;
    private String mVpnInterfaceName;
    private BroadcastReceiver mPendingDataRestrictReceiver;
    private BroadcastReceiver mPendingVpnRestrictReceiver;

    private IBatteryStats mBatteryStats;

@@ -276,6 +278,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub
    final SparseBooleanArray mWifiBlacklist = new SparseBooleanArray();
    @GuardedBy("mQuotaLock")
    final SparseBooleanArray mDataBlacklist = new SparseBooleanArray();
    @GuardedBy("mQuotaLock")
    final SparseBooleanArray mVpnBlacklist = new SparseBooleanArray();

    @GuardedBy("mQuotaLock")
    private boolean mDataSaverMode;
@@ -307,6 +311,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
            new RemoteCallbackList<INetworkActivityListener>();
    private boolean mNetworkActive;
    private SparseBooleanArray mPendingRestrictOnData = new SparseBooleanArray();
    private SparseBooleanArray mPendingRestrictOnVpn = new SparseBooleanArray();

    /**
     * Constructs a new NetworkManagementService instance
@@ -382,9 +387,19 @@ public class NetworkManagementService extends INetworkManagementService.Stub
                processPendingDataRestrictRequests();
           }
        };
        // Note: processPendingVpnRestrictRequests() will unregister
        // mPendingVpnRestrictReceiver once it has been able to determine
        // the vpn network interface name.
        mPendingVpnRestrictReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                processPendingVpnRestrictRequests();
           }
        };
        final IntentFilter filter = new IntentFilter();
        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        mContext.registerReceiver(mPendingDataRestrictReceiver, filter);
        mContext.registerReceiver(mPendingVpnRestrictReceiver, filter);
    }

    private IBatteryStats getBatteryStats() {
@@ -2006,6 +2021,37 @@ public class NetworkManagementService extends INetworkManagementService.Stub
        }
    }

    @Override
    public void restrictAppOnVpn(int uid, boolean restrict) {
        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
        // silently discard when control disabled
        if (!mBandwidthControlEnabled) return;

        initVpnInterface();
        if (TextUtils.isEmpty(mVpnInterfaceName)) {
            // We don't have an interface name since vpn is not active
            // yet, so queue up the request for when it comes up alive
            mPendingRestrictOnVpn.put(uid, restrict);
            return;
        }

        synchronized (mQuotaLock) {
            boolean oldValue = mVpnBlacklist.get(uid, false);
            if (oldValue == restrict) {
                return;
            }
            mVpnBlacklist.put(uid, restrict);
        }

        try {
            final String action = restrict ? "add" : "remove";
            mConnector.execute("bandwidth", action + "restrictappsonvpn",
                    mVpnInterfaceName, uid);
        } catch (NativeDaemonConnectorException e) {
            throw e.rethrowAsParcelableException();
        }
    }

    @Override
    public void restrictAppOnWifi(int uid, boolean restrict) {
        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
@@ -2065,6 +2111,23 @@ public class NetworkManagementService extends INetworkManagementService.Stub
        }
    }

    private void processPendingVpnRestrictRequests() {
        initVpnInterface();
        if (TextUtils.isEmpty(mVpnInterfaceName)) {
            return;
        }
        if (mPendingVpnRestrictReceiver != null) {
            mContext.unregisterReceiver(mPendingVpnRestrictReceiver);
            mPendingVpnRestrictReceiver = null;
        }
        int count = mPendingRestrictOnVpn.size();
        for (int i = 0; i < count; i++) {
            restrictAppOnVpn(mPendingRestrictOnVpn.keyAt(i),
                    mPendingRestrictOnVpn.valueAt(i));
        }
        mPendingRestrictOnVpn.clear();
    }

    @Override
    public void setAllowOnlyVpnForUids(boolean add, UidRange[] uidRanges)
            throws ServiceSpecificException {
@@ -3033,4 +3096,16 @@ public class NetworkManagementService extends INetworkManagementService.Stub
            mDataInterfaceName = linkProperties.getInterfaceName();
        }
    }

    private void initVpnInterface() {
        if (!TextUtils.isEmpty(mVpnInterfaceName)) {
            return;
        }
        ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(
                Context.CONNECTIVITY_SERVICE);
        LinkProperties linkProperties = cm.getLinkProperties(ConnectivityManager.TYPE_VPN);
        if (linkProperties != null) {
            mVpnInterfaceName = linkProperties.getInterfaceName();
        }
    }
}
+2 −0
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ import static android.net.NetworkPolicyManager.POLICY_NONE;
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
import static android.net.NetworkPolicyManager.POLICY_REJECT_ON_DATA;
import static android.net.NetworkPolicyManager.POLICY_REJECT_ON_WIFI;
import static android.net.NetworkPolicyManager.POLICY_REJECT_ON_VPN;
import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
import static android.net.NetworkPolicyManager.MASK_METERED_NETWORKS;
@@ -3006,6 +3007,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
        try {
            mNetworkManager.restrictAppOnWifi(uid, (uidPolicy & POLICY_REJECT_ON_WIFI) != 0);
            mNetworkManager.restrictAppOnData(uid, (uidPolicy & POLICY_REJECT_ON_DATA) != 0);
            mNetworkManager.restrictAppOnVpn(uid, (uidPolicy & POLICY_REJECT_ON_VPN) != 0);
        } catch (RemoteException e) {
            // ignored; service lives in system_server
        }