Merge "Fix isActiveNetworkMetered for VPNs." am: 8cf699851a am: cb011b799f

am: 08bd075e35

Change-Id: I3d536324052227bbfab31ba5d608c35ecb9b1ab5
This commit is contained in:
Varun Anand
2019-03-04 18:09:07 -08:00
committed by android-build-merger
2 changed files with 207 additions and 4 deletions

View File

@@ -1575,8 +1575,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
public boolean isActiveNetworkMetered() { public boolean isActiveNetworkMetered() {
enforceAccessPermission(); enforceAccessPermission();
final int uid = Binder.getCallingUid(); final NetworkCapabilities caps = getNetworkCapabilities(getActiveNetwork());
final NetworkCapabilities caps = getUnfilteredActiveNetworkState(uid).networkCapabilities;
if (caps != null) { if (caps != null) {
return !caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); return !caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
} else { } else {

View File

@@ -939,11 +939,19 @@ public class ConnectivityServiceTest {
return mConnected; // Similar trickery return mConnected; // Similar trickery
} }
public void connect() { private void connect(boolean isAlwaysMetered) {
mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities()); mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
mConnected = true; mConnected = true;
mConfig = new VpnConfig(); mConfig = new VpnConfig();
mConfig.isMetered = false; mConfig.isMetered = isAlwaysMetered;
}
public void connectAsAlwaysMetered() {
connect(true /* isAlwaysMetered */);
}
public void connect() {
connect(false /* isAlwaysMetered */);
} }
@Override @Override
@@ -5103,6 +5111,202 @@ public class ConnectivityServiceTest {
mMockVpn.disconnect(); mMockVpn.disconnect();
} }
@Test
public void testIsActiveNetworkMeteredOverWifi() {
// Returns true by default when no network is available.
assertTrue(mCm.isActiveNetworkMetered());
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
mWiFiNetworkAgent.connect(true);
waitForIdle();
assertFalse(mCm.isActiveNetworkMetered());
}
@Test
public void testIsActiveNetworkMeteredOverCell() {
// Returns true by default when no network is available.
assertTrue(mCm.isActiveNetworkMetered());
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
mCellNetworkAgent.connect(true);
waitForIdle();
assertTrue(mCm.isActiveNetworkMetered());
}
@Test
public void testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault() {
// Returns true by default when no network is available.
assertTrue(mCm.isActiveNetworkMetered());
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
mCellNetworkAgent.connect(true);
waitForIdle();
assertTrue(mCm.isActiveNetworkMetered());
// Connect VPN network. By default it is using current default network (Cell).
MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
final ArraySet<UidRange> ranges = new ArraySet<>();
final int uid = Process.myUid();
ranges.add(new UidRange(uid, uid));
mMockVpn.setNetworkAgent(vpnNetworkAgent);
mMockVpn.setUids(ranges);
vpnNetworkAgent.connect(true);
mMockVpn.connect();
waitForIdle();
// Ensure VPN is now the active network.
assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
// Expect VPN to be metered.
assertTrue(mCm.isActiveNetworkMetered());
// Connect WiFi.
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
mWiFiNetworkAgent.connect(true);
waitForIdle();
// VPN should still be the active network.
assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
// Expect VPN to be unmetered as it should now be using WiFi (new default).
assertFalse(mCm.isActiveNetworkMetered());
// Disconnecting Cell should not affect VPN's meteredness.
mCellNetworkAgent.disconnect();
waitForIdle();
assertFalse(mCm.isActiveNetworkMetered());
// Disconnect WiFi; Now there is no platform default network.
mWiFiNetworkAgent.disconnect();
waitForIdle();
// VPN without any underlying networks is treated as metered.
assertTrue(mCm.isActiveNetworkMetered());
vpnNetworkAgent.disconnect();
mMockVpn.disconnect();
}
@Test
public void testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks() {
// Returns true by default when no network is available.
assertTrue(mCm.isActiveNetworkMetered());
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
mCellNetworkAgent.connect(true);
waitForIdle();
assertTrue(mCm.isActiveNetworkMetered());
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
mWiFiNetworkAgent.connect(true);
waitForIdle();
assertFalse(mCm.isActiveNetworkMetered());
// Connect VPN network.
MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
final ArraySet<UidRange> ranges = new ArraySet<>();
final int uid = Process.myUid();
ranges.add(new UidRange(uid, uid));
mMockVpn.setNetworkAgent(vpnNetworkAgent);
mMockVpn.setUids(ranges);
vpnNetworkAgent.connect(true);
mMockVpn.connect();
waitForIdle();
// Ensure VPN is now the active network.
assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
// VPN is using Cell
mService.setUnderlyingNetworksForVpn(
new Network[] { mCellNetworkAgent.getNetwork() });
waitForIdle();
// Expect VPN to be metered.
assertTrue(mCm.isActiveNetworkMetered());
// VPN is now using WiFi
mService.setUnderlyingNetworksForVpn(
new Network[] { mWiFiNetworkAgent.getNetwork() });
waitForIdle();
// Expect VPN to be unmetered
assertFalse(mCm.isActiveNetworkMetered());
// VPN is using Cell | WiFi.
mService.setUnderlyingNetworksForVpn(
new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
waitForIdle();
// Expect VPN to be metered.
assertTrue(mCm.isActiveNetworkMetered());
// VPN is using WiFi | Cell.
mService.setUnderlyingNetworksForVpn(
new Network[] { mWiFiNetworkAgent.getNetwork(), mCellNetworkAgent.getNetwork() });
waitForIdle();
// Order should not matter and VPN should still be metered.
assertTrue(mCm.isActiveNetworkMetered());
// VPN is not using any underlying networks.
mService.setUnderlyingNetworksForVpn(new Network[0]);
waitForIdle();
// VPN without underlying networks is treated as metered.
assertTrue(mCm.isActiveNetworkMetered());
vpnNetworkAgent.disconnect();
mMockVpn.disconnect();
}
@Test
public void testIsActiveNetworkMeteredOverAlwaysMeteredVpn() {
// Returns true by default when no network is available.
assertTrue(mCm.isActiveNetworkMetered());
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
mWiFiNetworkAgent.connect(true);
waitForIdle();
assertFalse(mCm.isActiveNetworkMetered());
// Connect VPN network.
MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
final ArraySet<UidRange> ranges = new ArraySet<>();
final int uid = Process.myUid();
ranges.add(new UidRange(uid, uid));
mMockVpn.setNetworkAgent(vpnNetworkAgent);
mMockVpn.setUids(ranges);
vpnNetworkAgent.connect(true);
mMockVpn.connectAsAlwaysMetered();
waitForIdle();
assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
// VPN is tracking current platform default (WiFi).
mService.setUnderlyingNetworksForVpn(null);
waitForIdle();
// Despite VPN using WiFi (which is unmetered), VPN itself is marked as always metered.
assertTrue(mCm.isActiveNetworkMetered());
// VPN explicitly declares WiFi as its underlying network.
mService.setUnderlyingNetworksForVpn(
new Network[] { mWiFiNetworkAgent.getNetwork() });
waitForIdle();
// Doesn't really matter whether VPN declares its underlying networks explicitly.
assertTrue(mCm.isActiveNetworkMetered());
// With WiFi lost, VPN is basically without any underlying networks. And in that case it is
// anyways suppose to be metered.
mWiFiNetworkAgent.disconnect();
waitForIdle();
assertTrue(mCm.isActiveNetworkMetered());
vpnNetworkAgent.disconnect();
}
@Test @Test
public void testNetworkBlockedStatus() { public void testNetworkBlockedStatus() {
final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();