diff options
author | Robin Lee <rgl@google.com> | 2015-05-12 18:35:37 +0100 |
---|---|---|
committer | Robin Lee <rgl@google.com> | 2015-05-18 22:55:15 +0100 |
commit | 01b35bcae307907bd8aaaa9cf23fa50f70e5f491 (patch) | |
tree | 5b0dd918f5aa299b7bcb1ec7bde7f3bc6063843f | |
parent | fd210786eab8c4aacbbb3aad5a206c57a732d2dc (diff) | |
download | packages_apps_Settings-01b35bcae307907bd8aaaa9cf23fa50f70e5f491.zip packages_apps_Settings-01b35bcae307907bd8aaaa9cf23fa50f70e5f491.tar.gz packages_apps_Settings-01b35bcae307907bd8aaaa9cf23fa50f70e5f491.tar.bz2 |
VPN: UI for forgetting disconnected VPNs
Made possible by expanded internal VPN APIs.
Bug: 20872408
Bug: 20692490
Bug: 20747154
Change-Id: Idc87084a130afa18b27c85cc9d4b5033dcedaabe
-rw-r--r-- | src/com/android/settings/vpn2/AppDialog.java | 21 | ||||
-rw-r--r-- | src/com/android/settings/vpn2/AppDialogFragment.java | 49 | ||||
-rw-r--r-- | src/com/android/settings/vpn2/ConfigDialogFragment.java | 10 | ||||
-rw-r--r-- | src/com/android/settings/vpn2/VpnSettings.java | 120 | ||||
-rw-r--r-- | tests/src/com/android/settings/vpn2/VpnTests.java | 3 |
5 files changed, 99 insertions, 104 deletions
diff --git a/src/com/android/settings/vpn2/AppDialog.java b/src/com/android/settings/vpn2/AppDialog.java index cd6a16c..c06de14 100644 --- a/src/com/android/settings/vpn2/AppDialog.java +++ b/src/com/android/settings/vpn2/AppDialog.java @@ -41,28 +41,25 @@ import com.android.settings.R; */ class AppDialog extends AlertDialog implements DialogInterface.OnClickListener { private final Listener mListener; - private final PackageInfo mPkgInfo; + private final PackageInfo mPackageInfo; private final String mLabel; - private final boolean mConnected; - AppDialog(Context context, Listener listener, PackageInfo pkgInfo, String label, - boolean connected) { + AppDialog(Context context, Listener listener, PackageInfo pkgInfo, String label) { super(context); mListener = listener; - mPkgInfo = pkgInfo; + mPackageInfo = pkgInfo; mLabel = label; - mConnected = connected; } public final PackageInfo getPackageInfo() { - return mPkgInfo; + return mPackageInfo; } @Override protected void onCreate(Bundle savedState) { setTitle(mLabel); - setMessage(getContext().getString(R.string.vpn_version, mPkgInfo.versionName)); + setMessage(getContext().getString(R.string.vpn_version, mPackageInfo.versionName)); createButtons(); super.onCreate(savedState); @@ -71,11 +68,9 @@ class AppDialog extends AlertDialog implements DialogInterface.OnClickListener { protected void createButtons() { Context context = getContext(); - if (mConnected) { - // Forget the network - setButton(DialogInterface.BUTTON_NEGATIVE, - context.getString(R.string.vpn_forget), this); - } + // Forget the network + setButton(DialogInterface.BUTTON_NEGATIVE, + context.getString(R.string.vpn_forget), this); // Dismiss setButton(DialogInterface.BUTTON_POSITIVE, diff --git a/src/com/android/settings/vpn2/AppDialogFragment.java b/src/com/android/settings/vpn2/AppDialogFragment.java index 6ac4fb5..906f896 100644 --- a/src/com/android/settings/vpn2/AppDialogFragment.java +++ b/src/com/android/settings/vpn2/AppDialogFragment.java @@ -27,6 +27,7 @@ import android.net.IConnectivityManager; import android.os.Bundle; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.UserHandle; import android.util.Log; import com.android.internal.net.VpnConfig; @@ -41,18 +42,20 @@ public class AppDialogFragment extends DialogFragment implements AppDialog.Liste private static final String ARG_MANAGING = "managing"; private static final String ARG_LABEL = "label"; - private static final String ARG_PACKAGE = "package"; private static final String ARG_CONNECTED = "connected"; + private static final String ARG_PACKAGE = "package"; + + private PackageInfo mPackageInfo; private final IConnectivityManager mService = IConnectivityManager.Stub.asInterface( ServiceManager.getService(Context.CONNECTIVITY_SERVICE)); - public static void show(VpnSettings parent, PackageInfo pkgInfo, String label, boolean managing, - boolean connected) { + public static void show(VpnSettings parent, PackageInfo packageInfo, String label, + boolean managing, boolean connected) { if (!parent.isAdded()) return; Bundle args = new Bundle(); - args.putParcelable(ARG_PACKAGE, pkgInfo); + args.putParcelable(ARG_PACKAGE, packageInfo); args.putString(ARG_LABEL, label); args.putBoolean(ARG_MANAGING, managing); args.putBoolean(ARG_CONNECTED, connected); @@ -66,13 +69,13 @@ public class AppDialogFragment extends DialogFragment implements AppDialog.Liste @Override public Dialog onCreateDialog(Bundle savedInstanceState) { Bundle args = getArguments(); - PackageInfo pkgInfo = (PackageInfo) args.getParcelable(ARG_PACKAGE); - String label = args.getString(ARG_LABEL); + final String label = args.getString(ARG_LABEL); boolean managing = args.getBoolean(ARG_MANAGING); boolean connected = args.getBoolean(ARG_CONNECTED); + mPackageInfo = (PackageInfo) args.getParcelable(ARG_PACKAGE); if (managing) { - return new AppDialog(getActivity(), this, pkgInfo, label, connected); + return new AppDialog(getActivity(), this, mPackageInfo, label); } else { // Build an AlertDialog with an option to disconnect. AlertDialog.Builder dlog = new AlertDialog.Builder(getActivity()) @@ -94,12 +97,6 @@ public class AppDialogFragment extends DialogFragment implements AppDialog.Liste } @Override - public void dismiss() { - ((VpnSettings) getTargetFragment()).update(); - super.dismiss(); - } - - @Override public void onCancel(DialogInterface dialog) { dismiss(); super.onCancel(dialog); @@ -107,25 +104,29 @@ public class AppDialogFragment extends DialogFragment implements AppDialog.Liste @Override public void onForget(final DialogInterface dialog) { - PackageInfo pkgInfo = (PackageInfo) getArguments().getParcelable(ARG_PACKAGE); - final String pkg = pkgInfo.packageName; + final int userId = UserHandle.getUserId(mPackageInfo.applicationInfo.uid); try { - VpnConfig vpnConfig = mService.getVpnConfig(); - if (vpnConfig != null && pkg.equals(vpnConfig.user) && !vpnConfig.legacy) { - mService.setVpnPackageAuthorization(false); - onDisconnect(dialog); - } + mService.setVpnPackageAuthorization(mPackageInfo.packageName, userId, false); + onDisconnect(dialog); } catch (RemoteException e) { - Log.e(TAG, "Failed to forget authorization for " + pkg, e); + Log.e(TAG, "Failed to forget authorization of " + mPackageInfo.packageName + + " for user " + userId, e); } } private void onDisconnect(final DialogInterface dialog) { - PackageInfo pkgInfo = (PackageInfo) getArguments().getParcelable(ARG_PACKAGE); + final int userId = UserHandle.getUserId(mPackageInfo.applicationInfo.uid); try { - mService.prepareVpn(pkgInfo.packageName, VpnConfig.LEGACY_VPN); + final VpnConfig vpnConfig = mService.getVpnConfig(userId); + if (vpnConfig == null || vpnConfig.legacy) { + return; + } + if (mPackageInfo.packageName.equals(vpnConfig.user)) { + mService.prepareVpn(mPackageInfo.packageName, VpnConfig.LEGACY_VPN, userId); + } } catch (RemoteException e) { - Log.e(TAG, "Failed to disconnect package " + pkgInfo.packageName, e); + Log.e(TAG, "Failed to disconnect package " + mPackageInfo.packageName + + " for user " + userId, e); } } } diff --git a/src/com/android/settings/vpn2/ConfigDialogFragment.java b/src/com/android/settings/vpn2/ConfigDialogFragment.java index 42e1614..26b7982 100644 --- a/src/com/android/settings/vpn2/ConfigDialogFragment.java +++ b/src/com/android/settings/vpn2/ConfigDialogFragment.java @@ -24,6 +24,7 @@ import android.net.IConnectivityManager; import android.os.Bundle; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.UserHandle; import android.security.Credentials; import android.security.KeyStore; import android.util.Log; @@ -128,12 +129,6 @@ public class ConfigDialogFragment extends DialogFragment implements } @Override - public void dismiss() { - ((VpnSettings) getTargetFragment()).update(); - super.dismiss(); - } - - @Override public void onCancel(DialogInterface dialog) { dismiss(); super.onCancel(dialog); @@ -151,7 +146,8 @@ public class ConfigDialogFragment extends DialogFragment implements try { LegacyVpnInfo connected = mService.getLegacyVpnInfo(); if (connected != null && profile.key.equals(connected.key)) { - mService.prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN); + mService.prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN, + UserHandle.myUserId()); } } catch (RemoteException e) { Log.e(TAG, "Failed to disconnect", e); diff --git a/src/com/android/settings/vpn2/VpnSettings.java b/src/com/android/settings/vpn2/VpnSettings.java index e60a262..a82585d 100644 --- a/src/com/android/settings/vpn2/VpnSettings.java +++ b/src/com/android/settings/vpn2/VpnSettings.java @@ -71,6 +71,9 @@ public class VpnSettings extends SettingsPreferenceFragment implements Handler.Callback, Preference.OnPreferenceClickListener { private static final String LOG_TAG = "VpnSettings"; + private static final int RESCAN_MESSAGE = 0; + private static final int RESCAN_INTERVAL_MS = 1000; + private static final String EXTRA_PICK_LOCKDOWN = "android.net.vpn.PICK_LOCKDOWN"; private static final NetworkRequest VPN_REQUEST = new NetworkRequest.Builder() .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) @@ -90,7 +93,6 @@ public class VpnSettings extends SettingsPreferenceFragment implements private Handler mUpdater; private LegacyVpnInfo mConnectedLegacyVpn; - private HashSet<String> mConnectedVpns = new HashSet<>(); private boolean mUnavailable; @@ -111,7 +113,6 @@ public class VpnSettings extends SettingsPreferenceFragment implements } mConnectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); - mConnectivityManager.registerNetworkCallback(VPN_REQUEST, mNetworkCallback); setHasOptionsMenu(true); addPreferencesFromResource(R.xml.vpn_settings2); @@ -179,10 +180,32 @@ public class VpnSettings extends SettingsPreferenceFragment implements LockdownConfigFragment.show(this); } - update(); + // Start monitoring + mConnectivityManager.registerNetworkCallback(VPN_REQUEST, mNetworkCallback); + + // Trigger a refresh + if (mUpdater == null) { + mUpdater = new Handler(this); + } + mUpdater.sendEmptyMessage(RESCAN_MESSAGE); + } + + @Override + public void onPause() { + // Pause monitoring + mConnectivityManager.unregisterNetworkCallback(mNetworkCallback); + + if (mUpdater != null) { + mUpdater.removeCallbacksAndMessages(null); + } + + super.onPause(); } - public void update() { + @Override + public boolean handleMessage(Message message) { + mUpdater.removeMessages(RESCAN_MESSAGE); + // Pref group within which to list VPNs PreferenceGroup vpnGroup = getPreferenceScreen(); vpnGroup.removeAll(); @@ -200,18 +223,43 @@ public class VpnSettings extends SettingsPreferenceFragment implements // 3rd-party VPN apps can change elsewhere. Reload them every time. for (AppOpsManager.PackageOps pkg : getVpnApps()) { + String key = getVpnIdentifier(UserHandle.getUserId(pkg.getUid()), pkg.getPackageName()); final AppPreference pref = new AppPreference(getActivity(), mManageListener, pkg.getPackageName(), pkg.getUid()); pref.setOnPreferenceClickListener(this); - mAppPreferences.put(pkg.getPackageName(), pref); + mAppPreferences.put(key, pref); vpnGroup.addPreference(pref); } - // Start monitoring. - if (mUpdater == null) { - mUpdater = new Handler(this); + // Mark out connections with a subtitle + try { + // Legacy VPNs + LegacyVpnInfo info = mConnectivityService.getLegacyVpnInfo(); + if (info != null) { + ConfigPreference preference = mConfigPreferences.get(info.key); + if (preference != null) { + preference.setState(info.state); + mConnectedLegacyVpn = info; + } + } + + // Third-party VPNs + for (UserHandle profile : mUserManager.getUserProfiles()) { + VpnConfig cfg = mConnectivityService.getVpnConfig(profile.getIdentifier()); + if (cfg != null) { + final String key = getVpnIdentifier(profile.getIdentifier(), cfg.user); + final AppPreference preference = mAppPreferences.get(key); + if (preference != null) { + preference.setState(AppPreference.STATE_CONNECTED); + } + } + } + } catch (RemoteException e) { + // ignore } - mUpdater.sendEmptyMessage(0); + + mUpdater.sendEmptyMessageDelayed(RESCAN_MESSAGE, RESCAN_INTERVAL_MS); + return true; } @Override @@ -275,68 +323,22 @@ public class VpnSettings extends SettingsPreferenceFragment implements } }; - @Override - public boolean handleMessage(Message message) { - mUpdater.removeMessages(0); - - if (isResumed()) { - try { - // Legacy VPNs - LegacyVpnInfo info = mConnectivityService.getLegacyVpnInfo(); - if (mConnectedLegacyVpn != null) { - ConfigPreference preference = mConfigPreferences.get(mConnectedLegacyVpn.key); - if (preference != null) { - preference.setState(-1); - } - mConnectedLegacyVpn = null; - } - if (info != null) { - ConfigPreference preference = mConfigPreferences.get(info.key); - if (preference != null) { - preference.setState(info.state); - mConnectedLegacyVpn = info; - } - } - - // VPN apps - for (String key : mConnectedVpns) { - AppPreference preference = mAppPreferences.get(key); - if (preference != null) { - preference.setState(AppPreference.STATE_DISCONNECTED); - } - } - mConnectedVpns.clear(); - // TODO: also query VPN services in user profiles STOPSHIP - VpnConfig cfg = mConnectivityService.getVpnConfig(); - if (cfg != null) { - mConnectedVpns.add(cfg.user); - } - for (String key : mConnectedVpns) { - AppPreference preference = mAppPreferences.get(key); - if (preference != null) { - preference.setState(AppPreference.STATE_CONNECTED); - } - } - } catch (RemoteException e) { - // ignore - } - mUpdater.sendEmptyMessageDelayed(0, 1000); - } - return true; + private static String getVpnIdentifier(int userId, String packageName) { + return Integer.toString(userId)+ "_" + packageName; } private NetworkCallback mNetworkCallback = new NetworkCallback() { @Override public void onAvailable(Network network) { if (mUpdater != null) { - mUpdater.sendEmptyMessage(0); + mUpdater.sendEmptyMessage(RESCAN_MESSAGE); } } @Override public void onLost(Network network) { if (mUpdater != null) { - mUpdater.sendEmptyMessage(0); + mUpdater.sendEmptyMessage(RESCAN_MESSAGE); } } }; diff --git a/tests/src/com/android/settings/vpn2/VpnTests.java b/tests/src/com/android/settings/vpn2/VpnTests.java index 8300534..26cfc9b 100644 --- a/tests/src/com/android/settings/vpn2/VpnTests.java +++ b/tests/src/com/android/settings/vpn2/VpnTests.java @@ -22,6 +22,7 @@ import android.os.Bundle; import android.os.Environment; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.UserHandle; import android.security.Credentials; import android.security.KeyStore; import android.security.NetworkSecurityPolicy; @@ -214,7 +215,7 @@ public class VpnTests extends InstrumentationTestCase { */ private void disconnect() throws Exception { try { - mService.prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN); + mService.prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN, UserHandle.myUserId()); } catch (RemoteException e) { Log.e(TAG, String.format("disconnect VPN exception: %s", e.toString())); } |