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

Commit e0b672d1 authored by Benedict Wong's avatar Benedict Wong
Browse files

Add VpnRunner abstract class

This change adds a VpnRunner superclass to the LegacyVpnRunner in
preparation for the PlatformVpnRunner

Bug: 144246767
Test: FrameworksNetTests passing
Change-Id: I1b7da86d59c34f5d8c1ac13fb621f2e5d3bf8d26
parent 526e7dd0
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ public class VpnConfig implements Parcelable {

    public static final String DIALOGS_PACKAGE = "com.android.vpndialogs";

    // TODO: Rename this to something that encompasses Settings-based Platform VPNs as well.
    public static final String LEGACY_VPN = "[Legacy VPN]";

    public static Intent getIntentForConfirmation() {
+64 −23
Original line number Diff line number Diff line
@@ -180,7 +180,10 @@ public class Vpn {
    private boolean mIsPackageTargetingAtLeastQ;
    private String mInterface;
    private Connection mConnection;
    private LegacyVpnRunner mLegacyVpnRunner;

    /** Tracks the runners for all VPN types managed by the platform (eg. LegacyVpn, PlatformVpn) */
    private VpnRunner mVpnRunner;

    private PendingIntent mStatusIntent;
    private volatile boolean mEnableTeardown = true;
    private final INetworkManagementService mNetd;
@@ -762,7 +765,7 @@ public class Vpn {
                mNetworkCapabilities.setUids(null);
            }

            // Revoke the connection or stop LegacyVpnRunner.
            // Revoke the connection or stop the VpnRunner.
            if (mConnection != null) {
                try {
                    mConnection.mService.transact(IBinder.LAST_CALL_TRANSACTION,
@@ -772,9 +775,9 @@ public class Vpn {
                }
                mContext.unbindService(mConnection);
                mConnection = null;
            } else if (mLegacyVpnRunner != null) {
                mLegacyVpnRunner.exit();
                mLegacyVpnRunner = null;
            } else if (mVpnRunner != null) {
                mVpnRunner.exit();
                mVpnRunner = null;
            }

            try {
@@ -1506,8 +1509,8 @@ public class Vpn {
        @Override
        public void interfaceStatusChanged(String interfaze, boolean up) {
            synchronized (Vpn.this) {
                if (!up && mLegacyVpnRunner != null) {
                    mLegacyVpnRunner.check(interfaze);
                if (!up && mVpnRunner != null && mVpnRunner instanceof LegacyVpnRunner) {
                    ((LegacyVpnRunner) mVpnRunner).exitIfOuterInterfaceIs(interfaze);
                }
            }
        }
@@ -1524,9 +1527,10 @@ public class Vpn {
                        mContext.unbindService(mConnection);
                        mConnection = null;
                        agentDisconnect();
                    } else if (mLegacyVpnRunner != null) {
                        mLegacyVpnRunner.exit();
                        mLegacyVpnRunner = null;
                    } else if (mVpnRunner != null) {
                        // agentDisconnect must be called from mVpnRunner.exit()
                        mVpnRunner.exit();
                        mVpnRunner = null;
                    }
                }
            }
@@ -1909,23 +1913,40 @@ public class Vpn {

    private synchronized void startLegacyVpn(VpnConfig config, String[] racoon, String[] mtpd,
            VpnProfile profile) {
        stopLegacyVpnPrivileged();
        stopVpnRunnerPrivileged();

        // Prepare for the new request.
        prepareInternal(VpnConfig.LEGACY_VPN);
        updateState(DetailedState.CONNECTING, "startLegacyVpn");

        // Start a new LegacyVpnRunner and we are done!
        mLegacyVpnRunner = new LegacyVpnRunner(config, racoon, mtpd, profile);
        mLegacyVpnRunner.start();
        mVpnRunner = new LegacyVpnRunner(config, racoon, mtpd, profile);
        mVpnRunner.start();
    }

    /** Stop legacy VPN. Permissions must be checked by callers. */
    public synchronized void stopLegacyVpnPrivileged() {
        if (mLegacyVpnRunner != null) {
            mLegacyVpnRunner.exit();
            mLegacyVpnRunner = null;
    /**
     * Checks if this the currently running VPN (if any) was started by the Settings app
     *
     * <p>This includes both Legacy VPNs and Platform VPNs.
     */
    private boolean isSettingsVpnLocked() {
        return mVpnRunner != null && VpnConfig.LEGACY_VPN.equals(mPackage);
    }

    /** Stop VPN runner. Permissions must be checked by callers. */
    public synchronized void stopVpnRunnerPrivileged() {
        if (!isSettingsVpnLocked()) {
            return;
        }

        final boolean isLegacyVpn = mVpnRunner instanceof LegacyVpnRunner;

        mVpnRunner.exit();
        mVpnRunner = null;

        // LegacyVpn uses daemons that must be shut down before new ones are brought up.
        // The same limitation does not apply to Platform VPNs.
        if (isLegacyVpn) {
            synchronized (LegacyVpnRunner.TAG) {
                // wait for old thread to completely finish before spinning up
                // new instance, otherwise state updates can be out of order.
@@ -1947,7 +1968,7 @@ public class Vpn {
     * Callers are responsible for checking permissions if needed.
     */
    private synchronized LegacyVpnInfo getLegacyVpnInfoPrivileged() {
        if (mLegacyVpnRunner == null) return null;
        if (!isSettingsVpnLocked()) return null;

        final LegacyVpnInfo info = new LegacyVpnInfo();
        info.key = mConfig.user;
@@ -1958,14 +1979,26 @@ public class Vpn {
        return info;
    }

    public VpnConfig getLegacyVpnConfig() {
        if (mLegacyVpnRunner != null) {
    public synchronized VpnConfig getLegacyVpnConfig() {
        if (isSettingsVpnLocked()) {
            return mConfig;
        } else {
            return null;
        }
    }

    /** This class represents the common interface for all VPN runners. */
    private abstract class VpnRunner extends Thread {

        protected VpnRunner(String name) {
            super(name);
        }

        public abstract void run();

        protected abstract void exit();
    }

    /**
     * Bringing up a VPN connection takes time, and that is all this thread
     * does. Here we have plenty of time. The only thing we need to take
@@ -1973,7 +2006,7 @@ public class Vpn {
     * requests will pile up. This could be done in a Handler as a state
     * machine, but it is much easier to read in the current form.
     */
    private class LegacyVpnRunner extends Thread {
    private class LegacyVpnRunner extends VpnRunner {
        private static final String TAG = "LegacyVpnRunner";

        private final String[] mDaemons;
@@ -2043,13 +2076,21 @@ public class Vpn {
            mContext.registerReceiver(mBroadcastReceiver, filter);
        }

        public void check(String interfaze) {
        /**
         * Checks if the parameter matches the underlying interface
         *
         * <p>If the underlying interface is torn down, the LegacyVpnRunner also should be. It has
         * no ability to migrate between interfaces (or Networks).
         */
        public void exitIfOuterInterfaceIs(String interfaze) {
            if (interfaze.equals(mOuterInterface)) {
                Log.i(TAG, "Legacy VPN is going down with " + interfaze);
                exit();
            }
        }

        /** Tears down this LegacyVpn connection */
        @Override
        public void exit() {
            // We assume that everything is reset after stopping the daemons.
            interrupt();
+2 −2
Original line number Diff line number Diff line
@@ -138,7 +138,7 @@ public class LockdownVpnTracker {

        if (egressDisconnected || egressChanged) {
            mAcceptedEgressIface = null;
            mVpn.stopLegacyVpnPrivileged();
            mVpn.stopVpnRunnerPrivileged();
        }
        if (egressDisconnected) {
            hideNotification();
@@ -218,7 +218,7 @@ public class LockdownVpnTracker {
        mAcceptedEgressIface = null;
        mErrorCount = 0;

        mVpn.stopLegacyVpnPrivileged();
        mVpn.stopVpnRunnerPrivileged();
        mVpn.setLockdown(false);
        hideNotification();