Merge changes Ic5a3e169,I76daa3ab am: 8ca385688d am: 88f10e63bb
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1512888 Change-Id: I1c4f486278a022b439a10bc65e5971ec8684a6de
This commit is contained in:
@@ -41,6 +41,7 @@ import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID;
|
|||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
|
||||||
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
|
||||||
@@ -6354,18 +6355,71 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
nai.declaredMetered = !nc.hasCapability(NET_CAPABILITY_NOT_METERED);
|
nai.declaredMetered = !nc.hasCapability(NET_CAPABILITY_NOT_METERED);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Propagates to |nc| the capabilities declared by the underlying networks of |nai|. */
|
/** Modifies |caps| based on the capabilities of the specified underlying networks. */
|
||||||
private void mixInUnderlyingCapabilities(NetworkAgentInfo nai, NetworkCapabilities nc) {
|
@VisibleForTesting
|
||||||
Network[] underlyingNetworks = nai.declaredUnderlyingNetworks;
|
void applyUnderlyingCapabilities(@Nullable Network[] underlyingNetworks,
|
||||||
Network defaultNetwork = getNetwork(getDefaultNetwork());
|
@NonNull NetworkCapabilities caps, boolean declaredMetered) {
|
||||||
|
final Network defaultNetwork = getNetwork(getDefaultNetwork());
|
||||||
if (underlyingNetworks == null && defaultNetwork != null) {
|
if (underlyingNetworks == null && defaultNetwork != null) {
|
||||||
// null underlying networks means to track the default.
|
// null underlying networks means to track the default.
|
||||||
underlyingNetworks = new Network[] { defaultNetwork };
|
underlyingNetworks = new Network[] { defaultNetwork };
|
||||||
}
|
}
|
||||||
|
int[] transportTypes = new int[] { NetworkCapabilities.TRANSPORT_VPN };
|
||||||
|
int downKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
|
||||||
|
int upKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
|
||||||
|
boolean metered = declaredMetered; // metered if any underlying is metered, or agentMetered
|
||||||
|
boolean roaming = false; // roaming if any underlying is roaming
|
||||||
|
boolean congested = false; // congested if any underlying is congested
|
||||||
|
boolean suspended = true; // suspended if all underlying are suspended
|
||||||
|
|
||||||
// TODO(b/124469351): Get capabilities directly from ConnectivityService instead.
|
boolean hadUnderlyingNetworks = false;
|
||||||
final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
|
if (null != underlyingNetworks) {
|
||||||
Vpn.applyUnderlyingCapabilities(cm, underlyingNetworks, nc, nai.declaredMetered);
|
for (Network underlyingNetwork : underlyingNetworks) {
|
||||||
|
final NetworkAgentInfo underlying =
|
||||||
|
getNetworkAgentInfoForNetwork(underlyingNetwork);
|
||||||
|
if (underlying == null) continue;
|
||||||
|
|
||||||
|
final NetworkCapabilities underlyingCaps = underlying.networkCapabilities;
|
||||||
|
hadUnderlyingNetworks = true;
|
||||||
|
for (int underlyingType : underlyingCaps.getTransportTypes()) {
|
||||||
|
transportTypes = ArrayUtils.appendInt(transportTypes, underlyingType);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge capabilities of this underlying network. For bandwidth, assume the
|
||||||
|
// worst case.
|
||||||
|
downKbps = NetworkCapabilities.minBandwidth(downKbps,
|
||||||
|
underlyingCaps.getLinkDownstreamBandwidthKbps());
|
||||||
|
upKbps = NetworkCapabilities.minBandwidth(upKbps,
|
||||||
|
underlyingCaps.getLinkUpstreamBandwidthKbps());
|
||||||
|
// If this underlying network is metered, the VPN is metered (it may cost money
|
||||||
|
// to send packets on this network).
|
||||||
|
metered |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_METERED);
|
||||||
|
// If this underlying network is roaming, the VPN is roaming (the billing structure
|
||||||
|
// is different than the usual, local one).
|
||||||
|
roaming |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_ROAMING);
|
||||||
|
// If this underlying network is congested, the VPN is congested (the current
|
||||||
|
// condition of the network affects the performance of this network).
|
||||||
|
congested |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_CONGESTED);
|
||||||
|
// If this network is not suspended, the VPN is not suspended (the VPN
|
||||||
|
// is able to transfer some data).
|
||||||
|
suspended &= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hadUnderlyingNetworks) {
|
||||||
|
// No idea what the underlying networks are; assume reasonable defaults
|
||||||
|
metered = true;
|
||||||
|
roaming = false;
|
||||||
|
congested = false;
|
||||||
|
suspended = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
caps.setTransportTypes(transportTypes);
|
||||||
|
caps.setLinkDownstreamBandwidthKbps(downKbps);
|
||||||
|
caps.setLinkUpstreamBandwidthKbps(upKbps);
|
||||||
|
caps.setCapability(NET_CAPABILITY_NOT_METERED, !metered);
|
||||||
|
caps.setCapability(NET_CAPABILITY_NOT_ROAMING, !roaming);
|
||||||
|
caps.setCapability(NET_CAPABILITY_NOT_CONGESTED, !congested);
|
||||||
|
caps.setCapability(NET_CAPABILITY_NOT_SUSPENDED, !suspended);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -6422,7 +6476,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (nai.supportsUnderlyingNetworks()) {
|
if (nai.supportsUnderlyingNetworks()) {
|
||||||
mixInUnderlyingCapabilities(nai, newNc);
|
applyUnderlyingCapabilities(nai.declaredUnderlyingNetworks, newNc, nai.declaredMetered);
|
||||||
}
|
}
|
||||||
|
|
||||||
return newNc;
|
return newNc;
|
||||||
|
|||||||
@@ -18,10 +18,7 @@ package com.android.server.connectivity;
|
|||||||
|
|
||||||
import static android.Manifest.permission.BIND_VPN_SERVICE;
|
import static android.Manifest.permission.BIND_VPN_SERVICE;
|
||||||
import static android.net.ConnectivityManager.NETID_UNSET;
|
import static android.net.ConnectivityManager.NETID_UNSET;
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
|
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
|
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
|
|
||||||
import static android.net.RouteInfo.RTN_THROW;
|
import static android.net.RouteInfo.RTN_THROW;
|
||||||
import static android.net.RouteInfo.RTN_UNREACHABLE;
|
import static android.net.RouteInfo.RTN_UNREACHABLE;
|
||||||
|
|
||||||
@@ -111,7 +108,6 @@ import com.android.internal.net.LegacyVpnInfo;
|
|||||||
import com.android.internal.net.VpnConfig;
|
import com.android.internal.net.VpnConfig;
|
||||||
import com.android.internal.net.VpnInfo;
|
import com.android.internal.net.VpnInfo;
|
||||||
import com.android.internal.net.VpnProfile;
|
import com.android.internal.net.VpnProfile;
|
||||||
import com.android.internal.util.ArrayUtils;
|
|
||||||
import com.android.server.DeviceIdleInternal;
|
import com.android.server.DeviceIdleInternal;
|
||||||
import com.android.server.LocalServices;
|
import com.android.server.LocalServices;
|
||||||
import com.android.server.net.BaseNetworkObserver;
|
import com.android.server.net.BaseNetworkObserver;
|
||||||
@@ -462,99 +458,6 @@ public class Vpn {
|
|||||||
updateAlwaysOnNotification(detailedState);
|
updateAlwaysOnNotification(detailedState);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates {@link #mNetworkCapabilities} based on current underlying networks and returns a
|
|
||||||
* defensive copy.
|
|
||||||
*
|
|
||||||
* <p>Does not propagate updated capabilities to apps.
|
|
||||||
*
|
|
||||||
* @param defaultNetwork underlying network for VPNs following platform's default
|
|
||||||
*/
|
|
||||||
public synchronized NetworkCapabilities updateCapabilities(@Nullable Network defaultNetwork) {
|
|
||||||
if (mConfig == null) {
|
|
||||||
// VPN is not running.
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Network[] underlyingNetworks = mConfig.underlyingNetworks;
|
|
||||||
if (underlyingNetworks == null && defaultNetwork != null) {
|
|
||||||
// null underlying networks means to track the default.
|
|
||||||
underlyingNetworks = new Network[] { defaultNetwork };
|
|
||||||
}
|
|
||||||
// Only apps targeting Q and above can explicitly declare themselves as metered.
|
|
||||||
final boolean isAlwaysMetered = mIsPackageTargetingAtLeastQ && mConfig.isMetered;
|
|
||||||
|
|
||||||
applyUnderlyingCapabilities(
|
|
||||||
mConnectivityManager,
|
|
||||||
underlyingNetworks,
|
|
||||||
mNetworkCapabilities,
|
|
||||||
isAlwaysMetered);
|
|
||||||
|
|
||||||
return new NetworkCapabilities(mNetworkCapabilities);
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
public static void applyUnderlyingCapabilities(
|
|
||||||
@NonNull final ConnectivityManager cm,
|
|
||||||
@Nullable final Network[] underlyingNetworks,
|
|
||||||
@NonNull final NetworkCapabilities caps,
|
|
||||||
final boolean isAlwaysMetered) {
|
|
||||||
int[] transportTypes = new int[] { NetworkCapabilities.TRANSPORT_VPN };
|
|
||||||
int downKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
|
|
||||||
int upKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
|
|
||||||
boolean metered = isAlwaysMetered; // metered if any underlying is metered, or alwaysMetered
|
|
||||||
boolean roaming = false; // roaming if any underlying is roaming
|
|
||||||
boolean congested = false; // congested if any underlying is congested
|
|
||||||
boolean suspended = true; // suspended if all underlying are suspended
|
|
||||||
|
|
||||||
boolean hadUnderlyingNetworks = false;
|
|
||||||
if (null != underlyingNetworks) {
|
|
||||||
for (Network underlying : underlyingNetworks) {
|
|
||||||
// TODO(b/124469351): Get capabilities directly from ConnectivityService instead.
|
|
||||||
final NetworkCapabilities underlyingCaps = cm.getNetworkCapabilities(underlying);
|
|
||||||
if (underlyingCaps == null) continue;
|
|
||||||
hadUnderlyingNetworks = true;
|
|
||||||
for (int underlyingType : underlyingCaps.getTransportTypes()) {
|
|
||||||
transportTypes = ArrayUtils.appendInt(transportTypes, underlyingType);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Merge capabilities of this underlying network. For bandwidth, assume the
|
|
||||||
// worst case.
|
|
||||||
downKbps = NetworkCapabilities.minBandwidth(downKbps,
|
|
||||||
underlyingCaps.getLinkDownstreamBandwidthKbps());
|
|
||||||
upKbps = NetworkCapabilities.minBandwidth(upKbps,
|
|
||||||
underlyingCaps.getLinkUpstreamBandwidthKbps());
|
|
||||||
// If this underlying network is metered, the VPN is metered (it may cost money
|
|
||||||
// to send packets on this network).
|
|
||||||
metered |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_METERED);
|
|
||||||
// If this underlying network is roaming, the VPN is roaming (the billing structure
|
|
||||||
// is different than the usual, local one).
|
|
||||||
roaming |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_ROAMING);
|
|
||||||
// If this underlying network is congested, the VPN is congested (the current
|
|
||||||
// condition of the network affects the performance of this network).
|
|
||||||
congested |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_CONGESTED);
|
|
||||||
// If this network is not suspended, the VPN is not suspended (the VPN
|
|
||||||
// is able to transfer some data).
|
|
||||||
suspended &= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!hadUnderlyingNetworks) {
|
|
||||||
// No idea what the underlying networks are; assume the safer defaults
|
|
||||||
metered = true;
|
|
||||||
roaming = false;
|
|
||||||
congested = false;
|
|
||||||
suspended = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
caps.setTransportTypes(transportTypes);
|
|
||||||
caps.setLinkDownstreamBandwidthKbps(downKbps);
|
|
||||||
caps.setLinkUpstreamBandwidthKbps(upKbps);
|
|
||||||
caps.setCapability(NET_CAPABILITY_NOT_METERED, !metered);
|
|
||||||
caps.setCapability(NET_CAPABILITY_NOT_ROAMING, !roaming);
|
|
||||||
caps.setCapability(NET_CAPABILITY_NOT_CONGESTED, !congested);
|
|
||||||
caps.setCapability(NET_CAPABILITY_NOT_SUSPENDED, !suspended);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Chooses whether to force all connections to go though VPN.
|
* Chooses whether to force all connections to go though VPN.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -56,8 +56,10 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_IA;
|
|||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
|
||||||
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
|
||||||
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
|
||||||
@@ -5397,6 +5399,106 @@ public class ConnectivityServiceTest {
|
|||||||
assertTrue(lp.getDnsServers().containsAll(dnsServers));
|
assertTrue(lp.getDnsServers().containsAll(dnsServers));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testApplyUnderlyingCapabilities() throws Exception {
|
||||||
|
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
|
||||||
|
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
|
||||||
|
mCellNetworkAgent.connect(false /* validated */);
|
||||||
|
mWiFiNetworkAgent.connect(false /* validated */);
|
||||||
|
|
||||||
|
final NetworkCapabilities cellNc = new NetworkCapabilities()
|
||||||
|
.addTransportType(TRANSPORT_CELLULAR)
|
||||||
|
.addCapability(NET_CAPABILITY_INTERNET)
|
||||||
|
.addCapability(NET_CAPABILITY_NOT_CONGESTED)
|
||||||
|
.setLinkDownstreamBandwidthKbps(10);
|
||||||
|
final NetworkCapabilities wifiNc = new NetworkCapabilities()
|
||||||
|
.addTransportType(TRANSPORT_WIFI)
|
||||||
|
.addCapability(NET_CAPABILITY_INTERNET)
|
||||||
|
.addCapability(NET_CAPABILITY_NOT_METERED)
|
||||||
|
.addCapability(NET_CAPABILITY_NOT_ROAMING)
|
||||||
|
.addCapability(NET_CAPABILITY_NOT_CONGESTED)
|
||||||
|
.addCapability(NET_CAPABILITY_NOT_SUSPENDED)
|
||||||
|
.setLinkUpstreamBandwidthKbps(20);
|
||||||
|
mCellNetworkAgent.setNetworkCapabilities(cellNc, true /* sendToConnectivityService */);
|
||||||
|
mWiFiNetworkAgent.setNetworkCapabilities(wifiNc, true /* sendToConnectivityService */);
|
||||||
|
waitForIdle();
|
||||||
|
|
||||||
|
final Network mobile = mCellNetworkAgent.getNetwork();
|
||||||
|
final Network wifi = mWiFiNetworkAgent.getNetwork();
|
||||||
|
|
||||||
|
final NetworkCapabilities initialCaps = new NetworkCapabilities();
|
||||||
|
initialCaps.addCapability(NET_CAPABILITY_INTERNET);
|
||||||
|
initialCaps.removeCapability(NET_CAPABILITY_NOT_VPN);
|
||||||
|
|
||||||
|
final NetworkCapabilities withNoUnderlying = new NetworkCapabilities();
|
||||||
|
withNoUnderlying.addCapability(NET_CAPABILITY_INTERNET);
|
||||||
|
withNoUnderlying.addCapability(NET_CAPABILITY_NOT_CONGESTED);
|
||||||
|
withNoUnderlying.addCapability(NET_CAPABILITY_NOT_ROAMING);
|
||||||
|
withNoUnderlying.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
|
||||||
|
withNoUnderlying.addTransportType(TRANSPORT_VPN);
|
||||||
|
withNoUnderlying.removeCapability(NET_CAPABILITY_NOT_VPN);
|
||||||
|
|
||||||
|
final NetworkCapabilities withMobileUnderlying = new NetworkCapabilities(withNoUnderlying);
|
||||||
|
withMobileUnderlying.addTransportType(TRANSPORT_CELLULAR);
|
||||||
|
withMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_ROAMING);
|
||||||
|
withMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
|
||||||
|
withMobileUnderlying.setLinkDownstreamBandwidthKbps(10);
|
||||||
|
|
||||||
|
final NetworkCapabilities withWifiUnderlying = new NetworkCapabilities(withNoUnderlying);
|
||||||
|
withWifiUnderlying.addTransportType(TRANSPORT_WIFI);
|
||||||
|
withWifiUnderlying.addCapability(NET_CAPABILITY_NOT_METERED);
|
||||||
|
withWifiUnderlying.setLinkUpstreamBandwidthKbps(20);
|
||||||
|
|
||||||
|
final NetworkCapabilities withWifiAndMobileUnderlying =
|
||||||
|
new NetworkCapabilities(withNoUnderlying);
|
||||||
|
withWifiAndMobileUnderlying.addTransportType(TRANSPORT_CELLULAR);
|
||||||
|
withWifiAndMobileUnderlying.addTransportType(TRANSPORT_WIFI);
|
||||||
|
withWifiAndMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_METERED);
|
||||||
|
withWifiAndMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_ROAMING);
|
||||||
|
withWifiAndMobileUnderlying.setLinkDownstreamBandwidthKbps(10);
|
||||||
|
withWifiAndMobileUnderlying.setLinkUpstreamBandwidthKbps(20);
|
||||||
|
|
||||||
|
NetworkCapabilities caps = new NetworkCapabilities(initialCaps);
|
||||||
|
final boolean notDeclaredMetered = false;
|
||||||
|
mService.applyUnderlyingCapabilities(new Network[]{}, caps, notDeclaredMetered);
|
||||||
|
assertEquals(withNoUnderlying, caps);
|
||||||
|
|
||||||
|
caps = new NetworkCapabilities(initialCaps);
|
||||||
|
mService.applyUnderlyingCapabilities(new Network[]{null}, caps, notDeclaredMetered);
|
||||||
|
assertEquals(withNoUnderlying, caps);
|
||||||
|
|
||||||
|
caps = new NetworkCapabilities(initialCaps);
|
||||||
|
mService.applyUnderlyingCapabilities(new Network[]{mobile}, caps, notDeclaredMetered);
|
||||||
|
assertEquals(withMobileUnderlying, caps);
|
||||||
|
|
||||||
|
mService.applyUnderlyingCapabilities(new Network[]{wifi}, caps, notDeclaredMetered);
|
||||||
|
assertEquals(withWifiUnderlying, caps);
|
||||||
|
|
||||||
|
final boolean isDeclaredMetered = true;
|
||||||
|
withWifiUnderlying.removeCapability(NET_CAPABILITY_NOT_METERED);
|
||||||
|
caps = new NetworkCapabilities(initialCaps);
|
||||||
|
mService.applyUnderlyingCapabilities(new Network[]{wifi}, caps, isDeclaredMetered);
|
||||||
|
assertEquals(withWifiUnderlying, caps);
|
||||||
|
|
||||||
|
caps = new NetworkCapabilities(initialCaps);
|
||||||
|
mService.applyUnderlyingCapabilities(new Network[]{mobile, wifi}, caps, isDeclaredMetered);
|
||||||
|
assertEquals(withWifiAndMobileUnderlying, caps);
|
||||||
|
|
||||||
|
withWifiUnderlying.addCapability(NET_CAPABILITY_NOT_METERED);
|
||||||
|
caps = new NetworkCapabilities(initialCaps);
|
||||||
|
mService.applyUnderlyingCapabilities(new Network[]{null, mobile, null, wifi},
|
||||||
|
caps, notDeclaredMetered);
|
||||||
|
assertEquals(withWifiAndMobileUnderlying, caps);
|
||||||
|
|
||||||
|
caps = new NetworkCapabilities(initialCaps);
|
||||||
|
mService.applyUnderlyingCapabilities(new Network[]{null, mobile, null, wifi},
|
||||||
|
caps, notDeclaredMetered);
|
||||||
|
assertEquals(withWifiAndMobileUnderlying, caps);
|
||||||
|
|
||||||
|
mService.applyUnderlyingCapabilities(null, caps, notDeclaredMetered);
|
||||||
|
assertEquals(withWifiUnderlying, caps);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testVpnConnectDisconnectUnderlyingNetwork() throws Exception {
|
public void testVpnConnectDisconnectUnderlyingNetwork() throws Exception {
|
||||||
final TestNetworkCallback callback = new TestNetworkCallback();
|
final TestNetworkCallback callback = new TestNetworkCallback();
|
||||||
@@ -5947,17 +6049,28 @@ public class ConnectivityServiceTest {
|
|||||||
&& caps.hasTransport(TRANSPORT_VPN)
|
&& caps.hasTransport(TRANSPORT_VPN)
|
||||||
&& caps.hasTransport(TRANSPORT_WIFI));
|
&& caps.hasTransport(TRANSPORT_WIFI));
|
||||||
|
|
||||||
|
// Change the VPN's capabilities somehow (specifically, disconnect wifi).
|
||||||
|
mWiFiNetworkAgent.disconnect();
|
||||||
|
callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
|
||||||
|
callback.expectCapabilitiesThat(mMockVpn, (caps)
|
||||||
|
-> caps.getUids().size() == 2
|
||||||
|
&& caps.getUids().contains(new UidRange(uid, uid))
|
||||||
|
&& caps.getUids().contains(UidRange.createForUser(restrictedUserId))
|
||||||
|
&& caps.hasTransport(TRANSPORT_VPN)
|
||||||
|
&& !caps.hasTransport(TRANSPORT_WIFI));
|
||||||
|
|
||||||
// Send a USER_REMOVED broadcast and expect to lose the UID range for the restricted user.
|
// Send a USER_REMOVED broadcast and expect to lose the UID range for the restricted user.
|
||||||
final Intent removedIntent = new Intent(ACTION_USER_REMOVED);
|
final Intent removedIntent = new Intent(ACTION_USER_REMOVED);
|
||||||
removedIntent.putExtra(Intent.EXTRA_USER_HANDLE, restrictedUserId);
|
removedIntent.putExtra(Intent.EXTRA_USER_HANDLE, restrictedUserId);
|
||||||
handler.post(() -> mServiceContext.sendBroadcast(removedIntent));
|
handler.post(() -> mServiceContext.sendBroadcast(removedIntent));
|
||||||
|
|
||||||
// Expect that the VPN gains the UID range for the restricted user.
|
// Expect that the VPN gains the UID range for the restricted user, and that the capability
|
||||||
|
// change made just before that (i.e., loss of TRANSPORT_WIFI) is preserved.
|
||||||
callback.expectCapabilitiesThat(mMockVpn, (caps)
|
callback.expectCapabilitiesThat(mMockVpn, (caps)
|
||||||
-> caps.getUids().size() == 1
|
-> caps.getUids().size() == 1
|
||||||
&& caps.getUids().contains(new UidRange(uid, uid))
|
&& caps.getUids().contains(new UidRange(uid, uid))
|
||||||
&& caps.hasTransport(TRANSPORT_VPN)
|
&& caps.hasTransport(TRANSPORT_VPN)
|
||||||
&& caps.hasTransport(TRANSPORT_WIFI));
|
&& !caps.hasTransport(TRANSPORT_WIFI));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -21,15 +21,6 @@ import static android.content.pm.UserInfo.FLAG_MANAGED_PROFILE;
|
|||||||
import static android.content.pm.UserInfo.FLAG_PRIMARY;
|
import static android.content.pm.UserInfo.FLAG_PRIMARY;
|
||||||
import static android.content.pm.UserInfo.FLAG_RESTRICTED;
|
import static android.content.pm.UserInfo.FLAG_RESTRICTED;
|
||||||
import static android.net.ConnectivityManager.NetworkCallback;
|
import static android.net.ConnectivityManager.NetworkCallback;
|
||||||
import static android.net.NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
|
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
|
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
|
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
|
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
|
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
|
|
||||||
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
|
|
||||||
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
|
|
||||||
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
@@ -621,102 +612,6 @@ public class VpnTest {
|
|||||||
order.verify(mNotificationManager).cancel(anyString(), anyInt());
|
order.verify(mNotificationManager).cancel(anyString(), anyInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCapabilities() {
|
|
||||||
setMockedUsers(primaryUser);
|
|
||||||
|
|
||||||
final Network mobile = new Network(1);
|
|
||||||
final Network wifi = new Network(2);
|
|
||||||
|
|
||||||
final Map<Network, NetworkCapabilities> networks = new HashMap<>();
|
|
||||||
networks.put(
|
|
||||||
mobile,
|
|
||||||
new NetworkCapabilities()
|
|
||||||
.addTransportType(TRANSPORT_CELLULAR)
|
|
||||||
.addCapability(NET_CAPABILITY_INTERNET)
|
|
||||||
.addCapability(NET_CAPABILITY_NOT_CONGESTED)
|
|
||||||
.setLinkDownstreamBandwidthKbps(10));
|
|
||||||
networks.put(
|
|
||||||
wifi,
|
|
||||||
new NetworkCapabilities()
|
|
||||||
.addTransportType(TRANSPORT_WIFI)
|
|
||||||
.addCapability(NET_CAPABILITY_INTERNET)
|
|
||||||
.addCapability(NET_CAPABILITY_NOT_METERED)
|
|
||||||
.addCapability(NET_CAPABILITY_NOT_ROAMING)
|
|
||||||
.addCapability(NET_CAPABILITY_NOT_CONGESTED)
|
|
||||||
.addCapability(NET_CAPABILITY_NOT_SUSPENDED)
|
|
||||||
.setLinkUpstreamBandwidthKbps(20));
|
|
||||||
setMockedNetworks(networks);
|
|
||||||
|
|
||||||
final NetworkCapabilities caps = new NetworkCapabilities();
|
|
||||||
|
|
||||||
Vpn.applyUnderlyingCapabilities(
|
|
||||||
mConnectivityManager, new Network[] {}, caps, false /* isAlwaysMetered */);
|
|
||||||
assertTrue(caps.hasTransport(TRANSPORT_VPN));
|
|
||||||
assertFalse(caps.hasTransport(TRANSPORT_CELLULAR));
|
|
||||||
assertFalse(caps.hasTransport(TRANSPORT_WIFI));
|
|
||||||
assertEquals(LINK_BANDWIDTH_UNSPECIFIED, caps.getLinkDownstreamBandwidthKbps());
|
|
||||||
assertEquals(LINK_BANDWIDTH_UNSPECIFIED, caps.getLinkUpstreamBandwidthKbps());
|
|
||||||
assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED));
|
|
||||||
assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
|
|
||||||
assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
|
|
||||||
assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
|
|
||||||
|
|
||||||
Vpn.applyUnderlyingCapabilities(
|
|
||||||
mConnectivityManager,
|
|
||||||
new Network[] {mobile},
|
|
||||||
caps,
|
|
||||||
false /* isAlwaysMetered */);
|
|
||||||
assertTrue(caps.hasTransport(TRANSPORT_VPN));
|
|
||||||
assertTrue(caps.hasTransport(TRANSPORT_CELLULAR));
|
|
||||||
assertFalse(caps.hasTransport(TRANSPORT_WIFI));
|
|
||||||
assertEquals(10, caps.getLinkDownstreamBandwidthKbps());
|
|
||||||
assertEquals(LINK_BANDWIDTH_UNSPECIFIED, caps.getLinkUpstreamBandwidthKbps());
|
|
||||||
assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED));
|
|
||||||
assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
|
|
||||||
assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
|
|
||||||
assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
|
|
||||||
|
|
||||||
Vpn.applyUnderlyingCapabilities(
|
|
||||||
mConnectivityManager, new Network[] {wifi}, caps, false /* isAlwaysMetered */);
|
|
||||||
assertTrue(caps.hasTransport(TRANSPORT_VPN));
|
|
||||||
assertFalse(caps.hasTransport(TRANSPORT_CELLULAR));
|
|
||||||
assertTrue(caps.hasTransport(TRANSPORT_WIFI));
|
|
||||||
assertEquals(LINK_BANDWIDTH_UNSPECIFIED, caps.getLinkDownstreamBandwidthKbps());
|
|
||||||
assertEquals(20, caps.getLinkUpstreamBandwidthKbps());
|
|
||||||
assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_METERED));
|
|
||||||
assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
|
|
||||||
assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
|
|
||||||
assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
|
|
||||||
|
|
||||||
Vpn.applyUnderlyingCapabilities(
|
|
||||||
mConnectivityManager, new Network[] {wifi}, caps, true /* isAlwaysMetered */);
|
|
||||||
assertTrue(caps.hasTransport(TRANSPORT_VPN));
|
|
||||||
assertFalse(caps.hasTransport(TRANSPORT_CELLULAR));
|
|
||||||
assertTrue(caps.hasTransport(TRANSPORT_WIFI));
|
|
||||||
assertEquals(LINK_BANDWIDTH_UNSPECIFIED, caps.getLinkDownstreamBandwidthKbps());
|
|
||||||
assertEquals(20, caps.getLinkUpstreamBandwidthKbps());
|
|
||||||
assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED));
|
|
||||||
assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
|
|
||||||
assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
|
|
||||||
assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
|
|
||||||
|
|
||||||
Vpn.applyUnderlyingCapabilities(
|
|
||||||
mConnectivityManager,
|
|
||||||
new Network[] {mobile, wifi},
|
|
||||||
caps,
|
|
||||||
false /* isAlwaysMetered */);
|
|
||||||
assertTrue(caps.hasTransport(TRANSPORT_VPN));
|
|
||||||
assertTrue(caps.hasTransport(TRANSPORT_CELLULAR));
|
|
||||||
assertTrue(caps.hasTransport(TRANSPORT_WIFI));
|
|
||||||
assertEquals(10, caps.getLinkDownstreamBandwidthKbps());
|
|
||||||
assertEquals(20, caps.getLinkUpstreamBandwidthKbps());
|
|
||||||
assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED));
|
|
||||||
assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
|
|
||||||
assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
|
|
||||||
assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The profile name should NOT change between releases for backwards compatibility
|
* The profile name should NOT change between releases for backwards compatibility
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user