Merge changes I5a01d709,I1b7da86d

* changes:
  Add Skeleton Ikev2VpnRunner class
  Add VpnRunner abstract class
This commit is contained in:
Benedict Wong
2020-02-06 00:55:05 +00:00
committed by Gerrit Code Review
3 changed files with 95 additions and 25 deletions

View File

@@ -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() {

View File

@@ -49,6 +49,7 @@ import android.content.pm.UserInfo;
import android.net.ConnectivityManager;
import android.net.INetworkManagementEventObserver;
import android.net.IpPrefix;
import android.net.IpSecManager;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.LocalSocket;
@@ -180,7 +181,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 +766,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 +776,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 +1510,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 +1528,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 +1914,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 +1969,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 +1980,53 @@ 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();
}
private class IkeV2VpnRunner extends VpnRunner {
private static final String TAG = "IkeV2VpnRunner";
private final IpSecManager mIpSecManager;
private final VpnProfile mProfile;
IkeV2VpnRunner(VpnProfile profile) {
super(TAG);
mProfile = profile;
// TODO: move this to startVpnRunnerPrivileged()
mConfig = new VpnConfig();
mIpSecManager = mContext.getSystemService(IpSecManager.class);
}
@Override
public void run() {
// TODO: Build IKE config, start IKE session
}
@Override
public void exit() {
// TODO: Teardown IKE session & any resources.
agentDisconnect();
}
}
/**
* 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 +2034,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 +2104,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();

View File

@@ -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();