Merge changes Ia68f482a,I4911e214,Ied379654,I66d18512,Ie8e1bd63
* changes: Check registering system default callback needs NETWORK_SETTINGS. Move VPN code from ConnectivityService to VpnManagerService. Add a skeleton VpnManagerService, and start it on boot. Convert LockdownVpnTracker to NetworkCallbacks. Minor fixes to VpnTransportInfo.
This commit is contained in:
@@ -49,17 +49,6 @@ public final class ConnectivityFrameworkInitializer {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// TODO: move outside of the connectivity JAR
|
|
||||||
SystemServiceRegistry.registerContextAwareService(
|
|
||||||
Context.VPN_MANAGEMENT_SERVICE,
|
|
||||||
VpnManager.class,
|
|
||||||
(context) -> {
|
|
||||||
final ConnectivityManager cm = context.getSystemService(
|
|
||||||
ConnectivityManager.class);
|
|
||||||
return cm.createVpnManager();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
SystemServiceRegistry.registerContextAwareService(
|
SystemServiceRegistry.registerContextAwareService(
|
||||||
Context.CONNECTIVITY_DIAGNOSTICS_SERVICE,
|
Context.CONNECTIVITY_DIAGNOSTICS_SERVICE,
|
||||||
ConnectivityDiagnosticsManager.class,
|
ConnectivityDiagnosticsManager.class,
|
||||||
|
|||||||
@@ -824,6 +824,7 @@ public class ConnectivityManager {
|
|||||||
|
|
||||||
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562)
|
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562)
|
||||||
private final IConnectivityManager mService;
|
private final IConnectivityManager mService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A kludge to facilitate static access where a Context pointer isn't available, like in the
|
* A kludge to facilitate static access where a Context pointer isn't available, like in the
|
||||||
* case of the static set/getProcessDefaultNetwork methods and from the Network class.
|
* case of the static set/getProcessDefaultNetwork methods and from the Network class.
|
||||||
@@ -1069,106 +1070,55 @@ public class ConnectivityManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if a VPN app supports always-on mode.
|
* Calls VpnManager#isAlwaysOnVpnPackageSupportedForUser.
|
||||||
*
|
* @deprecated TODO: remove when callers have migrated to VpnManager.
|
||||||
* In order to support the always-on feature, an app has to
|
|
||||||
* <ul>
|
|
||||||
* <li>target {@link VERSION_CODES#N API 24} or above, and
|
|
||||||
* <li>not opt out through the {@link VpnService#SERVICE_META_DATA_SUPPORTS_ALWAYS_ON}
|
|
||||||
* meta-data field.
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @param userId The identifier of the user for whom the VPN app is installed.
|
|
||||||
* @param vpnPackage The canonical package name of the VPN app.
|
|
||||||
* @return {@code true} if and only if the VPN app exists and supports always-on mode.
|
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public boolean isAlwaysOnVpnPackageSupportedForUser(int userId, @Nullable String vpnPackage) {
|
public boolean isAlwaysOnVpnPackageSupportedForUser(int userId, @Nullable String vpnPackage) {
|
||||||
try {
|
return getVpnManager().isAlwaysOnVpnPackageSupportedForUser(userId, vpnPackage);
|
||||||
return mService.isAlwaysOnVpnPackageSupported(userId, vpnPackage);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
throw e.rethrowFromSystemServer();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures an always-on VPN connection through a specific application.
|
* Calls VpnManager#setAlwaysOnVpnPackageForUser.
|
||||||
* This connection is automatically granted and persisted after a reboot.
|
* @deprecated TODO: remove when callers have migrated to VpnManager.
|
||||||
*
|
|
||||||
* <p>The designated package should declare a {@link VpnService} in its
|
|
||||||
* manifest guarded by {@link android.Manifest.permission.BIND_VPN_SERVICE},
|
|
||||||
* otherwise the call will fail.
|
|
||||||
*
|
|
||||||
* @param userId The identifier of the user to set an always-on VPN for.
|
|
||||||
* @param vpnPackage The package name for an installed VPN app on the device, or {@code null}
|
|
||||||
* to remove an existing always-on VPN configuration.
|
|
||||||
* @param lockdownEnabled {@code true} to disallow networking when the VPN is not connected or
|
|
||||||
* {@code false} otherwise.
|
|
||||||
* @param lockdownAllowlist The list of packages that are allowed to access network directly
|
|
||||||
* when VPN is in lockdown mode but is not running. Non-existent packages are ignored so
|
|
||||||
* this method must be called when a package that should be allowed is installed or
|
|
||||||
* uninstalled.
|
|
||||||
* @return {@code true} if the package is set as always-on VPN controller;
|
|
||||||
* {@code false} otherwise.
|
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
@RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN)
|
@Deprecated
|
||||||
public boolean setAlwaysOnVpnPackageForUser(int userId, @Nullable String vpnPackage,
|
public boolean setAlwaysOnVpnPackageForUser(int userId, @Nullable String vpnPackage,
|
||||||
boolean lockdownEnabled, @Nullable List<String> lockdownAllowlist) {
|
boolean lockdownEnabled, @Nullable List<String> lockdownAllowlist) {
|
||||||
try {
|
return getVpnManager().setAlwaysOnVpnPackageForUser(userId, vpnPackage, lockdownEnabled,
|
||||||
return mService.setAlwaysOnVpnPackage(
|
lockdownAllowlist);
|
||||||
userId, vpnPackage, lockdownEnabled, lockdownAllowlist);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
throw e.rethrowFromSystemServer();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the package name of the currently set always-on VPN application.
|
* Calls VpnManager#getAlwaysOnVpnPackageForUser.
|
||||||
* If there is no always-on VPN set, or the VPN is provided by the system instead
|
* @deprecated TODO: remove when callers have migrated to VpnManager.
|
||||||
* of by an app, {@code null} will be returned.
|
|
||||||
*
|
|
||||||
* @return Package name of VPN controller responsible for always-on VPN,
|
|
||||||
* or {@code null} if none is set.
|
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
@RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN)
|
@Deprecated
|
||||||
public String getAlwaysOnVpnPackageForUser(int userId) {
|
public String getAlwaysOnVpnPackageForUser(int userId) {
|
||||||
try {
|
return getVpnManager().getAlwaysOnVpnPackageForUser(userId);
|
||||||
return mService.getAlwaysOnVpnPackage(userId);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
throw e.rethrowFromSystemServer();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return whether always-on VPN is in lockdown mode.
|
* Calls VpnManager#isVpnLockdownEnabled.
|
||||||
*
|
* @deprecated TODO: remove when callers have migrated to VpnManager.
|
||||||
* @hide
|
* @hide
|
||||||
**/
|
*/
|
||||||
@RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN)
|
@Deprecated
|
||||||
public boolean isVpnLockdownEnabled(int userId) {
|
public boolean isVpnLockdownEnabled(int userId) {
|
||||||
try {
|
return getVpnManager().isVpnLockdownEnabled(userId);
|
||||||
return mService.isVpnLockdownEnabled(userId);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
throw e.rethrowFromSystemServer();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the list of packages that are allowed to access network when always-on VPN is in
|
* Calls VpnManager#getVpnLockdownAllowlist.
|
||||||
* lockdown mode but not connected. Returns {@code null} when VPN lockdown is not active.
|
* @deprecated TODO: remove when callers have migrated to VpnManager.
|
||||||
*
|
|
||||||
* @hide
|
* @hide
|
||||||
**/
|
*/
|
||||||
@RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN)
|
@Deprecated
|
||||||
public List<String> getVpnLockdownWhitelist(int userId) {
|
public List<String> getVpnLockdownWhitelist(int userId) {
|
||||||
try {
|
return getVpnManager().getVpnLockdownAllowlist(userId);
|
||||||
return mService.getVpnLockdownWhitelist(userId);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
throw e.rethrowFromSystemServer();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1220,6 +1170,45 @@ public class ConnectivityManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Informs ConnectivityService of whether the legacy lockdown VPN, as implemented by
|
||||||
|
* LockdownVpnTracker, is in use. This is deprecated for new devices starting from Android 12
|
||||||
|
* but is still supported for backwards compatibility.
|
||||||
|
* <p>
|
||||||
|
* This type of VPN is assumed always to use the system default network, and must always declare
|
||||||
|
* exactly one underlying network, which is the network that was the default when the VPN
|
||||||
|
* connected.
|
||||||
|
* <p>
|
||||||
|
* Calling this method with {@code true} enables legacy behaviour, specifically:
|
||||||
|
* <ul>
|
||||||
|
* <li>Any VPN that applies to userId 0 behaves specially with respect to deprecated
|
||||||
|
* {@link #CONNECTIVITY_ACTION} broadcasts. Any such broadcasts will have the state in the
|
||||||
|
* {@link #EXTRA_NETWORK_INFO} replaced by state of the VPN network. Also, any time the VPN
|
||||||
|
* connects, a {@link #CONNECTIVITY_ACTION} broadcast will be sent for the network
|
||||||
|
* underlying the VPN.</li>
|
||||||
|
* <li>Deprecated APIs that return {@link NetworkInfo} objects will have their state
|
||||||
|
* similarly replaced by the VPN network state.</li>
|
||||||
|
* <li>Information on current network interfaces passed to NetworkStatsService will not
|
||||||
|
* include any VPN interfaces.</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param enabled whether legacy lockdown VPN is enabled or disabled
|
||||||
|
*
|
||||||
|
* TODO: @SystemApi(client = MODULE_LIBRARIES)
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@RequiresPermission(anyOf = {
|
||||||
|
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
|
||||||
|
android.Manifest.permission.NETWORK_SETTINGS})
|
||||||
|
public void setLegacyLockdownVpnEnabled(boolean enabled) {
|
||||||
|
try {
|
||||||
|
mService.setLegacyLockdownVpnEnabled(enabled);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
throw e.rethrowFromSystemServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns details about the currently active default data network
|
* Returns details about the currently active default data network
|
||||||
* for a given uid. This is for internal use only to avoid spying
|
* for a given uid. This is for internal use only to avoid spying
|
||||||
@@ -3180,20 +3169,13 @@ public class ConnectivityManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the LockdownVpn mechanism is enabled, updates the vpn
|
* Calls VpnManager#updateLockdownVpn.
|
||||||
* with a reload of its profile.
|
* @deprecated TODO: remove when callers have migrated to VpnManager.
|
||||||
*
|
* @hide
|
||||||
* @return a boolean with {@code} indicating success
|
|
||||||
*
|
|
||||||
* <p>This method can only be called by the system UID
|
|
||||||
* {@hide}
|
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public boolean updateLockdownVpn() {
|
public boolean updateLockdownVpn() {
|
||||||
try {
|
return getVpnManager().updateLockdownVpn();
|
||||||
return mService.updateLockdownVpn();
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
throw e.rethrowFromSystemServer();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -4557,6 +4539,8 @@ public class ConnectivityManager {
|
|||||||
try {
|
try {
|
||||||
mService.factoryReset();
|
mService.factoryReset();
|
||||||
mTetheringManager.stopAllTethering();
|
mTetheringManager.stopAllTethering();
|
||||||
|
// TODO: Migrate callers to VpnManager#factoryReset.
|
||||||
|
getVpnManager().factoryReset();
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
throw e.rethrowFromSystemServer();
|
throw e.rethrowFromSystemServer();
|
||||||
}
|
}
|
||||||
@@ -4850,9 +4834,13 @@ public class ConnectivityManager {
|
|||||||
return new TestNetworkManager(ITestNetworkManager.Stub.asInterface(tnBinder));
|
return new TestNetworkManager(ITestNetworkManager.Stub.asInterface(tnBinder));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @hide */
|
/**
|
||||||
public VpnManager createVpnManager() {
|
* Temporary hack to shim calls from ConnectivityManager to VpnManager. We cannot store a
|
||||||
return new VpnManager(mContext, mService);
|
* private final mVpnManager because ConnectivityManager is initialized before VpnManager.
|
||||||
|
* @hide TODO: remove.
|
||||||
|
*/
|
||||||
|
public VpnManager getVpnManager() {
|
||||||
|
return mContext.getSystemService(VpnManager.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
|
|||||||
@@ -43,9 +43,6 @@ import android.os.PersistableBundle;
|
|||||||
import android.os.ResultReceiver;
|
import android.os.ResultReceiver;
|
||||||
|
|
||||||
import com.android.connectivity.aidl.INetworkAgent;
|
import com.android.connectivity.aidl.INetworkAgent;
|
||||||
import com.android.internal.net.LegacyVpnInfo;
|
|
||||||
import com.android.internal.net.VpnConfig;
|
|
||||||
import com.android.internal.net.VpnProfile;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface that answers queries about, and allows changing, the
|
* Interface that answers queries about, and allows changing, the
|
||||||
@@ -123,35 +120,8 @@ interface IConnectivityManager
|
|||||||
|
|
||||||
ProxyInfo getProxyForNetwork(in Network nework);
|
ProxyInfo getProxyForNetwork(in Network nework);
|
||||||
|
|
||||||
boolean prepareVpn(String oldPackage, String newPackage, int userId);
|
|
||||||
|
|
||||||
void setVpnPackageAuthorization(String packageName, int userId, int vpnType);
|
|
||||||
|
|
||||||
ParcelFileDescriptor establishVpn(in VpnConfig config);
|
|
||||||
|
|
||||||
boolean provisionVpnProfile(in VpnProfile profile, String packageName);
|
|
||||||
|
|
||||||
void deleteVpnProfile(String packageName);
|
|
||||||
|
|
||||||
void startVpnProfile(String packageName);
|
|
||||||
|
|
||||||
void stopVpnProfile(String packageName);
|
|
||||||
|
|
||||||
VpnConfig getVpnConfig(int userId);
|
|
||||||
|
|
||||||
@UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
|
|
||||||
void startLegacyVpn(in VpnProfile profile);
|
|
||||||
|
|
||||||
LegacyVpnInfo getLegacyVpnInfo(int userId);
|
|
||||||
|
|
||||||
boolean updateLockdownVpn();
|
|
||||||
boolean isAlwaysOnVpnPackageSupported(int userId, String packageName);
|
|
||||||
boolean setAlwaysOnVpnPackage(int userId, String packageName, boolean lockdown,
|
|
||||||
in List<String> lockdownWhitelist);
|
|
||||||
String getAlwaysOnVpnPackage(int userId);
|
|
||||||
boolean isVpnLockdownEnabled(int userId);
|
|
||||||
List<String> getVpnLockdownWhitelist(int userId);
|
|
||||||
void setRequireVpnForUids(boolean requireVpn, in UidRange[] ranges);
|
void setRequireVpnForUids(boolean requireVpn, in UidRange[] ranges);
|
||||||
|
void setLegacyLockdownVpnEnabled(boolean enabled);
|
||||||
|
|
||||||
void setProvisioningNotificationVisible(boolean visible, int networkType, in String action);
|
void setProvisioningNotificationVisible(boolean visible, int networkType, in String action);
|
||||||
|
|
||||||
@@ -200,10 +170,6 @@ interface IConnectivityManager
|
|||||||
|
|
||||||
int getRestoreDefaultNetworkDelay(int networkType);
|
int getRestoreDefaultNetworkDelay(int networkType);
|
||||||
|
|
||||||
boolean addVpnAddress(String address, int prefixLength);
|
|
||||||
boolean removeVpnAddress(String address, int prefixLength);
|
|
||||||
boolean setUnderlyingNetworksForVpn(in Network[] networks);
|
|
||||||
|
|
||||||
void factoryReset();
|
void factoryReset();
|
||||||
|
|
||||||
void startNattKeepalive(in Network network, int intervalSeconds,
|
void startNattKeepalive(in Network network, int intervalSeconds,
|
||||||
@@ -223,8 +189,6 @@ interface IConnectivityManager
|
|||||||
byte[] getNetworkWatchlistConfigHash();
|
byte[] getNetworkWatchlistConfigHash();
|
||||||
|
|
||||||
int getConnectionOwnerUid(in ConnectionInfo connectionInfo);
|
int getConnectionOwnerUid(in ConnectionInfo connectionInfo);
|
||||||
boolean isCallerCurrentAlwaysOnVpnApp();
|
|
||||||
boolean isCallerCurrentAlwaysOnVpnLockdownApp();
|
|
||||||
|
|
||||||
void registerConnectivityDiagnosticsCallback(in IConnectivityDiagnosticsCallback callback,
|
void registerConnectivityDiagnosticsCallback(in IConnectivityDiagnosticsCallback callback,
|
||||||
in NetworkRequest request, String callingPackageName);
|
in NetworkRequest request, String callingPackageName);
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import static com.android.internal.util.Preconditions.checkNotNull;
|
|||||||
import android.annotation.IntDef;
|
import android.annotation.IntDef;
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
|
import android.annotation.RequiresPermission;
|
||||||
import android.annotation.UserIdInt;
|
import android.annotation.UserIdInt;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
@@ -37,6 +38,7 @@ import java.io.IOException;
|
|||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class provides an interface for apps to manage platform VPN profiles
|
* This class provides an interface for apps to manage platform VPN profiles
|
||||||
@@ -76,13 +78,19 @@ public class VpnManager {
|
|||||||
@Deprecated
|
@Deprecated
|
||||||
public static final int TYPE_VPN_LEGACY = 3;
|
public static final int TYPE_VPN_LEGACY = 3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Channel for VPN notifications.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static final String NOTIFICATION_CHANNEL_VPN = "VPN";
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
@IntDef(value = {TYPE_VPN_NONE, TYPE_VPN_SERVICE, TYPE_VPN_PLATFORM, TYPE_VPN_LEGACY})
|
@IntDef(value = {TYPE_VPN_NONE, TYPE_VPN_SERVICE, TYPE_VPN_PLATFORM, TYPE_VPN_LEGACY})
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
public @interface VpnType {}
|
public @interface VpnType {}
|
||||||
|
|
||||||
@NonNull private final Context mContext;
|
@NonNull private final Context mContext;
|
||||||
@NonNull private final IConnectivityManager mService;
|
@NonNull private final IVpnManager mService;
|
||||||
|
|
||||||
private static Intent getIntentForConfirmation() {
|
private static Intent getIntentForConfirmation() {
|
||||||
final Intent intent = new Intent();
|
final Intent intent = new Intent();
|
||||||
@@ -101,9 +109,9 @@ public class VpnManager {
|
|||||||
*
|
*
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public VpnManager(@NonNull Context ctx, @NonNull IConnectivityManager service) {
|
public VpnManager(@NonNull Context ctx, @NonNull IVpnManager service) {
|
||||||
mContext = checkNotNull(ctx, "missing Context");
|
mContext = checkNotNull(ctx, "missing Context");
|
||||||
mService = checkNotNull(service, "missing IConnectivityManager");
|
mService = checkNotNull(service, "missing IVpnManager");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -194,6 +202,19 @@ public class VpnManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets all VPN settings back to factory defaults.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
|
||||||
|
public void factoryReset() {
|
||||||
|
try {
|
||||||
|
mService.factoryReset();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
throw e.rethrowFromSystemServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare for a VPN application.
|
* Prepare for a VPN application.
|
||||||
* VPN permissions are checked in the {@link Vpn} class. If the caller is not {@code userId},
|
* VPN permissions are checked in the {@link Vpn} class. If the caller is not {@code userId},
|
||||||
@@ -239,6 +260,108 @@ public class VpnManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a VPN app supports always-on mode.
|
||||||
|
*
|
||||||
|
* In order to support the always-on feature, an app has to
|
||||||
|
* <ul>
|
||||||
|
* <li>target {@link VERSION_CODES#N API 24} or above, and
|
||||||
|
* <li>not opt out through the {@link VpnService#SERVICE_META_DATA_SUPPORTS_ALWAYS_ON}
|
||||||
|
* meta-data field.
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param userId The identifier of the user for whom the VPN app is installed.
|
||||||
|
* @param vpnPackage The canonical package name of the VPN app.
|
||||||
|
* @return {@code true} if and only if the VPN app exists and supports always-on mode.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public boolean isAlwaysOnVpnPackageSupportedForUser(int userId, @Nullable String vpnPackage) {
|
||||||
|
try {
|
||||||
|
return mService.isAlwaysOnVpnPackageSupported(userId, vpnPackage);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
throw e.rethrowFromSystemServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures an always-on VPN connection through a specific application.
|
||||||
|
* This connection is automatically granted and persisted after a reboot.
|
||||||
|
*
|
||||||
|
* <p>The designated package should declare a {@link VpnService} in its
|
||||||
|
* manifest guarded by {@link android.Manifest.permission.BIND_VPN_SERVICE},
|
||||||
|
* otherwise the call will fail.
|
||||||
|
*
|
||||||
|
* @param userId The identifier of the user to set an always-on VPN for.
|
||||||
|
* @param vpnPackage The package name for an installed VPN app on the device, or {@code null}
|
||||||
|
* to remove an existing always-on VPN configuration.
|
||||||
|
* @param lockdownEnabled {@code true} to disallow networking when the VPN is not connected or
|
||||||
|
* {@code false} otherwise.
|
||||||
|
* @param lockdownAllowlist The list of packages that are allowed to access network directly
|
||||||
|
* when VPN is in lockdown mode but is not running. Non-existent packages are ignored so
|
||||||
|
* this method must be called when a package that should be allowed is installed or
|
||||||
|
* uninstalled.
|
||||||
|
* @return {@code true} if the package is set as always-on VPN controller;
|
||||||
|
* {@code false} otherwise.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN)
|
||||||
|
public boolean setAlwaysOnVpnPackageForUser(int userId, @Nullable String vpnPackage,
|
||||||
|
boolean lockdownEnabled, @Nullable List<String> lockdownAllowlist) {
|
||||||
|
try {
|
||||||
|
return mService.setAlwaysOnVpnPackage(
|
||||||
|
userId, vpnPackage, lockdownEnabled, lockdownAllowlist);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
throw e.rethrowFromSystemServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the package name of the currently set always-on VPN application.
|
||||||
|
* If there is no always-on VPN set, or the VPN is provided by the system instead
|
||||||
|
* of by an app, {@code null} will be returned.
|
||||||
|
*
|
||||||
|
* @return Package name of VPN controller responsible for always-on VPN,
|
||||||
|
* or {@code null} if none is set.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN)
|
||||||
|
public String getAlwaysOnVpnPackageForUser(int userId) {
|
||||||
|
try {
|
||||||
|
return mService.getAlwaysOnVpnPackage(userId);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
throw e.rethrowFromSystemServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return whether always-on VPN is in lockdown mode.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
**/
|
||||||
|
@RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN)
|
||||||
|
public boolean isVpnLockdownEnabled(int userId) {
|
||||||
|
try {
|
||||||
|
return mService.isVpnLockdownEnabled(userId);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
throw e.rethrowFromSystemServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the list of packages that are allowed to access network when always-on VPN is in
|
||||||
|
* lockdown mode but not connected. Returns {@code null} when VPN lockdown is not active.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
**/
|
||||||
|
@RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN)
|
||||||
|
public List<String> getVpnLockdownAllowlist(int userId) {
|
||||||
|
try {
|
||||||
|
return mService.getVpnLockdownAllowlist(userId);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
throw e.rethrowFromSystemServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the legacy VPN information for the specified user ID.
|
* Return the legacy VPN information for the specified user ID.
|
||||||
* @hide
|
* @hide
|
||||||
|
|||||||
@@ -170,12 +170,11 @@ public class VpnService extends Service {
|
|||||||
"android.net.VpnService.SUPPORTS_ALWAYS_ON";
|
"android.net.VpnService.SUPPORTS_ALWAYS_ON";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use IConnectivityManager since those methods are hidden and not
|
* Use IVpnManager since those methods are hidden and not available in VpnManager.
|
||||||
* available in ConnectivityManager.
|
|
||||||
*/
|
*/
|
||||||
private static IConnectivityManager getService() {
|
private static IVpnManager getService() {
|
||||||
return IConnectivityManager.Stub.asInterface(
|
return IVpnManager.Stub.asInterface(
|
||||||
ServiceManager.getService(Context.CONNECTIVITY_SERVICE));
|
ServiceManager.getService(Context.VPN_MANAGEMENT_SERVICE));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -226,15 +225,15 @@ public class VpnService extends Service {
|
|||||||
@SystemApi
|
@SystemApi
|
||||||
@RequiresPermission(android.Manifest.permission.CONTROL_VPN)
|
@RequiresPermission(android.Manifest.permission.CONTROL_VPN)
|
||||||
public static void prepareAndAuthorize(Context context) {
|
public static void prepareAndAuthorize(Context context) {
|
||||||
IConnectivityManager cm = getService();
|
IVpnManager vm = getService();
|
||||||
String packageName = context.getPackageName();
|
String packageName = context.getPackageName();
|
||||||
try {
|
try {
|
||||||
// Only prepare if we're not already prepared.
|
// Only prepare if we're not already prepared.
|
||||||
int userId = context.getUserId();
|
int userId = context.getUserId();
|
||||||
if (!cm.prepareVpn(packageName, null, userId)) {
|
if (!vm.prepareVpn(packageName, null, userId)) {
|
||||||
cm.prepareVpn(null, packageName, userId);
|
vm.prepareVpn(null, packageName, userId);
|
||||||
}
|
}
|
||||||
cm.setVpnPackageAuthorization(packageName, userId, VpnManager.TYPE_VPN_SERVICE);
|
vm.setVpnPackageAuthorization(packageName, userId, VpnManager.TYPE_VPN_SERVICE);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -79,7 +79,6 @@ public class NetworkNotificationManager {
|
|||||||
// server.
|
// server.
|
||||||
public static final String NOTIFICATION_CHANNEL_NETWORK_STATUS = "NETWORK_STATUS";
|
public static final String NOTIFICATION_CHANNEL_NETWORK_STATUS = "NETWORK_STATUS";
|
||||||
public static final String NOTIFICATION_CHANNEL_NETWORK_ALERTS = "NETWORK_ALERTS";
|
public static final String NOTIFICATION_CHANNEL_NETWORK_ALERTS = "NETWORK_ALERTS";
|
||||||
public static final String NOTIFICATION_CHANNEL_VPN = "VPN";
|
|
||||||
|
|
||||||
// The context is for the current user (system server)
|
// The context is for the current user (system server)
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ public class VpnManagerTest {
|
|||||||
private static final String IDENTITY_STRING = "Identity";
|
private static final String IDENTITY_STRING = "Identity";
|
||||||
private static final byte[] PSK_BYTES = "preSharedKey".getBytes();
|
private static final byte[] PSK_BYTES = "preSharedKey".getBytes();
|
||||||
|
|
||||||
private IConnectivityManager mMockCs;
|
private IVpnManager mMockService;
|
||||||
private VpnManager mVpnManager;
|
private VpnManager mVpnManager;
|
||||||
private final MockContext mMockContext =
|
private final MockContext mMockContext =
|
||||||
new MockContext() {
|
new MockContext() {
|
||||||
@@ -61,24 +61,26 @@ public class VpnManagerTest {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
mMockCs = mock(IConnectivityManager.class);
|
mMockService = mock(IVpnManager.class);
|
||||||
mVpnManager = new VpnManager(mMockContext, mMockCs);
|
mVpnManager = new VpnManager(mMockContext, mMockService);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testProvisionVpnProfilePreconsented() throws Exception {
|
public void testProvisionVpnProfilePreconsented() throws Exception {
|
||||||
final PlatformVpnProfile profile = getPlatformVpnProfile();
|
final PlatformVpnProfile profile = getPlatformVpnProfile();
|
||||||
when(mMockCs.provisionVpnProfile(any(VpnProfile.class), eq(PKG_NAME))).thenReturn(true);
|
when(mMockService.provisionVpnProfile(any(VpnProfile.class), eq(PKG_NAME)))
|
||||||
|
.thenReturn(true);
|
||||||
|
|
||||||
// Expect there to be no intent returned, as consent has already been granted.
|
// Expect there to be no intent returned, as consent has already been granted.
|
||||||
assertNull(mVpnManager.provisionVpnProfile(profile));
|
assertNull(mVpnManager.provisionVpnProfile(profile));
|
||||||
verify(mMockCs).provisionVpnProfile(eq(profile.toVpnProfile()), eq(PKG_NAME));
|
verify(mMockService).provisionVpnProfile(eq(profile.toVpnProfile()), eq(PKG_NAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testProvisionVpnProfileNeedsConsent() throws Exception {
|
public void testProvisionVpnProfileNeedsConsent() throws Exception {
|
||||||
final PlatformVpnProfile profile = getPlatformVpnProfile();
|
final PlatformVpnProfile profile = getPlatformVpnProfile();
|
||||||
when(mMockCs.provisionVpnProfile(any(VpnProfile.class), eq(PKG_NAME))).thenReturn(false);
|
when(mMockService.provisionVpnProfile(any(VpnProfile.class), eq(PKG_NAME)))
|
||||||
|
.thenReturn(false);
|
||||||
|
|
||||||
// Expect intent to be returned, as consent has not already been granted.
|
// Expect intent to be returned, as consent has not already been granted.
|
||||||
final Intent intent = mVpnManager.provisionVpnProfile(profile);
|
final Intent intent = mVpnManager.provisionVpnProfile(profile);
|
||||||
@@ -88,25 +90,25 @@ public class VpnManagerTest {
|
|||||||
ComponentName.unflattenFromString(
|
ComponentName.unflattenFromString(
|
||||||
"com.android.vpndialogs/com.android.vpndialogs.PlatformVpnConfirmDialog");
|
"com.android.vpndialogs/com.android.vpndialogs.PlatformVpnConfirmDialog");
|
||||||
assertEquals(expectedComponentName, intent.getComponent());
|
assertEquals(expectedComponentName, intent.getComponent());
|
||||||
verify(mMockCs).provisionVpnProfile(eq(profile.toVpnProfile()), eq(PKG_NAME));
|
verify(mMockService).provisionVpnProfile(eq(profile.toVpnProfile()), eq(PKG_NAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDeleteProvisionedVpnProfile() throws Exception {
|
public void testDeleteProvisionedVpnProfile() throws Exception {
|
||||||
mVpnManager.deleteProvisionedVpnProfile();
|
mVpnManager.deleteProvisionedVpnProfile();
|
||||||
verify(mMockCs).deleteVpnProfile(eq(PKG_NAME));
|
verify(mMockService).deleteVpnProfile(eq(PKG_NAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStartProvisionedVpnProfile() throws Exception {
|
public void testStartProvisionedVpnProfile() throws Exception {
|
||||||
mVpnManager.startProvisionedVpnProfile();
|
mVpnManager.startProvisionedVpnProfile();
|
||||||
verify(mMockCs).startVpnProfile(eq(PKG_NAME));
|
verify(mMockService).startVpnProfile(eq(PKG_NAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStopProvisionedVpnProfile() throws Exception {
|
public void testStopProvisionedVpnProfile() throws Exception {
|
||||||
mVpnManager.stopProvisionedVpnProfile();
|
mVpnManager.stopProvisionedVpnProfile();
|
||||||
verify(mMockCs).stopVpnProfile(eq(PKG_NAME));
|
verify(mMockService).stopVpnProfile(eq(PKG_NAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Ikev2VpnProfile getPlatformVpnProfile() throws Exception {
|
private Ikev2VpnProfile getPlatformVpnProfile() throws Exception {
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
package android.net;
|
package android.net;
|
||||||
|
|
||||||
import static com.android.testutils.ParcelUtils.assertParcelSane;
|
import static com.android.testutils.ParcelUtils.assertParcelSane;
|
||||||
import static com.android.testutils.ParcelUtils.assertParcelingIsLossless;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotEquals;
|
import static org.junit.Assert.assertNotEquals;
|
||||||
@@ -36,7 +35,6 @@ public class VpnTransportInfoTest {
|
|||||||
public void testParceling() {
|
public void testParceling() {
|
||||||
VpnTransportInfo v = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM);
|
VpnTransportInfo v = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM);
|
||||||
assertParcelSane(v, 1 /* fieldCount */);
|
assertParcelSane(v, 1 /* fieldCount */);
|
||||||
assertParcelingIsLossless(v);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -200,6 +200,7 @@ import android.net.ResolverParamsParcel;
|
|||||||
import android.net.RouteInfo;
|
import android.net.RouteInfo;
|
||||||
import android.net.RouteInfoParcel;
|
import android.net.RouteInfoParcel;
|
||||||
import android.net.SocketKeepalive;
|
import android.net.SocketKeepalive;
|
||||||
|
import android.net.TransportInfo;
|
||||||
import android.net.UidRange;
|
import android.net.UidRange;
|
||||||
import android.net.UidRangeParcel;
|
import android.net.UidRangeParcel;
|
||||||
import android.net.UnderlyingNetworkInfo;
|
import android.net.UnderlyingNetworkInfo;
|
||||||
@@ -376,6 +377,7 @@ public class ConnectivityServiceTest {
|
|||||||
|
|
||||||
private MockContext mServiceContext;
|
private MockContext mServiceContext;
|
||||||
private HandlerThread mCsHandlerThread;
|
private HandlerThread mCsHandlerThread;
|
||||||
|
private HandlerThread mVMSHandlerThread;
|
||||||
private ConnectivityService.Dependencies mDeps;
|
private ConnectivityService.Dependencies mDeps;
|
||||||
private ConnectivityService mService;
|
private ConnectivityService mService;
|
||||||
private WrappedConnectivityManager mCm;
|
private WrappedConnectivityManager mCm;
|
||||||
@@ -390,6 +392,7 @@ public class ConnectivityServiceTest {
|
|||||||
private TestNetIdManager mNetIdManager;
|
private TestNetIdManager mNetIdManager;
|
||||||
private QosCallbackMockHelper mQosCallbackMockHelper;
|
private QosCallbackMockHelper mQosCallbackMockHelper;
|
||||||
private QosCallbackTracker mQosCallbackTracker;
|
private QosCallbackTracker mQosCallbackTracker;
|
||||||
|
private VpnManagerService mVpnManagerService;
|
||||||
|
|
||||||
// State variables required to emulate NetworkPolicyManagerService behaviour.
|
// State variables required to emulate NetworkPolicyManagerService behaviour.
|
||||||
private int mUidRules = RULE_NONE;
|
private int mUidRules = RULE_NONE;
|
||||||
@@ -1262,24 +1265,57 @@ public class ConnectivityServiceTest {
|
|||||||
r -> new UidRangeParcel(r.start, r.stop)).toArray(UidRangeParcel[]::new);
|
r -> new UidRangeParcel(r.start, r.stop)).toArray(UidRangeParcel[]::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void mockVpn(int uid) {
|
private VpnManagerService makeVpnManagerService() {
|
||||||
synchronized (mService.mVpns) {
|
final VpnManagerService.Dependencies deps = new VpnManagerService.Dependencies() {
|
||||||
int userId = UserHandle.getUserId(uid);
|
public int getCallingUid() {
|
||||||
mMockVpn = new MockVpn(userId);
|
return mDeps.getCallingUid();
|
||||||
// This has no effect unless the VPN is actually connected, because things like
|
}
|
||||||
// getActiveNetworkForUidInternal call getNetworkAgentInfoForNetId on the VPN
|
|
||||||
// netId, and check if that network is actually connected.
|
public HandlerThread makeHandlerThread() {
|
||||||
mService.mVpns.put(userId, mMockVpn);
|
return mVMSHandlerThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public KeyStore getKeyStore() {
|
||||||
|
return mKeyStore;
|
||||||
|
}
|
||||||
|
|
||||||
|
public INetd getNetd() {
|
||||||
|
return mMockNetd;
|
||||||
|
}
|
||||||
|
|
||||||
|
public INetworkManagementService getINetworkManagementService() {
|
||||||
|
return mNetworkManagementService;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return new VpnManagerService(mServiceContext, deps);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertVpnTransportInfo(NetworkCapabilities nc, int type) {
|
||||||
|
assertNotNull(nc);
|
||||||
|
final TransportInfo ti = nc.getTransportInfo();
|
||||||
|
assertTrue("VPN TransportInfo is not a VpnTransportInfo: " + ti,
|
||||||
|
ti instanceof VpnTransportInfo);
|
||||||
|
assertEquals(type, ((VpnTransportInfo) ti).type);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processBroadcastForVpn(Intent intent) {
|
private void processBroadcastForVpn(Intent intent) {
|
||||||
// The BroadcastReceiver for this broadcast checks it is being run on the handler thread.
|
// The BroadcastReceiver for this broadcast checks it is being run on the handler thread.
|
||||||
final Handler handler = new Handler(mCsHandlerThread.getLooper());
|
final Handler handler = new Handler(mVMSHandlerThread.getLooper());
|
||||||
handler.post(() -> mServiceContext.sendBroadcast(intent));
|
handler.post(() -> mServiceContext.sendBroadcast(intent));
|
||||||
|
HandlerUtils.waitForIdle(handler, TIMEOUT_MS);
|
||||||
waitForIdle();
|
waitForIdle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void mockVpn(int uid) {
|
||||||
|
synchronized (mVpnManagerService.mVpns) {
|
||||||
|
int userId = UserHandle.getUserId(uid);
|
||||||
|
mMockVpn = new MockVpn(userId);
|
||||||
|
// Every running user always has a Vpn in the mVpns array, even if no VPN is running.
|
||||||
|
mVpnManagerService.mVpns.put(userId, mMockVpn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void mockUidNetworkingBlocked() {
|
private void mockUidNetworkingBlocked() {
|
||||||
doAnswer(i -> mContext.getSystemService(NetworkPolicyManager.class)
|
doAnswer(i -> mContext.getSystemService(NetworkPolicyManager.class)
|
||||||
.checkUidNetworkingBlocked(i.getArgument(0) /* uid */, mUidRules,
|
.checkUidNetworkingBlocked(i.getArgument(0) /* uid */, mUidRules,
|
||||||
@@ -1403,6 +1439,7 @@ public class ConnectivityServiceTest {
|
|||||||
initAlarmManager(mAlarmManager, mAlarmManagerThread.getThreadHandler());
|
initAlarmManager(mAlarmManager, mAlarmManagerThread.getThreadHandler());
|
||||||
|
|
||||||
mCsHandlerThread = new HandlerThread("TestConnectivityService");
|
mCsHandlerThread = new HandlerThread("TestConnectivityService");
|
||||||
|
mVMSHandlerThread = new HandlerThread("TestVpnManagerService");
|
||||||
mDeps = makeDependencies();
|
mDeps = makeDependencies();
|
||||||
returnRealCallingUid();
|
returnRealCallingUid();
|
||||||
mService = new ConnectivityService(mServiceContext,
|
mService = new ConnectivityService(mServiceContext,
|
||||||
@@ -1425,6 +1462,8 @@ public class ConnectivityServiceTest {
|
|||||||
// getSystemService() correctly.
|
// getSystemService() correctly.
|
||||||
mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
|
mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
|
||||||
mService.systemReadyInternal();
|
mService.systemReadyInternal();
|
||||||
|
mVpnManagerService = makeVpnManagerService();
|
||||||
|
mVpnManagerService.systemReady();
|
||||||
mockVpn(Process.myUid());
|
mockVpn(Process.myUid());
|
||||||
mCm.bindProcessToNetwork(null);
|
mCm.bindProcessToNetwork(null);
|
||||||
mQosCallbackTracker = mock(QosCallbackTracker.class);
|
mQosCallbackTracker = mock(QosCallbackTracker.class);
|
||||||
@@ -1452,7 +1491,6 @@ public class ConnectivityServiceTest {
|
|||||||
doReturn(mock(ProxyTracker.class)).when(deps).makeProxyTracker(any(), any());
|
doReturn(mock(ProxyTracker.class)).when(deps).makeProxyTracker(any(), any());
|
||||||
doReturn(true).when(deps).queryUserAccess(anyInt(), anyInt());
|
doReturn(true).when(deps).queryUserAccess(anyInt(), anyInt());
|
||||||
doReturn(mBatteryStatsService).when(deps).getBatteryStatsService();
|
doReturn(mBatteryStatsService).when(deps).getBatteryStatsService();
|
||||||
doReturn(mKeyStore).when(deps).getKeyStore();
|
|
||||||
doAnswer(inv -> {
|
doAnswer(inv -> {
|
||||||
mPolicyTracker = new WrappedMultinetworkPolicyTracker(
|
mPolicyTracker = new WrappedMultinetworkPolicyTracker(
|
||||||
inv.getArgument(0), inv.getArgument(1), inv.getArgument(2));
|
inv.getArgument(0), inv.getArgument(1), inv.getArgument(2));
|
||||||
@@ -3873,6 +3911,24 @@ public class ConnectivityServiceTest {
|
|||||||
mCm.unregisterNetworkCallback(cellNetworkCallback);
|
mCm.unregisterNetworkCallback(cellNetworkCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRegisterSystemDefaultCallbackRequiresNetworkSettings() throws Exception {
|
||||||
|
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
|
||||||
|
mCellNetworkAgent.connect(false /* validated */);
|
||||||
|
|
||||||
|
final Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
|
||||||
|
final TestNetworkCallback callback = new TestNetworkCallback();
|
||||||
|
assertThrows(SecurityException.class,
|
||||||
|
() -> mCm.registerSystemDefaultNetworkCallback(callback, handler));
|
||||||
|
callback.assertNoCallback();
|
||||||
|
|
||||||
|
mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS,
|
||||||
|
PERMISSION_GRANTED);
|
||||||
|
mCm.registerSystemDefaultNetworkCallback(callback, handler);
|
||||||
|
callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
|
||||||
|
mCm.unregisterNetworkCallback(callback);
|
||||||
|
}
|
||||||
|
|
||||||
private void setCaptivePortalMode(int mode) {
|
private void setCaptivePortalMode(int mode) {
|
||||||
ContentResolver cr = mServiceContext.getContentResolver();
|
ContentResolver cr = mServiceContext.getContentResolver();
|
||||||
Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
|
Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
|
||||||
@@ -6484,6 +6540,8 @@ public class ConnectivityServiceTest {
|
|||||||
assertTrue(nc.hasCapability(NET_CAPABILITY_VALIDATED));
|
assertTrue(nc.hasCapability(NET_CAPABILITY_VALIDATED));
|
||||||
assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
|
assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
|
||||||
assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
|
assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
|
||||||
|
|
||||||
|
assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertDefaultNetworkCapabilities(int userId, NetworkAgentWrapper... networks) {
|
private void assertDefaultNetworkCapabilities(int userId, NetworkAgentWrapper... networks) {
|
||||||
@@ -6523,6 +6581,7 @@ public class ConnectivityServiceTest {
|
|||||||
assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
|
assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
|
||||||
// A VPN without underlying networks is not suspended.
|
// A VPN without underlying networks is not suspended.
|
||||||
assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
|
assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
|
||||||
|
assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE);
|
||||||
|
|
||||||
final int userId = UserHandle.getUserId(Process.myUid());
|
final int userId = UserHandle.getUserId(Process.myUid());
|
||||||
assertDefaultNetworkCapabilities(userId /* no networks */);
|
assertDefaultNetworkCapabilities(userId /* no networks */);
|
||||||
@@ -6686,6 +6745,7 @@ public class ConnectivityServiceTest {
|
|||||||
// By default, VPN is set to track default network (i.e. its underlying networks is null).
|
// By default, VPN is set to track default network (i.e. its underlying networks is null).
|
||||||
// In case of no default network, VPN is considered metered.
|
// In case of no default network, VPN is considered metered.
|
||||||
assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
|
assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
|
||||||
|
assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE);
|
||||||
|
|
||||||
// Connect to Cell; Cell is the default network.
|
// Connect to Cell; Cell is the default network.
|
||||||
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
|
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
|
||||||
@@ -6743,6 +6803,7 @@ public class ConnectivityServiceTest {
|
|||||||
NetworkCapabilities nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
|
NetworkCapabilities nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
|
||||||
assertNotNull("nc=" + nc, nc.getUids());
|
assertNotNull("nc=" + nc, nc.getUids());
|
||||||
assertEquals(nc.getUids(), uidRangesForUid(uid));
|
assertEquals(nc.getUids(), uidRangesForUid(uid));
|
||||||
|
assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE);
|
||||||
|
|
||||||
// Set an underlying network and expect to see the VPN transports change.
|
// Set an underlying network and expect to see the VPN transports change.
|
||||||
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
|
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
|
||||||
@@ -6825,8 +6886,8 @@ public class ConnectivityServiceTest {
|
|||||||
|
|
||||||
// Enable always-on VPN lockdown. The main user loses network access because no VPN is up.
|
// Enable always-on VPN lockdown. The main user loses network access because no VPN is up.
|
||||||
final ArrayList<String> allowList = new ArrayList<>();
|
final ArrayList<String> allowList = new ArrayList<>();
|
||||||
mService.setAlwaysOnVpnPackage(PRIMARY_USER, ALWAYS_ON_PACKAGE, true /* lockdown */,
|
mVpnManagerService.setAlwaysOnVpnPackage(PRIMARY_USER, ALWAYS_ON_PACKAGE,
|
||||||
allowList);
|
true /* lockdown */, allowList);
|
||||||
waitForIdle();
|
waitForIdle();
|
||||||
assertNull(mCm.getActiveNetworkForUid(uid));
|
assertNull(mCm.getActiveNetworkForUid(uid));
|
||||||
// This is arguably overspecified: a UID that is not running doesn't have an active network.
|
// This is arguably overspecified: a UID that is not running doesn't have an active network.
|
||||||
@@ -6856,7 +6917,8 @@ public class ConnectivityServiceTest {
|
|||||||
assertNull(mCm.getActiveNetworkForUid(uid));
|
assertNull(mCm.getActiveNetworkForUid(uid));
|
||||||
assertNotNull(mCm.getActiveNetworkForUid(restrictedUid));
|
assertNotNull(mCm.getActiveNetworkForUid(restrictedUid));
|
||||||
|
|
||||||
mService.setAlwaysOnVpnPackage(PRIMARY_USER, null, false /* lockdown */, allowList);
|
mVpnManagerService.setAlwaysOnVpnPackage(PRIMARY_USER, null, false /* lockdown */,
|
||||||
|
allowList);
|
||||||
waitForIdle();
|
waitForIdle();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7232,7 +7294,8 @@ public class ConnectivityServiceTest {
|
|||||||
final int uid = Process.myUid();
|
final int uid = Process.myUid();
|
||||||
final int userId = UserHandle.getUserId(uid);
|
final int userId = UserHandle.getUserId(uid);
|
||||||
final ArrayList<String> allowList = new ArrayList<>();
|
final ArrayList<String> allowList = new ArrayList<>();
|
||||||
mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, allowList);
|
mVpnManagerService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */,
|
||||||
|
allowList);
|
||||||
waitForIdle();
|
waitForIdle();
|
||||||
|
|
||||||
UidRangeParcel firstHalf = new UidRangeParcel(1, VPN_UID - 1);
|
UidRangeParcel firstHalf = new UidRangeParcel(1, VPN_UID - 1);
|
||||||
@@ -7254,7 +7317,7 @@ public class ConnectivityServiceTest {
|
|||||||
assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
|
assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
|
||||||
|
|
||||||
// Disable lockdown, expect to see the network unblocked.
|
// Disable lockdown, expect to see the network unblocked.
|
||||||
mService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList);
|
mVpnManagerService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList);
|
||||||
callback.expectBlockedStatusCallback(false, mWiFiNetworkAgent);
|
callback.expectBlockedStatusCallback(false, mWiFiNetworkAgent);
|
||||||
defaultCallback.expectBlockedStatusCallback(false, mWiFiNetworkAgent);
|
defaultCallback.expectBlockedStatusCallback(false, mWiFiNetworkAgent);
|
||||||
vpnUidCallback.assertNoCallback();
|
vpnUidCallback.assertNoCallback();
|
||||||
@@ -7267,7 +7330,8 @@ public class ConnectivityServiceTest {
|
|||||||
|
|
||||||
// Add our UID to the allowlist and re-enable lockdown, expect network is not blocked.
|
// Add our UID to the allowlist and re-enable lockdown, expect network is not blocked.
|
||||||
allowList.add(TEST_PACKAGE_NAME);
|
allowList.add(TEST_PACKAGE_NAME);
|
||||||
mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, allowList);
|
mVpnManagerService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */,
|
||||||
|
allowList);
|
||||||
callback.assertNoCallback();
|
callback.assertNoCallback();
|
||||||
defaultCallback.assertNoCallback();
|
defaultCallback.assertNoCallback();
|
||||||
vpnUidCallback.assertNoCallback();
|
vpnUidCallback.assertNoCallback();
|
||||||
@@ -7300,11 +7364,12 @@ public class ConnectivityServiceTest {
|
|||||||
|
|
||||||
// Disable lockdown, remove our UID from the allowlist, and re-enable lockdown.
|
// Disable lockdown, remove our UID from the allowlist, and re-enable lockdown.
|
||||||
// Everything should now be blocked.
|
// Everything should now be blocked.
|
||||||
mService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList);
|
mVpnManagerService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList);
|
||||||
waitForIdle();
|
waitForIdle();
|
||||||
expectNetworkRejectNonSecureVpn(inOrder, false, piece1, piece2, piece3);
|
expectNetworkRejectNonSecureVpn(inOrder, false, piece1, piece2, piece3);
|
||||||
allowList.clear();
|
allowList.clear();
|
||||||
mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, allowList);
|
mVpnManagerService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */,
|
||||||
|
allowList);
|
||||||
waitForIdle();
|
waitForIdle();
|
||||||
expectNetworkRejectNonSecureVpn(inOrder, true, firstHalf, secondHalf);
|
expectNetworkRejectNonSecureVpn(inOrder, true, firstHalf, secondHalf);
|
||||||
defaultCallback.expectBlockedStatusCallback(true, mWiFiNetworkAgent);
|
defaultCallback.expectBlockedStatusCallback(true, mWiFiNetworkAgent);
|
||||||
@@ -7317,7 +7382,7 @@ public class ConnectivityServiceTest {
|
|||||||
assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
|
assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
|
||||||
|
|
||||||
// Disable lockdown. Everything is unblocked.
|
// Disable lockdown. Everything is unblocked.
|
||||||
mService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList);
|
mVpnManagerService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList);
|
||||||
defaultCallback.expectBlockedStatusCallback(false, mWiFiNetworkAgent);
|
defaultCallback.expectBlockedStatusCallback(false, mWiFiNetworkAgent);
|
||||||
assertBlockedCallbackInAnyOrder(callback, false, mWiFiNetworkAgent, mCellNetworkAgent);
|
assertBlockedCallbackInAnyOrder(callback, false, mWiFiNetworkAgent, mCellNetworkAgent);
|
||||||
vpnUidCallback.assertNoCallback();
|
vpnUidCallback.assertNoCallback();
|
||||||
@@ -7329,7 +7394,8 @@ public class ConnectivityServiceTest {
|
|||||||
|
|
||||||
// Enable and disable an always-on VPN package without lockdown. Expect no changes.
|
// Enable and disable an always-on VPN package without lockdown. Expect no changes.
|
||||||
reset(mMockNetd);
|
reset(mMockNetd);
|
||||||
mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, false /* lockdown */, allowList);
|
mVpnManagerService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, false /* lockdown */,
|
||||||
|
allowList);
|
||||||
inOrder.verify(mMockNetd, never()).networkRejectNonSecureVpn(anyBoolean(), any());
|
inOrder.verify(mMockNetd, never()).networkRejectNonSecureVpn(anyBoolean(), any());
|
||||||
callback.assertNoCallback();
|
callback.assertNoCallback();
|
||||||
defaultCallback.assertNoCallback();
|
defaultCallback.assertNoCallback();
|
||||||
@@ -7340,7 +7406,7 @@ public class ConnectivityServiceTest {
|
|||||||
assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
|
assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
|
||||||
assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
|
assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
|
||||||
|
|
||||||
mService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList);
|
mVpnManagerService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList);
|
||||||
inOrder.verify(mMockNetd, never()).networkRejectNonSecureVpn(anyBoolean(), any());
|
inOrder.verify(mMockNetd, never()).networkRejectNonSecureVpn(anyBoolean(), any());
|
||||||
callback.assertNoCallback();
|
callback.assertNoCallback();
|
||||||
defaultCallback.assertNoCallback();
|
defaultCallback.assertNoCallback();
|
||||||
@@ -7352,7 +7418,8 @@ public class ConnectivityServiceTest {
|
|||||||
assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
|
assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
|
||||||
|
|
||||||
// Enable lockdown and connect a VPN. The VPN is not blocked.
|
// Enable lockdown and connect a VPN. The VPN is not blocked.
|
||||||
mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, allowList);
|
mVpnManagerService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */,
|
||||||
|
allowList);
|
||||||
defaultCallback.expectBlockedStatusCallback(true, mWiFiNetworkAgent);
|
defaultCallback.expectBlockedStatusCallback(true, mWiFiNetworkAgent);
|
||||||
assertBlockedCallbackInAnyOrder(callback, true, mWiFiNetworkAgent, mCellNetworkAgent);
|
assertBlockedCallbackInAnyOrder(callback, true, mWiFiNetworkAgent, mCellNetworkAgent);
|
||||||
vpnUidCallback.assertNoCallback();
|
vpnUidCallback.assertNoCallback();
|
||||||
@@ -7398,11 +7465,14 @@ public class ConnectivityServiceTest {
|
|||||||
when(mKeyStore.get(Credentials.VPN + profileName)).thenReturn(encodedProfile);
|
when(mKeyStore.get(Credentials.VPN + profileName)).thenReturn(encodedProfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void establishLegacyLockdownVpn() throws Exception {
|
private void establishLegacyLockdownVpn(Network underlying) throws Exception {
|
||||||
|
// The legacy lockdown VPN only supports userId 0, and must have an underlying network.
|
||||||
|
assertNotNull(underlying);
|
||||||
mMockVpn.setVpnType(VpnManager.TYPE_VPN_LEGACY);
|
mMockVpn.setVpnType(VpnManager.TYPE_VPN_LEGACY);
|
||||||
// The legacy lockdown VPN only supports userId 0.
|
// The legacy lockdown VPN only supports userId 0.
|
||||||
final Set<UidRange> ranges = Collections.singleton(UidRange.createForUser(PRIMARY_USER));
|
final Set<UidRange> ranges = Collections.singleton(UidRange.createForUser(PRIMARY_USER));
|
||||||
mMockVpn.registerAgent(ranges);
|
mMockVpn.registerAgent(ranges);
|
||||||
|
mMockVpn.setUnderlyingNetworks(new Network[]{underlying});
|
||||||
mMockVpn.connect(true);
|
mMockVpn.connect(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7410,6 +7480,9 @@ public class ConnectivityServiceTest {
|
|||||||
public void testLegacyLockdownVpn() throws Exception {
|
public void testLegacyLockdownVpn() throws Exception {
|
||||||
mServiceContext.setPermission(
|
mServiceContext.setPermission(
|
||||||
Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED);
|
Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED);
|
||||||
|
// For LockdownVpnTracker to call registerSystemDefaultNetworkCallback.
|
||||||
|
mServiceContext.setPermission(
|
||||||
|
Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED);
|
||||||
|
|
||||||
final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
|
final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
|
||||||
final TestNetworkCallback callback = new TestNetworkCallback();
|
final TestNetworkCallback callback = new TestNetworkCallback();
|
||||||
@@ -7418,6 +7491,10 @@ public class ConnectivityServiceTest {
|
|||||||
final TestNetworkCallback defaultCallback = new TestNetworkCallback();
|
final TestNetworkCallback defaultCallback = new TestNetworkCallback();
|
||||||
mCm.registerDefaultNetworkCallback(defaultCallback);
|
mCm.registerDefaultNetworkCallback(defaultCallback);
|
||||||
|
|
||||||
|
final TestNetworkCallback systemDefaultCallback = new TestNetworkCallback();
|
||||||
|
mCm.registerSystemDefaultNetworkCallback(systemDefaultCallback,
|
||||||
|
new Handler(ConnectivityThread.getInstanceLooper()));
|
||||||
|
|
||||||
// Pretend lockdown VPN was configured.
|
// Pretend lockdown VPN was configured.
|
||||||
setupLegacyLockdownVpn();
|
setupLegacyLockdownVpn();
|
||||||
|
|
||||||
@@ -7447,6 +7524,7 @@ public class ConnectivityServiceTest {
|
|||||||
mCellNetworkAgent.connect(false /* validated */);
|
mCellNetworkAgent.connect(false /* validated */);
|
||||||
callback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
|
callback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
|
||||||
defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
|
defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
|
||||||
|
systemDefaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
|
||||||
waitForIdle();
|
waitForIdle();
|
||||||
assertNull(mMockVpn.getAgent());
|
assertNull(mMockVpn.getAgent());
|
||||||
|
|
||||||
@@ -7458,6 +7536,8 @@ public class ConnectivityServiceTest {
|
|||||||
mCellNetworkAgent.sendLinkProperties(cellLp);
|
mCellNetworkAgent.sendLinkProperties(cellLp);
|
||||||
callback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
|
callback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
|
||||||
defaultCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
|
defaultCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
|
||||||
|
systemDefaultCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED,
|
||||||
|
mCellNetworkAgent);
|
||||||
waitForIdle();
|
waitForIdle();
|
||||||
assertNull(mMockVpn.getAgent());
|
assertNull(mMockVpn.getAgent());
|
||||||
|
|
||||||
@@ -7467,6 +7547,7 @@ public class ConnectivityServiceTest {
|
|||||||
mCellNetworkAgent.disconnect();
|
mCellNetworkAgent.disconnect();
|
||||||
callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
|
callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
|
||||||
defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
|
defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
|
||||||
|
systemDefaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
|
||||||
b1.expectBroadcast();
|
b1.expectBroadcast();
|
||||||
|
|
||||||
// When lockdown VPN is active, the NetworkInfo state in CONNECTIVITY_ACTION is overwritten
|
// When lockdown VPN is active, the NetworkInfo state in CONNECTIVITY_ACTION is overwritten
|
||||||
@@ -7476,6 +7557,7 @@ public class ConnectivityServiceTest {
|
|||||||
mCellNetworkAgent.connect(false /* validated */);
|
mCellNetworkAgent.connect(false /* validated */);
|
||||||
callback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
|
callback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
|
||||||
defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
|
defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
|
||||||
|
systemDefaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
|
||||||
b1.expectBroadcast();
|
b1.expectBroadcast();
|
||||||
assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
|
assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
|
||||||
assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
|
assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
|
||||||
@@ -7498,9 +7580,10 @@ public class ConnectivityServiceTest {
|
|||||||
mMockVpn.expectStartLegacyVpnRunner();
|
mMockVpn.expectStartLegacyVpnRunner();
|
||||||
b1 = expectConnectivityAction(TYPE_VPN, DetailedState.CONNECTED);
|
b1 = expectConnectivityAction(TYPE_VPN, DetailedState.CONNECTED);
|
||||||
ExpectedBroadcast b2 = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
|
ExpectedBroadcast b2 = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
|
||||||
establishLegacyLockdownVpn();
|
establishLegacyLockdownVpn(mCellNetworkAgent.getNetwork());
|
||||||
callback.expectAvailableThenValidatedCallbacks(mMockVpn);
|
callback.expectAvailableThenValidatedCallbacks(mMockVpn);
|
||||||
defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
|
defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
|
||||||
|
systemDefaultCallback.assertNoCallback();
|
||||||
NetworkCapabilities vpnNc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
|
NetworkCapabilities vpnNc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
|
||||||
b1.expectBroadcast();
|
b1.expectBroadcast();
|
||||||
b2.expectBroadcast();
|
b2.expectBroadcast();
|
||||||
@@ -7512,9 +7595,7 @@ public class ConnectivityServiceTest {
|
|||||||
assertTrue(vpnNc.hasTransport(TRANSPORT_CELLULAR));
|
assertTrue(vpnNc.hasTransport(TRANSPORT_CELLULAR));
|
||||||
assertFalse(vpnNc.hasTransport(TRANSPORT_WIFI));
|
assertFalse(vpnNc.hasTransport(TRANSPORT_WIFI));
|
||||||
assertFalse(vpnNc.hasCapability(NET_CAPABILITY_NOT_METERED));
|
assertFalse(vpnNc.hasCapability(NET_CAPABILITY_NOT_METERED));
|
||||||
VpnTransportInfo ti = (VpnTransportInfo) vpnNc.getTransportInfo();
|
assertVpnTransportInfo(vpnNc, VpnManager.TYPE_VPN_LEGACY);
|
||||||
assertNotNull(ti);
|
|
||||||
assertEquals(VpnManager.TYPE_VPN_LEGACY, ti.type);
|
|
||||||
|
|
||||||
// Switch default network from cell to wifi. Expect VPN to disconnect and reconnect.
|
// Switch default network from cell to wifi. Expect VPN to disconnect and reconnect.
|
||||||
final LinkProperties wifiLp = new LinkProperties();
|
final LinkProperties wifiLp = new LinkProperties();
|
||||||
@@ -7542,11 +7623,10 @@ public class ConnectivityServiceTest {
|
|||||||
// fact that a VPN is connected should only result in the VPN itself being unblocked, not
|
// fact that a VPN is connected should only result in the VPN itself being unblocked, not
|
||||||
// any other network. Bug in isUidBlockedByVpn?
|
// any other network. Bug in isUidBlockedByVpn?
|
||||||
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
|
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
|
||||||
callback.expectCapabilitiesThat(mMockVpn, nc -> nc.hasTransport(TRANSPORT_WIFI));
|
|
||||||
callback.expectCallback(CallbackEntry.LOST, mMockVpn);
|
callback.expectCallback(CallbackEntry.LOST, mMockVpn);
|
||||||
defaultCallback.expectCapabilitiesThat(mMockVpn, nc -> nc.hasTransport(TRANSPORT_WIFI));
|
|
||||||
defaultCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
|
defaultCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
|
||||||
defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent);
|
defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent);
|
||||||
|
systemDefaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
|
||||||
|
|
||||||
// While the VPN is reconnecting on the new network, everything is blocked.
|
// While the VPN is reconnecting on the new network, everything is blocked.
|
||||||
assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
|
assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
|
||||||
@@ -7557,9 +7637,10 @@ public class ConnectivityServiceTest {
|
|||||||
// The VPN comes up again on wifi.
|
// The VPN comes up again on wifi.
|
||||||
b1 = expectConnectivityAction(TYPE_VPN, DetailedState.CONNECTED);
|
b1 = expectConnectivityAction(TYPE_VPN, DetailedState.CONNECTED);
|
||||||
b2 = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
|
b2 = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
|
||||||
establishLegacyLockdownVpn();
|
establishLegacyLockdownVpn(mWiFiNetworkAgent.getNetwork());
|
||||||
callback.expectAvailableThenValidatedCallbacks(mMockVpn);
|
callback.expectAvailableThenValidatedCallbacks(mMockVpn);
|
||||||
defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
|
defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
|
||||||
|
systemDefaultCallback.assertNoCallback();
|
||||||
b1.expectBroadcast();
|
b1.expectBroadcast();
|
||||||
b2.expectBroadcast();
|
b2.expectBroadcast();
|
||||||
assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
|
assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
|
||||||
@@ -7573,14 +7654,10 @@ public class ConnectivityServiceTest {
|
|||||||
assertTrue(vpnNc.hasCapability(NET_CAPABILITY_NOT_METERED));
|
assertTrue(vpnNc.hasCapability(NET_CAPABILITY_NOT_METERED));
|
||||||
|
|
||||||
// Disconnect cell. Nothing much happens since it's not the default network.
|
// Disconnect cell. Nothing much happens since it's not the default network.
|
||||||
// Whenever LockdownVpnTracker is connected, it will send a connected broadcast any time any
|
|
||||||
// NetworkInfo is updated. This is probably a bug.
|
|
||||||
// TODO: consider fixing this.
|
|
||||||
b1 = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
|
|
||||||
mCellNetworkAgent.disconnect();
|
mCellNetworkAgent.disconnect();
|
||||||
b1.expectBroadcast();
|
|
||||||
callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
|
callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
|
||||||
defaultCallback.assertNoCallback();
|
defaultCallback.assertNoCallback();
|
||||||
|
systemDefaultCallback.assertNoCallback();
|
||||||
|
|
||||||
assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
|
assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
|
||||||
assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
|
assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
|
||||||
@@ -7590,6 +7667,7 @@ public class ConnectivityServiceTest {
|
|||||||
b1 = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED);
|
b1 = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED);
|
||||||
mWiFiNetworkAgent.disconnect();
|
mWiFiNetworkAgent.disconnect();
|
||||||
callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
|
callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
|
||||||
|
systemDefaultCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
|
||||||
b1.expectBroadcast();
|
b1.expectBroadcast();
|
||||||
callback.expectCapabilitiesThat(mMockVpn, nc -> !nc.hasTransport(TRANSPORT_WIFI));
|
callback.expectCapabilitiesThat(mMockVpn, nc -> !nc.hasTransport(TRANSPORT_WIFI));
|
||||||
b2 = expectConnectivityAction(TYPE_VPN, DetailedState.DISCONNECTED);
|
b2 = expectConnectivityAction(TYPE_VPN, DetailedState.DISCONNECTED);
|
||||||
|
|||||||
Reference in New Issue
Block a user