Show a disclaimer about enabling vpn lockdown
Lockdown is now the default option, not best-effort mode. It's easier to shoot oneself in the foot now so we'll show a warning to explain that before switching it on. Bug: 29052115 Bug: 29076208 Test: com.android.settings.vpn2.AppSettingsTest Change-Id: Ia6845e6a7d57baa5476b8a021fb1255fd74aabea
This commit is contained in:
@@ -5347,9 +5347,19 @@
|
||||
<!-- Button label to forget a VPN profile [CHAR LIMIT=40] -->
|
||||
<string name="vpn_forget_long">Forget VPN</string>
|
||||
<!-- Dialog message title to set another VPN app to be always-on [CHAR LIMIT=40] -->
|
||||
<string name="vpn_replace_always_on_vpn_title">Replace existing VPN?</string>
|
||||
<string name="vpn_replace_vpn_title">Replace existing VPN?</string>
|
||||
<!-- Dialog message title to set always-on VPN when another app was not already set. -->
|
||||
<string name="vpn_set_vpn_title">Set always-on VPN?</string>
|
||||
<!-- Dialog message body to explain that always-on VPN will disable network traffic while the VPN is connecting. -->
|
||||
<string name="vpn_first_always_on_vpn_message">By turning on this setting, you won\'t have an Internet connection until the VPN successfully connects</string>
|
||||
<!-- Dialog message body to explain that always-on VPN will disable network traffic while the VPN is connecting, and that this will replace the current VPN. -->
|
||||
<string name="vpn_replace_always_on_vpn_enable_message">Your existing VPN will be replaced, and you won\'t have an Internet connection until the VPN successfully connects</string>
|
||||
<!-- Dialog message body to connect a VPN app, replacing another VPN app that is already always-on [CHAR LIMIT=NONE] -->
|
||||
<string name="vpn_replace_always_on_vpn_disable_message">You\'re already connected to an always-on VPN. If you connect to a different one, your existing VPN will be replaced, and always-on mode will turn off.</string>
|
||||
<!-- Dialog message body to set another VPN app to be always-on [CHAR LIMIT=NONE] -->
|
||||
<string name="vpn_replace_always_on_vpn_message">You\'re already connected to a VPN. If you connect to a different one, your existing VPN will be replaced.</string>
|
||||
<string name="vpn_replace_vpn_message">You\'re already connected to a VPN. If you connect to a different one, your existing VPN will be replaced.</string>
|
||||
<!-- Dialog action button to turn on a VPN. -->
|
||||
<string name="vpn_turn_on">Turn on</string>
|
||||
<!-- Dialog mesage title when the user can't connect an always-on vpn [CHAR LIMIT=NONE] -->
|
||||
<string name="vpn_cant_connect_title"><xliff:g id="vpn_name" example="OpenVPN">%1$s</xliff:g> can\'t connect</string>
|
||||
<!-- Dialog message subtitle when the user can't connect an always-on vpn [CHAR LIMIT=NONE] -->
|
||||
|
@@ -158,7 +158,7 @@ public class AppDialogFragment extends InstrumentedDialogFragment implements App
|
||||
}
|
||||
final int userId = getUserId();
|
||||
try {
|
||||
if (mPackageInfo.packageName.equals(getConnectedPackage(mService, userId))) {
|
||||
if (mPackageInfo.packageName.equals(VpnUtils.getConnectedPackage(mService, userId))) {
|
||||
mService.setAlwaysOnVpnPackage(userId, null, /* lockdownEnabled */ false);
|
||||
mService.prepareVpn(mPackageInfo.packageName, VpnConfig.LEGACY_VPN, userId);
|
||||
}
|
||||
@@ -176,10 +176,4 @@ public class AppDialogFragment extends InstrumentedDialogFragment implements App
|
||||
private int getUserId() {
|
||||
return UserHandle.getUserId(mPackageInfo.applicationInfo.uid);
|
||||
}
|
||||
|
||||
private static String getConnectedPackage(IConnectivityManager service, final int userId)
|
||||
throws RemoteException {
|
||||
final VpnConfig config = service.getVpnConfig(userId);
|
||||
return config != null ? config.user : null;
|
||||
}
|
||||
}
|
||||
|
@@ -21,18 +21,21 @@ import android.app.AppOpsManager;
|
||||
import android.app.Dialog;
|
||||
import android.app.DialogFragment;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.IConnectivityManager;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
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;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
@@ -51,7 +54,8 @@ import java.util.List;
|
||||
import static android.app.AppOpsManager.OP_ACTIVATE_VPN;
|
||||
|
||||
public class AppManagementFragment extends SettingsPreferenceFragment
|
||||
implements Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener {
|
||||
implements Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener,
|
||||
ConfirmLockdownFragment.ConfirmLockdownListener {
|
||||
|
||||
private static final String TAG = "AppManagementFragment";
|
||||
|
||||
@@ -63,6 +67,7 @@ public class AppManagementFragment extends SettingsPreferenceFragment
|
||||
|
||||
private PackageManager mPackageManager;
|
||||
private ConnectivityManager mConnectivityManager;
|
||||
private IConnectivityManager mConnectivityService;
|
||||
|
||||
// VPN app info
|
||||
private final int mUserId = UserHandle.myUserId();
|
||||
@@ -108,6 +113,8 @@ public class AppManagementFragment extends SettingsPreferenceFragment
|
||||
|
||||
mPackageManager = getContext().getPackageManager();
|
||||
mConnectivityManager = getContext().getSystemService(ConnectivityManager.class);
|
||||
mConnectivityService = IConnectivityManager.Stub
|
||||
.asInterface(ServiceManager.getService(Context.CONNECTIVITY_SERVICE));
|
||||
|
||||
mPreferenceVersion = findPreference(KEY_VERSION);
|
||||
mPreferenceAlwaysOn = (RestrictedSwitchPreference) findPreference(KEY_ALWAYS_ON_VPN);
|
||||
@@ -169,13 +176,23 @@ public class AppManagementFragment extends SettingsPreferenceFragment
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean onAlwaysOnVpnClick(final boolean isChecked) {
|
||||
if (isChecked && isLegacyVpnLockDownOrAnotherPackageAlwaysOn()) {
|
||||
// Show dialog if user replace always-on-vpn package and show not checked first
|
||||
ReplaceExistingVpnFragment.show(this);
|
||||
private boolean onAlwaysOnVpnClick(final boolean alwaysOnSetting) {
|
||||
final boolean replacing = isAnotherVpnActive();
|
||||
final boolean wasAlwaysOn = VpnUtils.isAlwaysOnOrLegacyLockdownActive(getActivity());
|
||||
if (ConfirmLockdownFragment.shouldShow(replacing, wasAlwaysOn, alwaysOnSetting)) {
|
||||
// Place a dialog to confirm that traffic should be locked down.
|
||||
final Bundle options = null;
|
||||
ConfirmLockdownFragment.show(this, replacing, wasAlwaysOn, alwaysOnSetting, options);
|
||||
return false;
|
||||
} else {
|
||||
return setAlwaysOnVpnByUI(isChecked);
|
||||
}
|
||||
// No need to show the dialog. Change the setting straight away.
|
||||
return setAlwaysOnVpnByUI(alwaysOnSetting);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfirmLockdown(Bundle options, boolean isEnabled) {
|
||||
if (setAlwaysOnVpnByUI(isEnabled)) {
|
||||
updateUI();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,7 +214,7 @@ public class AppManagementFragment extends SettingsPreferenceFragment
|
||||
|
||||
private boolean setAlwaysOnVpn(boolean isEnabled) {
|
||||
return mConnectivityManager.setAlwaysOnVpnPackageForUser(mUserId,
|
||||
isEnabled ? mPackageName : null, /* lockdownEnabled */ false);
|
||||
isEnabled ? mPackageName : null, /* lockdownEnabled */ true);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -293,15 +310,17 @@ public class AppManagementFragment extends SettingsPreferenceFragment
|
||||
return !ArrayUtils.isEmpty(ops);
|
||||
}
|
||||
|
||||
private boolean isLegacyVpnLockDownOrAnotherPackageAlwaysOn() {
|
||||
if (mUserId == UserHandle.USER_SYSTEM) {
|
||||
String lockdownKey = VpnUtils.getLockdownVpn();
|
||||
if (lockdownKey != null) {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* @return {@code true} if another VPN (VpnService or legacy) is connected or set as always-on.
|
||||
*/
|
||||
private boolean isAnotherVpnActive() {
|
||||
try {
|
||||
final VpnConfig config = mConnectivityService.getVpnConfig(mUserId);
|
||||
return config != null && !TextUtils.equals(config.user, mPackageName);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failure to look up active VPN", e);
|
||||
return false;
|
||||
}
|
||||
|
||||
return getAlwaysOnVpnPackage() != null && !isVpnAlwaysOn();
|
||||
}
|
||||
|
||||
public static class CannotConnectFragment extends InstrumentedDialogFragment {
|
||||
@@ -334,42 +353,4 @@ public class AppManagementFragment extends SettingsPreferenceFragment
|
||||
.create();
|
||||
}
|
||||
}
|
||||
|
||||
public static class ReplaceExistingVpnFragment extends InstrumentedDialogFragment
|
||||
implements DialogInterface.OnClickListener {
|
||||
private static final String TAG = "ReplaceExistingVpn";
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsEvent.DIALOG_VPN_REPLACE_EXISTING;
|
||||
}
|
||||
|
||||
public static void show(AppManagementFragment parent) {
|
||||
if (parent.getFragmentManager().findFragmentByTag(TAG) == null) {
|
||||
final ReplaceExistingVpnFragment frag = new ReplaceExistingVpnFragment();
|
||||
frag.setTargetFragment(parent, 0);
|
||||
frag.show(parent.getFragmentManager(), TAG);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
return new AlertDialog.Builder(getActivity())
|
||||
.setTitle(R.string.vpn_replace_always_on_vpn_title)
|
||||
.setMessage(getActivity().getString(R.string.vpn_replace_always_on_vpn_message))
|
||||
.setNegativeButton(getActivity().getString(R.string.vpn_cancel), null)
|
||||
.setPositiveButton(getActivity().getString(R.string.vpn_replace), this)
|
||||
.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
if (getTargetFragment() instanceof AppManagementFragment) {
|
||||
final AppManagementFragment target = (AppManagementFragment) getTargetFragment();
|
||||
if (target.setAlwaysOnVpnByUI(true)) {
|
||||
target.updateUI();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.settings.vpn2;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.app.DialogFragment;
|
||||
import android.content.Context;
|
||||
@@ -29,6 +30,7 @@ import android.os.UserHandle;
|
||||
import android.security.Credentials;
|
||||
import android.security.KeyStore;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.android.internal.logging.MetricsProto;
|
||||
@@ -41,8 +43,9 @@ import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
||||
/**
|
||||
* Fragment wrapper around a {@link ConfigDialog}.
|
||||
*/
|
||||
public class ConfigDialogFragment extends InstrumentedDialogFragment
|
||||
implements DialogInterface.OnClickListener {
|
||||
public class ConfigDialogFragment extends InstrumentedDialogFragment implements
|
||||
DialogInterface.OnClickListener, DialogInterface.OnShowListener, View.OnClickListener,
|
||||
ConfirmLockdownFragment.ConfirmLockdownListener {
|
||||
private static final String TAG_CONFIG_DIALOG = "vpnconfigdialog";
|
||||
private static final String TAG = "ConfigDialogFragment";
|
||||
|
||||
@@ -103,7 +106,31 @@ public class ConfigDialogFragment extends InstrumentedDialogFragment
|
||||
boolean editing = args.getBoolean(ARG_EDITING);
|
||||
boolean exists = args.getBoolean(ARG_EXISTS);
|
||||
|
||||
return new ConfigDialog(getActivity(), this, profile, editing, exists);
|
||||
final Dialog dialog = new ConfigDialog(getActivity(), this, profile, editing, exists);
|
||||
dialog.setOnShowListener(this);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override for the default onClick handler which also calls dismiss().
|
||||
*
|
||||
* @see DialogInterface.OnClickListener#onClick(DialogInterface, int)
|
||||
*/
|
||||
@Override
|
||||
public void onShow(DialogInterface dialogInterface) {
|
||||
((AlertDialog) getDialog()).getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View positiveButton) {
|
||||
onClick(getDialog(), AlertDialog.BUTTON_POSITIVE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfirmLockdown(Bundle options, boolean isEnabled) {
|
||||
VpnProfile profile = (VpnProfile) options.getParcelable(ARG_PROFILE);
|
||||
connect(profile, isEnabled);
|
||||
dismiss();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -112,24 +139,24 @@ public class ConfigDialogFragment extends InstrumentedDialogFragment
|
||||
VpnProfile profile = dialog.getProfile();
|
||||
|
||||
if (button == DialogInterface.BUTTON_POSITIVE) {
|
||||
// Update KeyStore entry
|
||||
KeyStore.getInstance().put(Credentials.VPN + profile.key, profile.encode(),
|
||||
KeyStore.UID_SELF, /* flags */ 0);
|
||||
|
||||
// Flush out previous connection, which may be an old version of the profile
|
||||
if (!disconnect(profile)) {
|
||||
Log.w(TAG, "Unable to remove previous connection. Continuing anyway.");
|
||||
}
|
||||
|
||||
updateLockdownVpn(dialog.isVpnAlwaysOn(), profile);
|
||||
|
||||
// If we are not editing, connect!
|
||||
if (!dialog.isEditing() && !VpnUtils.isVpnLockdown(profile.key)) {
|
||||
try {
|
||||
connect(profile);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to connect", e);
|
||||
// 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(getContext());
|
||||
try {
|
||||
final boolean replace = VpnUtils.isVpnActive(getContext());
|
||||
if (shouldConnect && !isConnected(profile) &&
|
||||
ConfirmLockdownFragment.shouldShow(replace, wasAlwaysOn, shouldLockdown)) {
|
||||
final Bundle opts = new Bundle();
|
||||
opts.putParcelable(ARG_PROFILE, profile);
|
||||
ConfirmLockdownFragment.show(this, replace, wasAlwaysOn, shouldLockdown, opts);
|
||||
} else if (shouldConnect) {
|
||||
connect(profile, shouldLockdown);
|
||||
} else {
|
||||
save(profile, false);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed to check active VPN state. Skipping.", e);
|
||||
}
|
||||
} else if (button == DialogInterface.BUTTON_NEUTRAL) {
|
||||
// Disable profile if connected
|
||||
@@ -175,11 +202,31 @@ public class ConfigDialogFragment extends InstrumentedDialogFragment
|
||||
}
|
||||
}
|
||||
|
||||
private void connect(VpnProfile profile) throws RemoteException {
|
||||
try {
|
||||
mService.startLegacyVpn(profile);
|
||||
} catch (IllegalStateException e) {
|
||||
Toast.makeText(getActivity(), R.string.vpn_no_network, Toast.LENGTH_LONG).show();
|
||||
private void save(VpnProfile profile, boolean lockdown) {
|
||||
KeyStore.getInstance().put(Credentials.VPN + profile.key, profile.encode(),
|
||||
KeyStore.UID_SELF, /* flags */ 0);
|
||||
|
||||
// Flush out old version of profile
|
||||
disconnect(profile);
|
||||
|
||||
// Notify lockdown VPN that the profile has changed.
|
||||
updateLockdownVpn(lockdown, profile);
|
||||
}
|
||||
|
||||
private void connect(VpnProfile profile, boolean lockdown) {
|
||||
save(profile, lockdown);
|
||||
|
||||
// Now try to start the VPN - this is not necessary if the profile is set as lockdown,
|
||||
// because just saving the profile in this mode will start a connection.
|
||||
if (!VpnUtils.isVpnLockdown(profile.key)) {
|
||||
VpnUtils.clearLockdownVpn(getContext());
|
||||
try {
|
||||
mService.startLegacyVpn(profile);
|
||||
} catch (IllegalStateException e) {
|
||||
Toast.makeText(getActivity(), R.string.vpn_no_network, Toast.LENGTH_LONG).show();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to connect", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
110
src/com/android/settings/vpn2/ConfirmLockdownFragment.java
Normal file
110
src/com/android/settings/vpn2/ConfirmLockdownFragment.java
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.settings.vpn2;
|
||||
|
||||
import android.app.Fragment;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.app.DialogFragment;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.android.internal.logging.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
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);
|
||||
}
|
||||
|
||||
private static final String TAG = "ConfirmLockdown";
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsEvent.DIALOG_VPN_REPLACE_EXISTING;
|
||||
}
|
||||
|
||||
private static final String ARG_REPLACING = "replacing";
|
||||
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";
|
||||
|
||||
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.
|
||||
return replacing || (toLockdown && !fromLockdown);
|
||||
}
|
||||
|
||||
public static void show(Fragment parent, boolean replacing,
|
||||
boolean fromLockdown, boolean toLockdown, Bundle options) {
|
||||
if (parent.getFragmentManager().findFragmentByTag(TAG) != null) {
|
||||
// Already exists. Don't show it twice.
|
||||
return;
|
||||
}
|
||||
final Bundle args = new Bundle();
|
||||
args.putBoolean(ARG_REPLACING, replacing);
|
||||
args.putBoolean(ARG_LOCKDOWN_SRC, fromLockdown);
|
||||
args.putBoolean(ARG_LOCKDOWN_DST, toLockdown);
|
||||
args.putParcelable(ARG_OPTIONS, options);
|
||||
|
||||
final ConfirmLockdownFragment frag = new ConfirmLockdownFragment();
|
||||
frag.setArguments(args);
|
||||
frag.setTargetFragment(parent, 0);
|
||||
frag.show(parent.getFragmentManager(), TAG);
|
||||
}
|
||||
|
||||
@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 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));
|
||||
final int messageId;
|
||||
if (nowAlwaysOn) {
|
||||
messageId = replacing
|
||||
? R.string.vpn_replace_always_on_vpn_enable_message
|
||||
: R.string.vpn_first_always_on_vpn_message;
|
||||
} else {
|
||||
messageId = wasAlwaysOn
|
||||
? R.string.vpn_replace_always_on_vpn_disable_message
|
||||
: R.string.vpn_replace_vpn_message;
|
||||
}
|
||||
|
||||
return new AlertDialog.Builder(getActivity())
|
||||
.setTitle(titleId)
|
||||
.setMessage(messageId)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.setPositiveButton(actionId, this)
|
||||
.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
if (getTargetFragment() instanceof ConfirmLockdownListener) {
|
||||
((ConfirmLockdownListener) getTargetFragment()).onConfirmLockdown(
|
||||
getArguments().getParcelable(ARG_OPTIONS),
|
||||
getArguments().getBoolean(ARG_LOCKDOWN_DST));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -17,16 +17,20 @@ package com.android.settings.vpn2;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.IConnectivityManager;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.security.Credentials;
|
||||
import android.security.KeyStore;
|
||||
|
||||
import com.android.internal.net.VpnConfig;
|
||||
|
||||
/**
|
||||
* Utility functions for vpn.
|
||||
*
|
||||
* Keystore methods should only be called in system user
|
||||
*/
|
||||
public class VpnUtils {
|
||||
|
||||
public static String getLockdownVpn() {
|
||||
final byte[] value = KeyStore.getInstance().get(Credentials.LOCKDOWN_VPN);
|
||||
return value == null ? null : new String(value);
|
||||
@@ -35,17 +39,42 @@ public class VpnUtils {
|
||||
public static void clearLockdownVpn(Context context) {
|
||||
KeyStore.getInstance().delete(Credentials.LOCKDOWN_VPN);
|
||||
// Always notify ConnectivityManager after keystore update
|
||||
context.getSystemService(ConnectivityManager.class).updateLockdownVpn();
|
||||
getConnectivityManager(context).updateLockdownVpn();
|
||||
}
|
||||
|
||||
public static void setLockdownVpn(Context context, String lockdownKey) {
|
||||
KeyStore.getInstance().put(Credentials.LOCKDOWN_VPN, lockdownKey.getBytes(),
|
||||
KeyStore.UID_SELF, /* flags */ 0);
|
||||
// Always notify ConnectivityManager after keystore update
|
||||
context.getSystemService(ConnectivityManager.class).updateLockdownVpn();
|
||||
getConnectivityManager(context).updateLockdownVpn();
|
||||
}
|
||||
|
||||
public static boolean isVpnLockdown(String key) {
|
||||
return key.equals(getLockdownVpn());
|
||||
}
|
||||
|
||||
public static boolean isAlwaysOnOrLegacyLockdownActive(Context context) {
|
||||
final int userId = context.getUserId();
|
||||
return getLockdownVpn() != null
|
||||
|| getConnectivityManager(context).getAlwaysOnVpnPackageForUser(userId) != null;
|
||||
}
|
||||
|
||||
public static boolean isVpnActive(Context context) throws RemoteException {
|
||||
return getIConnectivityManager().getVpnConfig(context.getUserId()) != null;
|
||||
}
|
||||
|
||||
public static String getConnectedPackage(IConnectivityManager service, final int userId)
|
||||
throws RemoteException {
|
||||
final VpnConfig config = service.getVpnConfig(userId);
|
||||
return config != null ? config.user : null;
|
||||
}
|
||||
|
||||
private static ConnectivityManager getConnectivityManager(Context context) {
|
||||
return context.getSystemService(ConnectivityManager.class);
|
||||
}
|
||||
|
||||
private static IConnectivityManager getIConnectivityManager() {
|
||||
return IConnectivityManager.Stub.asInterface(
|
||||
ServiceManager.getService(Context.CONNECTIVITY_SERVICE));
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user