Merge changes I65784f35,Ib6937335 into nyc-mr1-dev

am: 74f7f2ec0d

Change-Id: Iba950e7837d91f83a9c2bcd7fc8e7b1193038400
This commit is contained in:
Lorenzo Colitti
2016-06-30 14:33:25 +00:00
committed by android-build-merger

View File

@@ -17,6 +17,7 @@
package com.android.server; package com.android.server;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.TYPE_ETHERNET;
import static android.net.ConnectivityManager.TYPE_MOBILE; import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.ConnectivityManager.getNetworkTypeName; import static android.net.ConnectivityManager.getNetworkTypeName;
@@ -79,6 +80,7 @@ import com.android.server.net.NetworkPinner;
import java.net.InetAddress; import java.net.InetAddress;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Objects;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@@ -100,6 +102,7 @@ public class ConnectivityServiceTest extends AndroidTestCase {
private WrappedConnectivityManager mCm; private WrappedConnectivityManager mCm;
private MockNetworkAgent mWiFiNetworkAgent; private MockNetworkAgent mWiFiNetworkAgent;
private MockNetworkAgent mCellNetworkAgent; private MockNetworkAgent mCellNetworkAgent;
private MockNetworkAgent mEthernetNetworkAgent;
// This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
// do not go through ConnectivityService but talk to netd directly, so they don't automatically // do not go through ConnectivityService but talk to netd directly, so they don't automatically
@@ -243,6 +246,9 @@ public class ConnectivityServiceTest extends AndroidTestCase {
mNetworkCapabilities = new NetworkCapabilities(); mNetworkCapabilities = new NetworkCapabilities();
mNetworkCapabilities.addTransportType(transport); mNetworkCapabilities.addTransportType(transport);
switch (transport) { switch (transport) {
case TRANSPORT_ETHERNET:
mScore = 70;
break;
case TRANSPORT_WIFI: case TRANSPORT_WIFI:
mScore = 60; mScore = 60;
break; break;
@@ -304,6 +310,11 @@ public class ConnectivityServiceTest extends AndroidTestCase {
mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
} }
public void removeCapability(int capability) {
mNetworkCapabilities.removeCapability(capability);
mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
}
public void setSignalStrength(int signalStrength) { public void setSignalStrength(int signalStrength) {
mNetworkCapabilities.setSignalStrength(signalStrength); mNetworkCapabilities.setSignalStrength(signalStrength);
mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
@@ -694,14 +705,23 @@ public class ConnectivityServiceTest extends AndroidTestCase {
mCm.bindProcessToNetwork(null); mCm.bindProcessToNetwork(null);
} }
public void tearDown() throws Exception {
if (mCellNetworkAgent != null) { mCellNetworkAgent.disconnect(); }
if (mWiFiNetworkAgent != null) { mWiFiNetworkAgent.disconnect(); }
mCellNetworkAgent = mWiFiNetworkAgent = null;
super.tearDown();
}
private int transportToLegacyType(int transport) { private int transportToLegacyType(int transport) {
switch (transport) { switch (transport) {
case TRANSPORT_ETHERNET:
return TYPE_ETHERNET;
case TRANSPORT_WIFI: case TRANSPORT_WIFI:
return TYPE_WIFI; return TYPE_WIFI;
case TRANSPORT_CELLULAR: case TRANSPORT_CELLULAR:
return TYPE_MOBILE; return TYPE_MOBILE;
default: default:
throw new IllegalStateException("Unknown transport" + transport); throw new IllegalStateException("Unknown transport " + transport);
} }
} }
@@ -911,8 +931,6 @@ public class ConnectivityServiceTest extends AndroidTestCase {
mWiFiNetworkAgent.adjustScore(11); mWiFiNetworkAgent.adjustScore(11);
waitFor(cv); waitFor(cv);
verifyActiveNetwork(TRANSPORT_WIFI); verifyActiveNetwork(TRANSPORT_WIFI);
mCellNetworkAgent.disconnect();
mWiFiNetworkAgent.disconnect();
} }
@LargeTest @LargeTest
@@ -984,8 +1002,6 @@ public class ConnectivityServiceTest extends AndroidTestCase {
assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability( assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
NET_CAPABILITY_VALIDATED)); NET_CAPABILITY_VALIDATED));
verifyActiveNetwork(TRANSPORT_WIFI); verifyActiveNetwork(TRANSPORT_WIFI);
mCellNetworkAgent.disconnect();
mWiFiNetworkAgent.disconnect();
} }
@LargeTest @LargeTest
@@ -1012,8 +1028,6 @@ public class ConnectivityServiceTest extends AndroidTestCase {
assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability( assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
NET_CAPABILITY_VALIDATED)); NET_CAPABILITY_VALIDATED));
verifyActiveNetwork(TRANSPORT_WIFI); verifyActiveNetwork(TRANSPORT_WIFI);
mCellNetworkAgent.disconnect();
mWiFiNetworkAgent.disconnect();
} }
enum CallbackState { enum CallbackState {
@@ -1029,59 +1043,74 @@ public class ConnectivityServiceTest extends AndroidTestCase {
* received. assertNoCallback may be called at any time. * received. assertNoCallback may be called at any time.
*/ */
private class TestNetworkCallback extends NetworkCallback { private class TestNetworkCallback extends NetworkCallback {
private final ConditionVariable mConditionVariable = new ConditionVariable(); private class CallbackInfo {
private CallbackState mLastCallback = CallbackState.NONE; public final CallbackState state;
private Network mLastNetwork; public final Network network;
public CallbackInfo(CallbackState s, Network n) { state = s; network = n; }
public String toString() { return String.format("%s (%s)", state, network); }
public boolean equals(Object o) {
if (!(o instanceof CallbackInfo)) return false;
CallbackInfo other = (CallbackInfo) o;
return state == other.state && Objects.equals(network, other.network);
}
}
private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
private void setLastCallback(CallbackState state, Network network) {
mCallbacks.offer(new CallbackInfo(state, network));
}
public void onAvailable(Network network) { public void onAvailable(Network network) {
assertEquals(CallbackState.NONE, mLastCallback); setLastCallback(CallbackState.AVAILABLE, network);
mLastCallback = CallbackState.AVAILABLE;
mLastNetwork = network;
mConditionVariable.open();
} }
public void onLosing(Network network, int maxMsToLive) { public void onLosing(Network network, int maxMsToLive) {
assertEquals(CallbackState.NONE, mLastCallback); setLastCallback(CallbackState.LOSING, network);
mLastCallback = CallbackState.LOSING;
mLastNetwork = network;
mConditionVariable.open();
} }
public void onLost(Network network) { public void onLost(Network network) {
assertEquals(CallbackState.NONE, mLastCallback); setLastCallback(CallbackState.LOST, network);
mLastCallback = CallbackState.LOST;
mLastNetwork = network;
mConditionVariable.open();
}
void expectCallback(CallbackState state) {
expectCallback(state, null);
} }
void expectCallback(CallbackState state, MockNetworkAgent mockAgent) { void expectCallback(CallbackState state, MockNetworkAgent mockAgent) {
waitFor(mConditionVariable); CallbackInfo expected = new CallbackInfo(
assertEquals(state, mLastCallback); state,
if (mockAgent != null) { (mockAgent != null) ? mockAgent.getNetwork() : null);
assertEquals(mockAgent.getNetwork(), mLastNetwork); try {
assertEquals("Unexpected callback:",
expected, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
} catch (InterruptedException e) {
fail("Did not receive expected " + expected + " after " + TIMEOUT_MS + "ms");
} }
mLastCallback = CallbackState.NONE;
mLastNetwork = null;
mConditionVariable.close();
} }
void assertNoCallback() { void assertNoCallback() {
assertEquals(CallbackState.NONE, mLastCallback); mService.waitForIdle();
CallbackInfo c = mCallbacks.peek();
assertNull("Unexpected callback: " + c, c);
}
}
// Can't be part of TestNetworkCallback because "cannot be declared static; static methods can
// only be declared in a static or top level type".
static void assertNoCallbacks(TestNetworkCallback ... callbacks) {
for (TestNetworkCallback c : callbacks) {
c.assertNoCallback();
} }
} }
@LargeTest @LargeTest
public void testStateChangeNetworkCallbacks() throws Exception { public void testStateChangeNetworkCallbacks() throws Exception {
final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback(); final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
final NetworkRequest genericRequest = new NetworkRequest.Builder()
.clearCapabilities().build();
final NetworkRequest wifiRequest = new NetworkRequest.Builder() final NetworkRequest wifiRequest = new NetworkRequest.Builder()
.addTransportType(TRANSPORT_WIFI).build(); .addTransportType(TRANSPORT_WIFI).build();
final NetworkRequest cellRequest = new NetworkRequest.Builder() final NetworkRequest cellRequest = new NetworkRequest.Builder()
.addTransportType(TRANSPORT_CELLULAR).build(); .addTransportType(TRANSPORT_CELLULAR).build();
mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback); mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
mCm.registerNetworkCallback(cellRequest, cellNetworkCallback); mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
@@ -1089,65 +1118,218 @@ public class ConnectivityServiceTest extends AndroidTestCase {
ConditionVariable cv = waitForConnectivityBroadcasts(1); ConditionVariable cv = waitForConnectivityBroadcasts(1);
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(false); mCellNetworkAgent.connect(false);
cellNetworkCallback.expectCallback(CallbackState.AVAILABLE); genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
wifiNetworkCallback.assertNoCallback(); cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
waitFor(cv); waitFor(cv);
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
// This should not trigger spurious onAvailable() callbacks, b/21762680. // This should not trigger spurious onAvailable() callbacks, b/21762680.
mCellNetworkAgent.adjustScore(-1); mCellNetworkAgent.adjustScore(-1);
mService.waitForIdle(); mService.waitForIdle();
wifiNetworkCallback.assertNoCallback(); assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
cellNetworkCallback.assertNoCallback();
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
cv = waitForConnectivityBroadcasts(2); cv = waitForConnectivityBroadcasts(2);
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false); mWiFiNetworkAgent.connect(false);
wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE); genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
cellNetworkCallback.assertNoCallback(); wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
waitFor(cv); waitFor(cv);
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
cv = waitForConnectivityBroadcasts(2); cv = waitForConnectivityBroadcasts(2);
mWiFiNetworkAgent.disconnect(); mWiFiNetworkAgent.disconnect();
wifiNetworkCallback.expectCallback(CallbackState.LOST); genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
cellNetworkCallback.assertNoCallback(); cellNetworkCallback.assertNoCallback();
waitFor(cv); waitFor(cv);
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
cv = waitForConnectivityBroadcasts(1); cv = waitForConnectivityBroadcasts(1);
mCellNetworkAgent.disconnect(); mCellNetworkAgent.disconnect();
cellNetworkCallback.expectCallback(CallbackState.LOST); genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
wifiNetworkCallback.assertNoCallback(); cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
waitFor(cv); waitFor(cv);
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
// Test validated networks // Test validated networks
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(true); mCellNetworkAgent.connect(true);
cellNetworkCallback.expectCallback(CallbackState.AVAILABLE); genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
wifiNetworkCallback.assertNoCallback(); cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
// This should not trigger spurious onAvailable() callbacks, b/21762680. // This should not trigger spurious onAvailable() callbacks, b/21762680.
mCellNetworkAgent.adjustScore(-1); mCellNetworkAgent.adjustScore(-1);
mService.waitForIdle(); mService.waitForIdle();
wifiNetworkCallback.assertNoCallback(); assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
cellNetworkCallback.assertNoCallback();
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(true); mWiFiNetworkAgent.connect(true);
wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE); genericNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
cellNetworkCallback.expectCallback(CallbackState.LOSING); genericNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
wifiNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
cellNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
mWiFiNetworkAgent.disconnect();
genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
mCellNetworkAgent.disconnect();
genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
}
@SmallTest
public void testMultipleLingering() {
NetworkRequest request = new NetworkRequest.Builder()
.clearCapabilities().addCapability(NET_CAPABILITY_NOT_METERED)
.build();
TestNetworkCallback callback = new TestNetworkCallback();
mCm.registerNetworkCallback(request, callback);
TestNetworkCallback defaultCallback = new TestNetworkCallback();
mCm.registerDefaultNetworkCallback(defaultCallback);
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
mCellNetworkAgent.connect(true);
callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
mWiFiNetworkAgent.connect(true);
// We get AVAILABLE on wifi when wifi connects and satisfies our unmetered request.
// We then get LOSING when wifi validates and cell is outscored.
callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
mEthernetNetworkAgent.connect(true);
callback.expectCallback(CallbackState.AVAILABLE, mEthernetNetworkAgent);
callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
defaultCallback.expectCallback(CallbackState.AVAILABLE, mEthernetNetworkAgent);
assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
mEthernetNetworkAgent.disconnect();
callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
for (int i = 0; i < 4; i++) {
MockNetworkAgent oldNetwork, newNetwork;
if (i % 2 == 0) {
mWiFiNetworkAgent.adjustScore(-15);
oldNetwork = mWiFiNetworkAgent;
newNetwork = mCellNetworkAgent;
} else {
mWiFiNetworkAgent.adjustScore(15);
oldNetwork = mCellNetworkAgent;
newNetwork = mWiFiNetworkAgent;
}
callback.expectCallback(CallbackState.LOSING, oldNetwork);
defaultCallback.expectCallback(CallbackState.AVAILABLE, newNetwork);
assertEquals(newNetwork.getNetwork(), mCm.getActiveNetwork());
}
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
// Verify that if a network no longer satisfies a request, we send LOST and not LOSING, even
// if the network is still up.
mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
// Wifi no longer satisfies our listen, which is for an unmetered network.
// But because its score is 55, it's still up (and the default network).
defaultCallback.assertNoCallback();
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
// Disconnect our test networks.
mWiFiNetworkAgent.disconnect();
defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
mCellNetworkAgent.disconnect();
defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
mCm.unregisterNetworkCallback(callback);
mService.waitForIdle();
// Check that a network is only lingered or torn down if it would not satisfy a request even
// if it validated.
request = new NetworkRequest.Builder().clearCapabilities().build();
callback = new TestNetworkCallback();
mCm.registerNetworkCallback(request, callback);
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(false); // Score: 10
callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
// Bring up wifi with a score of 20.
// Cell stays up because it would satisfy the default request if it validated.
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false); // Score: 20
callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
mWiFiNetworkAgent.disconnect(); mWiFiNetworkAgent.disconnect();
wifiNetworkCallback.expectCallback(CallbackState.LOST); callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
cellNetworkCallback.assertNoCallback(); defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
mCellNetworkAgent.disconnect(); // Bring up wifi with a score of 70.
cellNetworkCallback.expectCallback(CallbackState.LOST); // Cell is lingered because it would not satisfy any reques, even if it validated.
wifiNetworkCallback.assertNoCallback(); mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.adjustScore(50);
mWiFiNetworkAgent.connect(false); // Score: 70
callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
// Tear down wifi.
mWiFiNetworkAgent.disconnect();
callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
// Bring up wifi, then validate it. In this case we do not linger cell. What happens is that
// when wifi connects, we don't linger because cell could potentially become the default
// network if it validated. Then, when wifi validates, we re-evaluate cell, see it has no
// requests, and tear it down because it's unneeded.
// TODO: can we linger in this case?
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(true);
callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
mWiFiNetworkAgent.disconnect();
callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
mCm.unregisterNetworkCallback(callback);
mCm.unregisterNetworkCallback(defaultCallback);
} }
private void tryNetworkFactoryRequests(int capability) throws Exception { private void tryNetworkFactoryRequests(int capability) throws Exception {
@@ -1314,7 +1496,7 @@ public class ConnectivityServiceTest extends AndroidTestCase {
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS); mCellNetworkAgent.addCapability(NET_CAPABILITY_MMS);
mCellNetworkAgent.connectWithoutInternet(); mCellNetworkAgent.connectWithoutInternet();
networkCallback.expectCallback(CallbackState.AVAILABLE); networkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
verifyActiveNetwork(TRANSPORT_WIFI); verifyActiveNetwork(TRANSPORT_WIFI);
// Test releasing NetworkRequest disconnects cellular with MMS // Test releasing NetworkRequest disconnects cellular with MMS
cv = mCellNetworkAgent.getDisconnectedCV(); cv = mCellNetworkAgent.getDisconnectedCV();
@@ -1340,7 +1522,7 @@ public class ConnectivityServiceTest extends AndroidTestCase {
MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); MockNetworkAgent mmsNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS); mmsNetworkAgent.addCapability(NET_CAPABILITY_MMS);
mmsNetworkAgent.connectWithoutInternet(); mmsNetworkAgent.connectWithoutInternet();
networkCallback.expectCallback(CallbackState.AVAILABLE); networkCallback.expectCallback(CallbackState.AVAILABLE, mmsNetworkAgent);
verifyActiveNetwork(TRANSPORT_CELLULAR); verifyActiveNetwork(TRANSPORT_CELLULAR);
// Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent // Test releasing MMS NetworkRequest does not disconnect main cellular NetworkAgent
cv = mmsNetworkAgent.getDisconnectedCV(); cv = mmsNetworkAgent.getDisconnectedCV();
@@ -1366,36 +1548,36 @@ public class ConnectivityServiceTest extends AndroidTestCase {
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
String firstRedirectUrl = "http://example.com/firstPath"; String firstRedirectUrl = "http://example.com/firstPath";
mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl); mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
captivePortalCallback.expectCallback(CallbackState.AVAILABLE); captivePortalCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl); assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
// Take down network. // Take down network.
// Expect onLost callback. // Expect onLost callback.
mWiFiNetworkAgent.disconnect(); mWiFiNetworkAgent.disconnect();
captivePortalCallback.expectCallback(CallbackState.LOST); captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
// Bring up a network with a captive portal. // Bring up a network with a captive portal.
// Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL. // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
String secondRedirectUrl = "http://example.com/secondPath"; String secondRedirectUrl = "http://example.com/secondPath";
mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl); mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
captivePortalCallback.expectCallback(CallbackState.AVAILABLE); captivePortalCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl); assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
// Make captive portal disappear then revalidate. // Make captive portal disappear then revalidate.
// Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL. // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204; mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 204;
mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true); mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
captivePortalCallback.expectCallback(CallbackState.LOST); captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
// Expect NET_CAPABILITY_VALIDATED onAvailable callback. // Expect NET_CAPABILITY_VALIDATED onAvailable callback.
validatedCallback.expectCallback(CallbackState.AVAILABLE); validatedCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
// Break network connectivity. // Break network connectivity.
// Expect NET_CAPABILITY_VALIDATED onLost callback. // Expect NET_CAPABILITY_VALIDATED onLost callback.
mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 500; mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 500;
mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false); mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
validatedCallback.expectCallback(CallbackState.LOST); validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
} }
@SmallTest @SmallTest
@@ -1410,7 +1592,7 @@ public class ConnectivityServiceTest extends AndroidTestCase {
// do nothing - should get here // do nothing - should get here
} }
assertTrue("NetworkReqeuest builder with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER", assertTrue("NetworkRequest builder with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER",
execptionCalled); execptionCalled);
try { try {
@@ -1477,6 +1659,78 @@ public class ConnectivityServiceTest extends AndroidTestCase {
defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent); defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
} }
@SmallTest
public void testRequestBenchmark() throws Exception {
// Benchmarks connecting and switching performance in the presence of a large number of
// NetworkRequests.
// 1. File NUM_REQUESTS requests.
// 2. Have a network connect. Wait for NUM_REQUESTS onAvailable callbacks to fire.
// 3. Have a new network connect and outscore the previous. Wait for NUM_REQUESTS onLosing
// and NUM_REQUESTS onAvailable callbacks to fire.
// See how long it took.
final int NUM_REQUESTS = 90;
final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
final NetworkCallback[] callbacks = new NetworkCallback[NUM_REQUESTS];
final CountDownLatch availableLatch = new CountDownLatch(NUM_REQUESTS);
final CountDownLatch losingLatch = new CountDownLatch(NUM_REQUESTS);
final int REGISTER_TIME_LIMIT_MS = 100;
long startTime = System.currentTimeMillis();
for (int i = 0; i < NUM_REQUESTS; i++) {
callbacks[i] = new NetworkCallback() {
@Override public void onAvailable(Network n) { availableLatch.countDown(); }
@Override public void onLosing(Network n, int t) { losingLatch.countDown(); }
};
mCm.registerNetworkCallback(request, callbacks[i]);
}
long timeTaken = System.currentTimeMillis() - startTime;
String msg = String.format("Register %d callbacks: %dms, acceptable %dms",
NUM_REQUESTS, timeTaken, REGISTER_TIME_LIMIT_MS);
Log.d(TAG, msg);
assertTrue(msg, timeTaken < REGISTER_TIME_LIMIT_MS);
final int CONNECT_TIME_LIMIT_MS = 30;
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
// Don't request that the network validate, because otherwise connect() will block until
// the network gets NET_CAPABILITY_VALIDATED, after all the callbacks below have fired,
// and we won't actually measure anything.
mCellNetworkAgent.connect(false);
startTime = System.currentTimeMillis();
if (!availableLatch.await(CONNECT_TIME_LIMIT_MS, TimeUnit.MILLISECONDS)) {
fail(String.format("Only dispatched %d/%d onAvailable callbacks in %dms",
NUM_REQUESTS - availableLatch.getCount(), NUM_REQUESTS,
CONNECT_TIME_LIMIT_MS));
}
timeTaken = System.currentTimeMillis() - startTime;
Log.d(TAG, String.format("Connect, %d callbacks: %dms, acceptable %dms",
NUM_REQUESTS, timeTaken, CONNECT_TIME_LIMIT_MS));
final int SWITCH_TIME_LIMIT_MS = 30;
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
// Give wifi a high enough score that we'll linger cell when wifi comes up.
mWiFiNetworkAgent.adjustScore(40);
mWiFiNetworkAgent.connect(false);
startTime = System.currentTimeMillis();
if (!losingLatch.await(SWITCH_TIME_LIMIT_MS, TimeUnit.MILLISECONDS)) {
fail(String.format("Only dispatched %d/%d onLosing callbacks in %dms",
NUM_REQUESTS - losingLatch.getCount(), NUM_REQUESTS, SWITCH_TIME_LIMIT_MS));
}
timeTaken = System.currentTimeMillis() - startTime;
Log.d(TAG, String.format("Linger, %d callbacks: %dms, acceptable %dms",
NUM_REQUESTS, timeTaken, SWITCH_TIME_LIMIT_MS));
final int UNREGISTER_TIME_LIMIT_MS = 10;
startTime = System.currentTimeMillis();
for (int i = 0; i < NUM_REQUESTS; i++) {
mCm.unregisterNetworkCallback(callbacks[i]);
}
timeTaken = System.currentTimeMillis() - startTime;
msg = String.format("Unregister %d callbacks: %dms, acceptable %dms",
NUM_REQUESTS, timeTaken, UNREGISTER_TIME_LIMIT_MS);
Log.d(TAG, msg);
assertTrue(msg, timeTaken < UNREGISTER_TIME_LIMIT_MS);
}
@SmallTest @SmallTest
public void testMobileDataAlwaysOn() throws Exception { public void testMobileDataAlwaysOn() throws Exception {
final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
@@ -1520,7 +1774,7 @@ public class ConnectivityServiceTest extends AndroidTestCase {
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
testFactory.expectAddRequests(2); // Because the cell request changes score twice. testFactory.expectAddRequests(2); // Because the cell request changes score twice.
mCellNetworkAgent.connect(true); mCellNetworkAgent.connect(true);
cellNetworkCallback.expectCallback(CallbackState.AVAILABLE); cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
testFactory.waitForNetworkRequests(2); testFactory.waitForNetworkRequests(2);
assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us. assertFalse(testFactory.getMyStartRequested()); // Because the cell network outscores us.
@@ -1536,7 +1790,7 @@ public class ConnectivityServiceTest extends AndroidTestCase {
testFactory.waitForNetworkRequests(1); testFactory.waitForNetworkRequests(1);
// ... and cell data to be torn down. // ... and cell data to be torn down.
cellNetworkCallback.expectCallback(CallbackState.LOST); cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
assertEquals(1, mCm.getAllNetworks().length); assertEquals(1, mCm.getAllNetworks().length);
testFactory.unregister(); testFactory.unregister();