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

Commit ad5ccad4 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Implement always-on VPN separate lockdown setting"

parents dea70354 e7347dd8
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -5367,6 +5367,12 @@
    <string name="vpn_always_on_inactive">Always-on inactive</string>
    <!-- Preference summary for app not supporting always-on vpn [CHAR LIMIT=NONE] -->
    <string name="vpn_not_supported_by_this_app">Not supported by this app</string>
    <!-- Preference title for forcing all network connections to go through VPN. -->
    <string name="vpn_require_connection">Only allow connections through VPN</string>
    <!-- Preference summary for network connections being forced to go through VPN. -->
    <string name="vpn_lockdown_active">Lockdown active</string>
    <!-- Preference summary for network connections not being forced to go through VPN. -->
    <string name="vpn_lockdown_inactive">Lockdown inactive</string>
    <!-- Summary describing the always-on VPN feature. [CHAR LIMIT=NONE] -->
    <string name="vpn_lockdown_summary">Select a VPN profile to always remain connected to. Network traffic will only be allowed when connected to this VPN.</string>
+11 −0
Original line number Diff line number Diff line
@@ -33,6 +33,17 @@
                settings:useAdditionalSummary="true"
                settings:restrictedSwitchSummary="@string/disabled_by_admin_summary_text" />

        <com.android.settingslib.RestrictedSwitchPreference
                android:key="lockdown_vpn"
                android:title="@string/vpn_require_connection"
                android:defaultValue="false"
                android:summaryOn="@string/vpn_lockdown_active"
                android:summaryOff="@string/vpn_lockdown_inactive"
                android:dependency="always_on_vpn"
                settings:userRestriction="no_config_vpn"
                settings:useAdditionalSummary="true"
                settings:restrictedSwitchSummary="@string/disabled_by_admin_summary_text" />

        <com.android.settings.DimmableIconPreference
                android:key="forget_vpn"
                android:title="@string/vpn_forget_long"
+30 −16
Original line number Diff line number Diff line
@@ -33,7 +33,6 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.support.v7.preference.Preference;
import android.text.TextUtils;
import android.util.Log;
@@ -63,6 +62,7 @@ public class AppManagementFragment extends SettingsPreferenceFragment

    private static final String KEY_VERSION = "version";
    private static final String KEY_ALWAYS_ON_VPN = "always_on_vpn";
    private static final String KEY_LOCKDOWN_VPN = "lockdown_vpn";
    private static final String KEY_FORGET_VPN = "forget_vpn";

    private PackageManager mPackageManager;
@@ -78,6 +78,7 @@ public class AppManagementFragment extends SettingsPreferenceFragment
    // UI preference
    private Preference mPreferenceVersion;
    private RestrictedSwitchPreference mPreferenceAlwaysOn;
    private RestrictedSwitchPreference mPreferenceLockdown;
    private RestrictedPreference mPreferenceForget;

    // Listener
@@ -87,7 +88,7 @@ public class AppManagementFragment extends SettingsPreferenceFragment
        public void onForget() {
            // Unset always-on-vpn when forgetting the VPN
            if (isVpnAlwaysOn()) {
                setAlwaysOnVpn(false);
                setAlwaysOnVpn(false, false);
            }
            // Also dismiss and go back to VPN list
            finish();
@@ -118,9 +119,11 @@ public class AppManagementFragment extends SettingsPreferenceFragment

        mPreferenceVersion = findPreference(KEY_VERSION);
        mPreferenceAlwaysOn = (RestrictedSwitchPreference) findPreference(KEY_ALWAYS_ON_VPN);
        mPreferenceLockdown = (RestrictedSwitchPreference) findPreference(KEY_LOCKDOWN_VPN);
        mPreferenceForget = (RestrictedPreference) findPreference(KEY_FORGET_VPN);

        mPreferenceAlwaysOn.setOnPreferenceChangeListener(this);
        mPreferenceLockdown.setOnPreferenceChangeListener(this);
        mPreferenceForget.setOnPreferenceClickListener(this);
    }

@@ -154,7 +157,9 @@ public class AppManagementFragment extends SettingsPreferenceFragment
    public boolean onPreferenceChange(Preference preference, Object newValue) {
        switch (preference.getKey()) {
            case KEY_ALWAYS_ON_VPN:
                return onAlwaysOnVpnClick((Boolean) newValue);
                return onAlwaysOnVpnClick((Boolean) newValue, mPreferenceLockdown.isChecked());
            case KEY_LOCKDOWN_VPN:
                return onAlwaysOnVpnClick(mPreferenceAlwaysOn.isChecked(), (Boolean) newValue);
            default:
                Log.w(TAG, "unknown key is clicked: " + preference.getKey());
                return false;
@@ -176,27 +181,28 @@ public class AppManagementFragment extends SettingsPreferenceFragment
        return true;
    }

    private boolean onAlwaysOnVpnClick(final boolean alwaysOnSetting) {
    private boolean onAlwaysOnVpnClick(final boolean alwaysOnSetting, final boolean lockdown) {
        final boolean replacing = isAnotherVpnActive();
        final boolean wasAlwaysOn = VpnUtils.isAlwaysOnOrLegacyLockdownActive(getActivity());
        if (ConfirmLockdownFragment.shouldShow(replacing, wasAlwaysOn, alwaysOnSetting)) {
        final boolean wasLockdown = VpnUtils.isAnyLockdownActive(getActivity());
        if (ConfirmLockdownFragment.shouldShow(replacing, wasLockdown, lockdown)) {
            // Place a dialog to confirm that traffic should be locked down.
            final Bundle options = null;
            ConfirmLockdownFragment.show(this, replacing, wasAlwaysOn, alwaysOnSetting, options);
            ConfirmLockdownFragment.show(
                    this, replacing, alwaysOnSetting, wasLockdown, lockdown, options);
            return false;
        }
        // No need to show the dialog. Change the setting straight away.
        return setAlwaysOnVpnByUI(alwaysOnSetting);
        return setAlwaysOnVpnByUI(alwaysOnSetting, lockdown);
    }

    @Override
    public void onConfirmLockdown(Bundle options, boolean isEnabled) {
        if (setAlwaysOnVpnByUI(isEnabled)) {
    public void onConfirmLockdown(Bundle options, boolean isEnabled, boolean isLockdown) {
        if (setAlwaysOnVpnByUI(isEnabled, isLockdown)) {
            updateUI();
        }
    }

    private boolean setAlwaysOnVpnByUI(boolean isEnabled) {
    private boolean setAlwaysOnVpnByUI(boolean isEnabled, boolean isLockdown) {
        updateRestrictedViews();
        if (!mPreferenceAlwaysOn.isEnabled()) {
            return false;
@@ -205,16 +211,16 @@ public class AppManagementFragment extends SettingsPreferenceFragment
        if (mUserId == UserHandle.USER_SYSTEM) {
            VpnUtils.clearLockdownVpn(getContext());
        }
        final boolean success = setAlwaysOnVpn(isEnabled);
        final boolean success = setAlwaysOnVpn(isEnabled, isLockdown);
        if (isEnabled && (!success || !isVpnAlwaysOn())) {
            CannotConnectFragment.show(this, mVpnLabel);
        }
        return success;
    }

    private boolean setAlwaysOnVpn(boolean isEnabled) {
    private boolean setAlwaysOnVpn(boolean isEnabled, boolean isLockdown) {
        return mConnectivityManager.setAlwaysOnVpnPackageForUser(mUserId,
                isEnabled ? mPackageName : null, /* lockdownEnabled */ true);
                isEnabled ? mPackageName : null, isLockdown);
    }

    @VisibleForTesting
@@ -232,7 +238,12 @@ public class AppManagementFragment extends SettingsPreferenceFragment

    private void updateUI() {
        if (isAdded()) {
            mPreferenceAlwaysOn.setChecked(isVpnAlwaysOn());
            final boolean alwaysOn = isVpnAlwaysOn();
            final boolean lockdown = alwaysOn
                    && VpnUtils.isAnyLockdownActive(getActivity());

            mPreferenceAlwaysOn.setChecked(alwaysOn);
            mPreferenceLockdown.setChecked(lockdown);
            updateRestrictedViews();
        }
    }
@@ -241,6 +252,8 @@ public class AppManagementFragment extends SettingsPreferenceFragment
        if (isAdded()) {
            mPreferenceAlwaysOn.checkRestrictionAndSetDisabled(UserManager.DISALLOW_CONFIG_VPN,
                    mUserId);
            mPreferenceLockdown.checkRestrictionAndSetDisabled(UserManager.DISALLOW_CONFIG_VPN,
                    mUserId);
            mPreferenceForget.checkRestrictionAndSetDisabled(UserManager.DISALLOW_CONFIG_VPN,
                    mUserId);

@@ -251,6 +264,7 @@ public class AppManagementFragment extends SettingsPreferenceFragment
                // should have refreshed the enable state.
            } else {
                mPreferenceAlwaysOn.setEnabled(false);
                mPreferenceLockdown.setEnabled(false);
                mPreferenceAlwaysOn.setSummary(R.string.vpn_not_supported_by_this_app);
            }
        }
+6 −5
Original line number Diff line number Diff line
@@ -134,9 +134,9 @@ public class ConfigDialogFragment extends InstrumentedDialogFragment implements
    }

    @Override
    public void onConfirmLockdown(Bundle options, boolean isEnabled) {
    public void onConfirmLockdown(Bundle options, boolean isAlwaysOn, boolean isLockdown) {
        VpnProfile profile = (VpnProfile) options.getParcelable(ARG_PROFILE);
        connect(profile, isEnabled);
        connect(profile, isAlwaysOn);
        dismiss();
    }

@@ -149,14 +149,15 @@ public class ConfigDialogFragment extends InstrumentedDialogFragment implements
            // Possibly throw up a dialog to explain lockdown VPN.
            final boolean shouldLockdown = dialog.isVpnAlwaysOn();
            final boolean shouldConnect = shouldLockdown || !dialog.isEditing();
            final boolean wasAlwaysOn = VpnUtils.isAlwaysOnOrLegacyLockdownActive(mContext);
            final boolean wasLockdown = VpnUtils.isAnyLockdownActive(mContext);
            try {
                final boolean replace = VpnUtils.isVpnActive(mContext);
                if (shouldConnect && !isConnected(profile) &&
                        ConfirmLockdownFragment.shouldShow(replace, wasAlwaysOn, shouldLockdown)) {
                        ConfirmLockdownFragment.shouldShow(replace, wasLockdown, shouldLockdown)) {
                    final Bundle opts = new Bundle();
                    opts.putParcelable(ARG_PROFILE, profile);
                    ConfirmLockdownFragment.show(this, replace, wasAlwaysOn, shouldLockdown, opts);
                    ConfirmLockdownFragment.show(this, replace, /* alwaysOn */ shouldLockdown,
                           /* from */  wasLockdown, /* to */ shouldLockdown, opts);
                } else if (shouldConnect) {
                    connect(profile, shouldLockdown);
                } else {
+12 −8
Original line number Diff line number Diff line
@@ -29,7 +29,7 @@ import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
public class ConfirmLockdownFragment extends InstrumentedDialogFragment
        implements DialogInterface.OnClickListener {
    public interface ConfirmLockdownListener {
        public void onConfirmLockdown(Bundle options, boolean isEnabled);
        public void onConfirmLockdown(Bundle options, boolean isEnabled, boolean isLockdown);
    }

    private static final String TAG = "ConfirmLockdown";
@@ -40,6 +40,7 @@ public class ConfirmLockdownFragment extends InstrumentedDialogFragment
    }

    private static final String ARG_REPLACING = "replacing";
    private static final String ARG_ALWAYS_ON = "always_on";
    private static final String ARG_LOCKDOWN_SRC = "lockdown_old";
    private static final String ARG_LOCKDOWN_DST = "lockdown_new";
    private static final String ARG_OPTIONS = "options";
@@ -47,11 +48,11 @@ public class ConfirmLockdownFragment extends InstrumentedDialogFragment
    public static boolean shouldShow(boolean replacing, boolean fromLockdown, boolean toLockdown) {
        // We only need to show this if we are:
        //  - replacing an existing connection
        //  - switching on always-on mode where it was not enabled before.
        //  - switching on always-on mode with lockdown enabled where it was not enabled before.
        return replacing || (toLockdown && !fromLockdown);
    }

    public static void show(Fragment parent, boolean replacing,
    public static void show(Fragment parent, boolean replacing, boolean alwaysOn,
            boolean fromLockdown, boolean toLockdown, Bundle options) {
        if (parent.getFragmentManager().findFragmentByTag(TAG) != null) {
            // Already exists. Don't show it twice.
@@ -59,6 +60,7 @@ public class ConfirmLockdownFragment extends InstrumentedDialogFragment
        }
        final Bundle args = new Bundle();
        args.putBoolean(ARG_REPLACING, replacing);
        args.putBoolean(ARG_ALWAYS_ON, alwaysOn);
        args.putBoolean(ARG_LOCKDOWN_SRC, fromLockdown);
        args.putBoolean(ARG_LOCKDOWN_DST, toLockdown);
        args.putParcelable(ARG_OPTIONS, options);
@@ -72,20 +74,21 @@ public class ConfirmLockdownFragment extends InstrumentedDialogFragment
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        final boolean replacing = getArguments().getBoolean(ARG_REPLACING);
        final boolean wasAlwaysOn = getArguments().getBoolean(ARG_LOCKDOWN_SRC);
        final boolean nowAlwaysOn = getArguments().getBoolean(ARG_LOCKDOWN_DST);
        final boolean alwaysOn = getArguments().getBoolean(ARG_ALWAYS_ON);
        final boolean wasLockdown = getArguments().getBoolean(ARG_LOCKDOWN_SRC);
        final boolean nowLockdown = getArguments().getBoolean(ARG_LOCKDOWN_DST);

        final int titleId = replacing ? R.string.vpn_replace_vpn_title : R.string.vpn_set_vpn_title;
        final int actionId =
                (replacing ? R.string.vpn_replace :
                (nowAlwaysOn ? R.string.vpn_turn_on : R.string.okay));
                (nowLockdown ? R.string.vpn_turn_on : R.string.okay));
        final int messageId;
        if (nowAlwaysOn) {
        if (nowLockdown) {
            messageId = replacing
                    ? R.string.vpn_replace_always_on_vpn_enable_message
                    : R.string.vpn_first_always_on_vpn_message;
        } else {
            messageId = wasAlwaysOn
            messageId = wasLockdown
                    ? R.string.vpn_replace_always_on_vpn_disable_message
                    : R.string.vpn_replace_vpn_message;
        }
@@ -103,6 +106,7 @@ public class ConfirmLockdownFragment extends InstrumentedDialogFragment
        if (getTargetFragment() instanceof ConfirmLockdownListener) {
            ((ConfirmLockdownListener) getTargetFragment()).onConfirmLockdown(
                    getArguments().getParcelable(ARG_OPTIONS),
                    getArguments().getBoolean(ARG_ALWAYS_ON),
                    getArguments().getBoolean(ARG_LOCKDOWN_DST));
        }
    }
Loading