diff options
author | Robert Greenwalt <rgreenwalt@google.com> | 2013-04-22 11:13:02 -0700 |
---|---|---|
committer | Robert Greenwalt <rgreenwalt@google.com> | 2013-04-22 14:13:51 -0700 |
commit | 1b0ca9dace3fb3b84f8a87e539c0179e6093b423 (patch) | |
tree | e986ce3c3fdf4dc471079293f31f71384fddd9b8 /services | |
parent | 5d1a182a8a2dd9613ef3b1f2de7b6a3d690ae890 (diff) | |
download | frameworks_base-1b0ca9dace3fb3b84f8a87e539c0179e6093b423.zip frameworks_base-1b0ca9dace3fb3b84f8a87e539c0179e6093b423.tar.gz frameworks_base-1b0ca9dace3fb3b84f8a87e539c0179e6093b423.tar.bz2 |
Listen for network disconnect.
VPN used to just watch the interface, but that is insufficient. There
is no promise that the interface will go down when we're done with it.
Now that wifi stays on in scan-only mode despite user turning it off
it seems that the interface is left up, even in AP mode.
Now listening for ConnectivityService broadcast that the network we were on
has disconnected and tearing down the VPN then or when the interface
goes away.
bug:8550083
Change-Id: Icf414497bc55bead69de04e91f39f90ac2e6578a
Diffstat (limited to 'services')
-rw-r--r-- | services/java/com/android/server/ConnectivityService.java | 17 | ||||
-rw-r--r-- | services/java/com/android/server/connectivity/Vpn.java | 51 |
2 files changed, 65 insertions, 3 deletions
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index 01625dd..c2f4a2c 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -544,7 +544,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { mTethering.getTetherableBluetoothRegexs().length != 0) && mTethering.getUpstreamIfaceTypes().length != 0); - mVpn = new Vpn(mContext, mVpnCallback, mNetd); + mVpn = new Vpn(mContext, mVpnCallback, mNetd, this); mVpn.startMonitoring(mContext, mTrackerHandler); mClat = new Nat464Xlat(mContext, mNetd, this, mTrackerHandler); @@ -3448,4 +3448,19 @@ public class ConnectivityService extends IConnectivityManager.Stub { mNetTrackers[networkType].supplyMessenger(messenger); } } + + public int findConnectionTypeForIface(String iface) { + enforceConnectivityInternalPermission(); + + if (TextUtils.isEmpty(iface)) return ConnectivityManager.TYPE_NONE; + for (NetworkStateTracker tracker : mNetTrackers) { + if (tracker != null) { + LinkProperties lp = tracker.getLinkProperties(); + if (lp != null && iface.equals(lp.getInterfaceName())) { + return tracker.getNetworkInfo().getType(); + } + } + } + return ConnectivityManager.TYPE_NONE; + } } diff --git a/services/java/com/android/server/connectivity/Vpn.java b/services/java/com/android/server/connectivity/Vpn.java index 533db46..10c7e27 100644 --- a/services/java/com/android/server/connectivity/Vpn.java +++ b/services/java/com/android/server/connectivity/Vpn.java @@ -21,9 +21,11 @@ import static android.Manifest.permission.BIND_VPN_SERVICE; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; +import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; @@ -33,6 +35,7 @@ import android.graphics.Canvas; import android.graphics.drawable.Drawable; import android.net.BaseNetworkStateTracker; import android.net.ConnectivityManager; +import android.net.IConnectivityManager; import android.net.INetworkManagementEventObserver; import android.net.LinkProperties; import android.net.LocalSocket; @@ -71,6 +74,7 @@ import java.net.Inet4Address; import java.net.InetAddress; import java.nio.charset.Charsets; import java.util.Arrays; +import java.util.concurrent.atomic.AtomicInteger; import libcore.io.IoUtils; @@ -92,12 +96,15 @@ public class Vpn extends BaseNetworkStateTracker { private LegacyVpnRunner mLegacyVpnRunner; private PendingIntent mStatusIntent; private boolean mEnableNotif = true; + private final IConnectivityManager mConnService; - public Vpn(Context context, VpnCallback callback, INetworkManagementService netService) { + public Vpn(Context context, VpnCallback callback, INetworkManagementService netService, + IConnectivityManager connService) { // TODO: create dedicated TYPE_VPN network type super(ConnectivityManager.TYPE_DUMMY); mContext = context; mCallback = callback; + mConnService = connService; try { netService.registerObserver(mObserver); @@ -562,7 +569,6 @@ public class Vpn extends BaseNetworkStateTracker { if (!profile.searchDomains.isEmpty()) { config.searchDomains = Arrays.asList(profile.searchDomains.split(" +")); } - startLegacyVpn(config, racoon, mtpd); } @@ -630,9 +636,32 @@ public class Vpn extends BaseNetworkStateTracker { private final String[][] mArguments; private final LocalSocket[] mSockets; private final String mOuterInterface; + private final AtomicInteger mOuterConnection = + new AtomicInteger(ConnectivityManager.TYPE_NONE); private long mTimer = -1; + /** + * Watch for the outer connection (passing in the constructor) going away. + */ + private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) { + if (intent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, + ConnectivityManager.TYPE_NONE) == mOuterConnection.get()) { + NetworkInfo info = (NetworkInfo)intent.getExtra( + ConnectivityManager.EXTRA_NETWORK_INFO); + if (info != null && !info.isConnectedOrConnecting()) { + try { + mObserver.interfaceStatusChanged(mOuterInterface, false); + } catch (RemoteException e) {} + } + } + } + } + }; + public LegacyVpnRunner(VpnConfig config, String[] racoon, String[] mtpd) { super(TAG); mConfig = config; @@ -644,7 +673,22 @@ public class Vpn extends BaseNetworkStateTracker { // This is the interface which VPN is running on, // mConfig.interfaze will change to point to OUR // internal interface soon. TODO - add inner/outer to mconfig + // TODO - we have a race - if the outer iface goes away/disconnects before we hit this + // we will leave the VPN up. We should check that it's still there/connected after + // registering mOuterInterface = mConfig.interfaze; + + try { + mOuterConnection.set( + mConnService.findConnectionTypeForIface(mOuterInterface)); + } catch (Exception e) { + mOuterConnection.set(ConnectivityManager.TYPE_NONE); + } + + IntentFilter filter = new IntentFilter(); + filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); + mContext.registerReceiver(mBroadcastReceiver, filter); + } public void check(String interfaze) { @@ -661,6 +705,9 @@ public class Vpn extends BaseNetworkStateTracker { IoUtils.closeQuietly(socket); } updateState(DetailedState.DISCONNECTED, "exit"); + try { + mContext.unregisterReceiver(mBroadcastReceiver); + } catch (IllegalArgumentException e) {} } @Override |