VpnSettings: show connected VPN even if deleted

So there's a way to disconnect from it, if someone deletes all the
keystore entries and the VPN doesn't actually exist any more (but
is still sitting around in memory somewhere keeping the connection
alive).

Bug: 29093779
Fix: 32880676
Test: runtest -x tests/app/src/com/android/settings/vpn2/VpnTests.java
Change-Id: I97671a74af746e5baaa5be0b5cff24e2b1766f53
This commit is contained in:
Robin Lee
2016-11-04 14:48:02 +00:00
parent 51ecc5eced
commit 393857be9c

View File

@@ -49,6 +49,7 @@ import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.net.LegacyVpnInfo; import com.android.internal.net.LegacyVpnInfo;
import com.android.internal.net.VpnConfig; import com.android.internal.net.VpnConfig;
@@ -96,8 +97,9 @@ public class VpnSettings extends RestrictedSettingsFragment implements
private Map<String, LegacyVpnPreference> mLegacyVpnPreferences = new ArrayMap<>(); private Map<String, LegacyVpnPreference> mLegacyVpnPreferences = new ArrayMap<>();
private Map<AppVpnInfo, AppPreference> mAppPreferences = new ArrayMap<>(); private Map<AppVpnInfo, AppPreference> mAppPreferences = new ArrayMap<>();
private HandlerThread mUpdaterThread; @GuardedBy("this")
private Handler mUpdater; private Handler mUpdater;
private HandlerThread mUpdaterThread;
private LegacyVpnInfo mConnectedLegacyVpn; private LegacyVpnInfo mConnectedLegacyVpn;
private boolean mUnavailable; private boolean mUnavailable;
@@ -181,11 +183,9 @@ public class VpnSettings extends RestrictedSettingsFragment implements
mConnectivityManager.registerNetworkCallback(VPN_REQUEST, mNetworkCallback); mConnectivityManager.registerNetworkCallback(VPN_REQUEST, mNetworkCallback);
// Trigger a refresh // Trigger a refresh
if (mUpdater == null) {
mUpdaterThread = new HandlerThread("Refresh VPN list in background"); mUpdaterThread = new HandlerThread("Refresh VPN list in background");
mUpdaterThread.start(); mUpdaterThread.start();
mUpdater = new Handler(mUpdaterThread.getLooper(), this); mUpdater = new Handler(mUpdaterThread.getLooper(), this);
}
mUpdater.sendEmptyMessage(RESCAN_MESSAGE); mUpdater.sendEmptyMessage(RESCAN_MESSAGE);
} }
@@ -199,7 +199,7 @@ public class VpnSettings extends RestrictedSettingsFragment implements
// Stop monitoring // Stop monitoring
mConnectivityManager.unregisterNetworkCallback(mNetworkCallback); mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
if (mUpdater != null) { synchronized (this) {
mUpdater.removeCallbacksAndMessages(null); mUpdater.removeCallbacksAndMessages(null);
mUpdater = null; mUpdater = null;
mUpdaterThread.quit(); mUpdaterThread.quit();
@@ -211,8 +211,6 @@ public class VpnSettings extends RestrictedSettingsFragment implements
@Override @WorkerThread @Override @WorkerThread
public boolean handleMessage(Message message) { public boolean handleMessage(Message message) {
mUpdater.removeMessages(RESCAN_MESSAGE);
// Run heavy RPCs before switching to UI thread // Run heavy RPCs before switching to UI thread
final List<VpnProfile> vpnProfiles = loadVpnProfiles(mKeyStore); final List<VpnProfile> vpnProfiles = loadVpnProfiles(mKeyStore);
final List<AppVpnInfo> vpnApps = getVpnApps(getActivity(), /* includeProfiles */ true); final List<AppVpnInfo> vpnApps = getVpnApps(getActivity(), /* includeProfiles */ true);
@@ -223,6 +221,13 @@ public class VpnSettings extends RestrictedSettingsFragment implements
final Set<AppVpnInfo> alwaysOnAppVpnInfos = getAlwaysOnAppVpnInfos(); final Set<AppVpnInfo> alwaysOnAppVpnInfos = getAlwaysOnAppVpnInfos();
final String lockdownVpnKey = VpnUtils.getLockdownVpn(); final String lockdownVpnKey = VpnUtils.getLockdownVpn();
synchronized (this) {
if (mUpdater != null) {
mUpdater.removeMessages(RESCAN_MESSAGE);
mUpdater.sendEmptyMessageDelayed(RESCAN_MESSAGE, RESCAN_INTERVAL_MS);
}
}
// Refresh list of VPNs // Refresh list of VPNs
getActivity().runOnUiThread(new Runnable() { getActivity().runOnUiThread(new Runnable() {
@Override @Override
@@ -235,8 +240,9 @@ public class VpnSettings extends RestrictedSettingsFragment implements
// Find new VPNs by subtracting existing ones from the full set // Find new VPNs by subtracting existing ones from the full set
final Set<Preference> updates = new ArraySet<>(); final Set<Preference> updates = new ArraySet<>();
// Add legacy VPNs
for (VpnProfile profile : vpnProfiles) { for (VpnProfile profile : vpnProfiles) {
LegacyVpnPreference p = findOrCreatePreference(profile); LegacyVpnPreference p = findOrCreatePreference(profile, true);
if (connectedLegacyVpns.containsKey(profile.key)) { if (connectedLegacyVpns.containsKey(profile.key)) {
p.setState(connectedLegacyVpns.get(profile.key).state); p.setState(connectedLegacyVpns.get(profile.key).state);
} else { } else {
@@ -245,6 +251,17 @@ public class VpnSettings extends RestrictedSettingsFragment implements
p.setAlwaysOn(lockdownVpnKey != null && lockdownVpnKey.equals(profile.key)); p.setAlwaysOn(lockdownVpnKey != null && lockdownVpnKey.equals(profile.key));
updates.add(p); updates.add(p);
} }
// Show connected VPNs even if the original entry in keystore is gone
for (LegacyVpnInfo vpn : connectedLegacyVpns.values()) {
final VpnProfile stubProfile = new VpnProfile(vpn.key);
LegacyVpnPreference p = findOrCreatePreference(stubProfile, false);
p.setState(vpn.state);
p.setAlwaysOn(lockdownVpnKey != null && lockdownVpnKey.equals(vpn.key));
updates.add(p);
}
// Add VpnService VPNs
for (AppVpnInfo app : vpnApps) { for (AppVpnInfo app : vpnApps) {
AppPreference p = findOrCreatePreference(app); AppPreference p = findOrCreatePreference(app);
if (connectedAppVpns.contains(app)) { if (connectedAppVpns.contains(app)) {
@@ -276,8 +293,6 @@ public class VpnSettings extends RestrictedSettingsFragment implements
} }
} }
}); });
mUpdater.sendEmptyMessageDelayed(RESCAN_MESSAGE, RESCAN_INTERVAL_MS);
return true; return true;
} }
@@ -361,16 +376,20 @@ public class VpnSettings extends RestrictedSettingsFragment implements
}; };
@UiThread @UiThread
private LegacyVpnPreference findOrCreatePreference(VpnProfile profile) { private LegacyVpnPreference findOrCreatePreference(VpnProfile profile, boolean update) {
LegacyVpnPreference pref = mLegacyVpnPreferences.get(profile.key); LegacyVpnPreference pref = mLegacyVpnPreferences.get(profile.key);
if (pref == null) { boolean created = false;
if (pref == null ) {
pref = new LegacyVpnPreference(getPrefContext()); pref = new LegacyVpnPreference(getPrefContext());
pref.setOnGearClickListener(mGearListener); pref.setOnGearClickListener(mGearListener);
pref.setOnPreferenceClickListener(this); pref.setOnPreferenceClickListener(this);
mLegacyVpnPreferences.put(profile.key, pref); mLegacyVpnPreferences.put(profile.key, pref);
created = true;
} }
// This may change as the profile can update and keep the same key. if (created || update) {
// This can change call-to-call because the profile can update and keep the same key.
pref.setProfile(profile); pref.setProfile(profile);
}
return pref; return pref;
} }