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

Commit c0d07e31 authored by Robin Lee's avatar Robin Lee Committed by Android Git Automerger
Browse files

am b5c48a4c: Merge "VPN: UI for forgetting disconnected VPNs" into mnc-dev

* commit 'b5c48a4c':
  VPN: UI for forgetting disconnected VPNs
parents a351cda3 b5c48a4c
Loading
Loading
Loading
Loading
+8 −13
Original line number Diff line number Diff line
@@ -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);
        }

        // Dismiss
        setButton(DialogInterface.BUTTON_POSITIVE,
+25 −24
Original line number Diff line number Diff line
@@ -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())
@@ -93,12 +96,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();
@@ -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);
            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);
        }
    }
}
+3 −7
Original line number Diff line number Diff line
@@ -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;
@@ -127,12 +128,6 @@ public class ConfigDialogFragment extends DialogFragment implements
        dismiss();
    }

    @Override
    public void dismiss() {
        ((VpnSettings) getTargetFragment()).update();
        super.dismiss();
    }

    @Override
    public void onCancel(DialogInterface dialog) {
        dismiss();
@@ -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);
+61 −59
Original line number Diff line number Diff line
@@ -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);
    }

    public void update() {
    @Override
    public void onPause() {
        // Pause monitoring
        mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);

        if (mUpdater != null) {
            mUpdater.removeCallbacksAndMessages(null);
        }

        super.onPause();
    }

    @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;
                }
        mUpdater.sendEmptyMessage(0);
            }

            // 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.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);
            }
        }
    };
+2 −1
Original line number Diff line number Diff line
@@ -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()));
        }