Add detailed test coverage for lingering.
Bug: 23113288
Change-Id: I65784f3589378d97f3c824e600f21f361be8741e
diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
index d654dfc..14744d0 100644
--- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
@@ -17,6 +17,7 @@
package com.android.server;
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_WIFI;
import static android.net.ConnectivityManager.getNetworkTypeName;
@@ -101,6 +102,7 @@
private WrappedConnectivityManager mCm;
private MockNetworkAgent mWiFiNetworkAgent;
private MockNetworkAgent mCellNetworkAgent;
+ private MockNetworkAgent mEthernetNetworkAgent;
// 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
@@ -244,6 +246,9 @@
mNetworkCapabilities = new NetworkCapabilities();
mNetworkCapabilities.addTransportType(transport);
switch (transport) {
+ case TRANSPORT_ETHERNET:
+ mScore = 70;
+ break;
case TRANSPORT_WIFI:
mScore = 60;
break;
@@ -305,6 +310,11 @@
mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
}
+ public void removeCapability(int capability) {
+ mNetworkCapabilities.removeCapability(capability);
+ mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
+ }
+
public void setSignalStrength(int signalStrength) {
mNetworkCapabilities.setSignalStrength(signalStrength);
mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
@@ -704,12 +714,14 @@
private int transportToLegacyType(int transport) {
switch (transport) {
+ case TRANSPORT_ETHERNET:
+ return TYPE_ETHERNET;
case TRANSPORT_WIFI:
return TYPE_WIFI;
case TRANSPORT_CELLULAR:
return TYPE_MOBILE;
default:
- throw new IllegalStateException("Unknown transport" + transport);
+ throw new IllegalStateException("Unknown transport " + transport);
}
}
@@ -1064,15 +1076,12 @@
CallbackInfo expected = new CallbackInfo(
state,
(mockAgent != null) ? mockAgent.getNetwork() : null);
- CallbackInfo actual;
try {
- actual = mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ assertEquals("Unexpected callback:",
+ expected, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
} catch (InterruptedException e) {
fail("Did not receive expected " + expected + " after " + TIMEOUT_MS + "ms");
- actual = null; // Or the compiler says it might be uninitialized.
}
-
- assertEquals("Unexpected callback:", expected, actual);
}
void assertNoCallback() {
@@ -1179,6 +1188,150 @@
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());
+
+ 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 with a score of 70.
+ // Cell is lingered because it would not satisfy any reques, even if it validated.
+ 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 {
// Verify NOT_RESTRICTED is set appropriately
final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)