Merge "Add a mode for cell radios unable to time share"
This commit is contained in:
@@ -1055,6 +1055,14 @@ public final class NetworkCapabilities implements Parcelable {
|
|||||||
return isValidTransport(transportType) && ((mTransportTypes & (1 << transportType)) != 0);
|
return isValidTransport(transportType) && ((mTransportTypes & (1 << transportType)) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true iff this NetworkCapabilities has the specified transport and no other.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public boolean hasSingleTransport(@Transport int transportType) {
|
||||||
|
return mTransportTypes == (1 << transportType);
|
||||||
|
}
|
||||||
|
|
||||||
private void combineTransportTypes(NetworkCapabilities nc) {
|
private void combineTransportTypes(NetworkCapabilities nc) {
|
||||||
this.mTransportTypes |= nc.mTransportTypes;
|
this.mTransportTypes |= nc.mTransportTypes;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,4 +125,15 @@
|
|||||||
details on what is happening. -->
|
details on what is happening. -->
|
||||||
<bool name="config_partialConnectivityNotifiedAsNoInternet">false</bool>
|
<bool name="config_partialConnectivityNotifiedAsNoInternet">false</bool>
|
||||||
|
|
||||||
|
<!-- Whether the cell radio of the device is capable of timesharing.
|
||||||
|
|
||||||
|
Whether the cell radio is capable of timesharing between two different networks
|
||||||
|
even for a few seconds. When this is false, the networking stack will ask telephony
|
||||||
|
networks to disconnect immediately, instead of lingering, when outscored by some
|
||||||
|
other telephony network (typically on another subscription). This deprives apps
|
||||||
|
of a chance to gracefully migrate to the new network and degrades the experience
|
||||||
|
for apps, so it should only be set to false when timesharing on the cell radio has
|
||||||
|
extreme adverse effects on performance of the new network.
|
||||||
|
-->
|
||||||
|
<bool translatable="false" name="config_cellular_radio_timesharing_capable">true</bool>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
<item type="bool" name="config_partialConnectivityNotifiedAsNoInternet"/>
|
<item type="bool" name="config_partialConnectivityNotifiedAsNoInternet"/>
|
||||||
<item type="drawable" name="stat_notify_wifi_in_range"/>
|
<item type="drawable" name="stat_notify_wifi_in_range"/>
|
||||||
<item type="drawable" name="stat_notify_rssi_in_range"/>
|
<item type="drawable" name="stat_notify_rssi_in_range"/>
|
||||||
|
<item type="bool" name="config_cellular_radio_timesharing_capable" />
|
||||||
</policy>
|
</policy>
|
||||||
</overlayable>
|
</overlayable>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ import static android.net.NetworkCapabilities.TRANSPORT_TEST;
|
|||||||
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
|
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
|
||||||
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
|
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
|
||||||
import static android.net.NetworkRequest.Type.LISTEN_FOR_BEST;
|
import static android.net.NetworkRequest.Type.LISTEN_FOR_BEST;
|
||||||
|
import static android.net.NetworkScore.POLICY_TRANSPORT_PRIMARY;
|
||||||
import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST;
|
import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST;
|
||||||
import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST_ONLY;
|
import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST_ONLY;
|
||||||
import static android.net.shared.NetworkMonitorUtils.isPrivateDnsValidationRequired;
|
import static android.net.shared.NetworkMonitorUtils.isPrivateDnsValidationRequired;
|
||||||
@@ -335,6 +336,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
protected int mLingerDelayMs; // Can't be final, or test subclass constructors can't change it.
|
protected int mLingerDelayMs; // Can't be final, or test subclass constructors can't change it.
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
protected int mNascentDelayMs;
|
protected int mNascentDelayMs;
|
||||||
|
// True if the cell radio of the device is capable of time-sharing.
|
||||||
|
@VisibleForTesting
|
||||||
|
protected boolean mCellularRadioTimesharingCapable = true;
|
||||||
|
|
||||||
// How long to delay to removal of a pending intent based request.
|
// How long to delay to removal of a pending intent based request.
|
||||||
// See ConnectivitySettingsManager.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS
|
// See ConnectivitySettingsManager.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS
|
||||||
@@ -1375,6 +1379,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
NetworkCapabilities.NET_CAPABILITY_VEHICLE_INTERNAL,
|
NetworkCapabilities.NET_CAPABILITY_VEHICLE_INTERNAL,
|
||||||
NetworkRequest.Type.BACKGROUND_REQUEST);
|
NetworkRequest.Type.BACKGROUND_REQUEST);
|
||||||
|
|
||||||
|
mLingerDelayMs = mSystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS);
|
||||||
|
// TODO: Consider making the timer customizable.
|
||||||
|
mNascentDelayMs = DEFAULT_NASCENT_DELAY_MS;
|
||||||
|
mCellularRadioTimesharingCapable =
|
||||||
|
mResources.get().getBoolean(R.bool.config_cellular_radio_timesharing_capable);
|
||||||
|
|
||||||
mHandlerThread = mDeps.makeHandlerThread();
|
mHandlerThread = mDeps.makeHandlerThread();
|
||||||
mHandlerThread.start();
|
mHandlerThread.start();
|
||||||
mHandler = new InternalHandler(mHandlerThread.getLooper());
|
mHandler = new InternalHandler(mHandlerThread.getLooper());
|
||||||
@@ -1385,10 +1395,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
mReleasePendingIntentDelayMs = Settings.Secure.getInt(context.getContentResolver(),
|
mReleasePendingIntentDelayMs = Settings.Secure.getInt(context.getContentResolver(),
|
||||||
ConnectivitySettingsManager.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, 5_000);
|
ConnectivitySettingsManager.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, 5_000);
|
||||||
|
|
||||||
mLingerDelayMs = mSystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS);
|
|
||||||
// TODO: Consider making the timer customizable.
|
|
||||||
mNascentDelayMs = DEFAULT_NASCENT_DELAY_MS;
|
|
||||||
|
|
||||||
mStatsManager = mContext.getSystemService(NetworkStatsManager.class);
|
mStatsManager = mContext.getSystemService(NetworkStatsManager.class);
|
||||||
mPolicyManager = mContext.getSystemService(NetworkPolicyManager.class);
|
mPolicyManager = mContext.getSystemService(NetworkPolicyManager.class);
|
||||||
mDnsResolver = Objects.requireNonNull(dnsresolver, "missing IDnsResolver");
|
mDnsResolver = Objects.requireNonNull(dnsresolver, "missing IDnsResolver");
|
||||||
@@ -7824,6 +7830,30 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
bundle.putParcelable(t.getClass().getSimpleName(), t);
|
bundle.putParcelable(t.getClass().getSimpleName(), t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether reassigning a request from an NAI to another can be done gracefully.
|
||||||
|
*
|
||||||
|
* When a request should be assigned to a new network, it is normally lingered to give
|
||||||
|
* time for apps to gracefully migrate their connections. When both networks are on the same
|
||||||
|
* radio, but that radio can't do time-sharing efficiently, this may end up being
|
||||||
|
* counter-productive because any traffic on the old network may drastically reduce the
|
||||||
|
* performance of the new network.
|
||||||
|
* The stack supports a configuration to let modem vendors state that their radio can't
|
||||||
|
* do time-sharing efficiently. If this configuration is set, the stack assumes moving
|
||||||
|
* from one cell network to another can't be done gracefully.
|
||||||
|
*
|
||||||
|
* @param oldNai the old network serving the request
|
||||||
|
* @param newNai the new network serving the request
|
||||||
|
* @return whether the switch can be graceful
|
||||||
|
*/
|
||||||
|
private boolean canSupportGracefulNetworkSwitch(@NonNull final NetworkAgentInfo oldSatisfier,
|
||||||
|
@NonNull final NetworkAgentInfo newSatisfier) {
|
||||||
|
if (mCellularRadioTimesharingCapable) return true;
|
||||||
|
return !oldSatisfier.networkCapabilities.hasSingleTransport(TRANSPORT_CELLULAR)
|
||||||
|
|| !newSatisfier.networkCapabilities.hasSingleTransport(TRANSPORT_CELLULAR)
|
||||||
|
|| !newSatisfier.getScore().hasPolicy(POLICY_TRANSPORT_PRIMARY);
|
||||||
|
}
|
||||||
|
|
||||||
private void teardownUnneededNetwork(NetworkAgentInfo nai) {
|
private void teardownUnneededNetwork(NetworkAgentInfo nai) {
|
||||||
if (nai.numRequestNetworkRequests() != 0) {
|
if (nai.numRequestNetworkRequests() != 0) {
|
||||||
for (int i = 0; i < nai.numNetworkRequests(); i++) {
|
for (int i = 0; i < nai.numNetworkRequests(); i++) {
|
||||||
@@ -8084,7 +8114,13 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
log(" accepting network in place of " + previousSatisfier.toShortString());
|
log(" accepting network in place of " + previousSatisfier.toShortString());
|
||||||
}
|
}
|
||||||
previousSatisfier.removeRequest(previousRequest.requestId);
|
previousSatisfier.removeRequest(previousRequest.requestId);
|
||||||
|
if (canSupportGracefulNetworkSwitch(previousSatisfier, newSatisfier)) {
|
||||||
|
// If this network switch can't be supported gracefully, the request is not
|
||||||
|
// lingered. This allows letting go of the network sooner to reclaim some
|
||||||
|
// performance on the new network, since the radio can't do both at the same
|
||||||
|
// time while preserving good performance.
|
||||||
previousSatisfier.lingerRequest(previousRequest.requestId, now);
|
previousSatisfier.lingerRequest(previousRequest.requestId, now);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (VDBG || DDBG) log(" accepting network in place of null");
|
if (VDBG || DDBG) log(" accepting network in place of null");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
|
|||||||
|
|
||||||
import static com.android.server.ConnectivityServiceTestUtils.transportToLegacyType;
|
import static com.android.server.ConnectivityServiceTestUtils.transportToLegacyType;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertFalse;
|
||||||
import static junit.framework.Assert.assertTrue;
|
import static junit.framework.Assert.assertTrue;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
@@ -310,6 +311,10 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork {
|
|||||||
assertTrue(mDisconnected.block(timeoutMs));
|
assertTrue(mDisconnected.block(timeoutMs));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void assertNotDisconnected(long timeoutMs) {
|
||||||
|
assertFalse(mDisconnected.block(timeoutMs));
|
||||||
|
}
|
||||||
|
|
||||||
public void sendLinkProperties(LinkProperties lp) {
|
public void sendLinkProperties(LinkProperties lp) {
|
||||||
mNetworkAgent.sendLinkProperties(lp);
|
mNetworkAgent.sendLinkProperties(lp);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1792,6 +1792,8 @@ public class ConnectivityServiceTest {
|
|||||||
doReturn(R.integer.config_networkAvoidBadWifi).when(mResources)
|
doReturn(R.integer.config_networkAvoidBadWifi).when(mResources)
|
||||||
.getIdentifier(eq("config_networkAvoidBadWifi"), eq("integer"), any());
|
.getIdentifier(eq("config_networkAvoidBadWifi"), eq("integer"), any());
|
||||||
doReturn(1).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
|
doReturn(1).when(mResources).getInteger(R.integer.config_networkAvoidBadWifi);
|
||||||
|
doReturn(true).when(mResources)
|
||||||
|
.getBoolean(R.bool.config_cellular_radio_timesharing_capable);
|
||||||
|
|
||||||
final ConnectivityResources connRes = mock(ConnectivityResources.class);
|
final ConnectivityResources connRes = mock(ConnectivityResources.class);
|
||||||
doReturn(mResources).when(connRes).get();
|
doReturn(mResources).when(connRes).get();
|
||||||
@@ -2273,8 +2275,22 @@ public class ConnectivityServiceTest {
|
|||||||
// After waitForIdle(), the message was processed and the service didn't crash.
|
// After waitForIdle(), the message was processed and the service didn't crash.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO : migrate to @Parameterized
|
||||||
@Test
|
@Test
|
||||||
public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
|
public void testValidatedCellularOutscoresUnvalidatedWiFi_CanTimeShare() throws Exception {
|
||||||
|
// The behavior of this test should be the same whether the radio can time share or not.
|
||||||
|
doTestValidatedCellularOutscoresUnvalidatedWiFi(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO : migrate to @Parameterized
|
||||||
|
@Test
|
||||||
|
public void testValidatedCellularOutscoresUnvalidatedWiFi_CannotTimeShare() throws Exception {
|
||||||
|
doTestValidatedCellularOutscoresUnvalidatedWiFi(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doTestValidatedCellularOutscoresUnvalidatedWiFi(
|
||||||
|
final boolean cellRadioTimesharingCapable) throws Exception {
|
||||||
|
mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
|
||||||
// Test bringing up unvalidated WiFi
|
// Test bringing up unvalidated WiFi
|
||||||
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
|
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
|
||||||
ExpectedBroadcast b = registerConnectivityBroadcast(1);
|
ExpectedBroadcast b = registerConnectivityBroadcast(1);
|
||||||
@@ -2308,8 +2324,21 @@ public class ConnectivityServiceTest {
|
|||||||
verifyNoNetwork();
|
verifyNoNetwork();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO : migrate to @Parameterized
|
||||||
@Test
|
@Test
|
||||||
public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
|
public void testUnvalidatedWifiOutscoresUnvalidatedCellular_CanTimeShare() throws Exception {
|
||||||
|
doTestUnvalidatedWifiOutscoresUnvalidatedCellular(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO : migrate to @Parameterized
|
||||||
|
@Test
|
||||||
|
public void testUnvalidatedWifiOutscoresUnvalidatedCellular_CannotTimeShare() throws Exception {
|
||||||
|
doTestUnvalidatedWifiOutscoresUnvalidatedCellular(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doTestUnvalidatedWifiOutscoresUnvalidatedCellular(
|
||||||
|
final boolean cellRadioTimesharingCapable) throws Exception {
|
||||||
|
mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
|
||||||
// Test bringing up unvalidated cellular.
|
// Test bringing up unvalidated cellular.
|
||||||
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
|
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
|
||||||
ExpectedBroadcast b = registerConnectivityBroadcast(1);
|
ExpectedBroadcast b = registerConnectivityBroadcast(1);
|
||||||
@@ -2334,8 +2363,21 @@ public class ConnectivityServiceTest {
|
|||||||
verifyNoNetwork();
|
verifyNoNetwork();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO : migrate to @Parameterized
|
||||||
@Test
|
@Test
|
||||||
public void testUnlingeringDoesNotValidate() throws Exception {
|
public void testUnlingeringDoesNotValidate_CanTimeShare() throws Exception {
|
||||||
|
doTestUnlingeringDoesNotValidate(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO : migrate to @Parameterized
|
||||||
|
@Test
|
||||||
|
public void testUnlingeringDoesNotValidate_CannotTimeShare() throws Exception {
|
||||||
|
doTestUnlingeringDoesNotValidate(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doTestUnlingeringDoesNotValidate(
|
||||||
|
final boolean cellRadioTimesharingCapable) throws Exception {
|
||||||
|
mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
|
||||||
// Test bringing up unvalidated WiFi.
|
// Test bringing up unvalidated WiFi.
|
||||||
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
|
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
|
||||||
ExpectedBroadcast b = registerConnectivityBroadcast(1);
|
ExpectedBroadcast b = registerConnectivityBroadcast(1);
|
||||||
@@ -2362,8 +2404,134 @@ public class ConnectivityServiceTest {
|
|||||||
NET_CAPABILITY_VALIDATED));
|
NET_CAPABILITY_VALIDATED));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO : migrate to @Parameterized
|
||||||
@Test
|
@Test
|
||||||
public void testCellularOutscoresWeakWifi() throws Exception {
|
public void testRequestMigrationToSameTransport_CanTimeShare() throws Exception {
|
||||||
|
// Simulate a device where the cell radio is capable of time sharing
|
||||||
|
mService.mCellularRadioTimesharingCapable = true;
|
||||||
|
doTestRequestMigrationToSameTransport(TRANSPORT_CELLULAR, true);
|
||||||
|
doTestRequestMigrationToSameTransport(TRANSPORT_WIFI, true);
|
||||||
|
doTestRequestMigrationToSameTransport(TRANSPORT_ETHERNET, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO : migrate to @Parameterized
|
||||||
|
@Test
|
||||||
|
public void testRequestMigrationToSameTransport_CannotTimeShare() throws Exception {
|
||||||
|
// Simulate a device where the cell radio is not capable of time sharing
|
||||||
|
mService.mCellularRadioTimesharingCapable = false;
|
||||||
|
doTestRequestMigrationToSameTransport(TRANSPORT_CELLULAR, false);
|
||||||
|
doTestRequestMigrationToSameTransport(TRANSPORT_WIFI, true);
|
||||||
|
doTestRequestMigrationToSameTransport(TRANSPORT_ETHERNET, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doTestRequestMigrationToSameTransport(final int transport,
|
||||||
|
final boolean expectLingering) throws Exception {
|
||||||
|
// To speed up tests the linger delay is very short by default in tests but this
|
||||||
|
// test needs to make sure the delay is not incurred so a longer value is safer (it
|
||||||
|
// reduces the risk that a bug exists but goes undetected). The alarm manager in the test
|
||||||
|
// throws and crashes CS if this is set to anything more than the below constant though.
|
||||||
|
mService.mLingerDelayMs = UNREASONABLY_LONG_ALARM_WAIT_MS;
|
||||||
|
|
||||||
|
final TestNetworkCallback generalCb = new TestNetworkCallback();
|
||||||
|
final TestNetworkCallback defaultCb = new TestNetworkCallback();
|
||||||
|
mCm.registerNetworkCallback(
|
||||||
|
new NetworkRequest.Builder().addTransportType(transport | transport).build(),
|
||||||
|
generalCb);
|
||||||
|
mCm.registerDefaultNetworkCallback(defaultCb);
|
||||||
|
|
||||||
|
// Bring up net agent 1
|
||||||
|
final TestNetworkAgentWrapper net1 = new TestNetworkAgentWrapper(transport);
|
||||||
|
net1.connect(true);
|
||||||
|
// Make sure the default request is on net 1
|
||||||
|
generalCb.expectAvailableThenValidatedCallbacks(net1);
|
||||||
|
defaultCb.expectAvailableThenValidatedCallbacks(net1);
|
||||||
|
|
||||||
|
// Bring up net 2 with primary and mms
|
||||||
|
final TestNetworkAgentWrapper net2 = new TestNetworkAgentWrapper(transport);
|
||||||
|
net2.addCapability(NET_CAPABILITY_MMS);
|
||||||
|
net2.setScore(new NetworkScore.Builder().setTransportPrimary(true).build());
|
||||||
|
net2.connect(true);
|
||||||
|
|
||||||
|
// Make sure the default request goes to net 2
|
||||||
|
generalCb.expectAvailableCallbacksUnvalidated(net2);
|
||||||
|
if (expectLingering) {
|
||||||
|
generalCb.expectCallback(CallbackEntry.LOSING, net1);
|
||||||
|
}
|
||||||
|
generalCb.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, net2);
|
||||||
|
defaultCb.expectAvailableDoubleValidatedCallbacks(net2);
|
||||||
|
|
||||||
|
// Make sure cell 1 is unwanted immediately if the radio can't time share, but only
|
||||||
|
// after some delay if it can.
|
||||||
|
if (expectLingering) {
|
||||||
|
net1.assertNotDisconnected(TEST_CALLBACK_TIMEOUT_MS); // always incurs the timeout
|
||||||
|
generalCb.assertNoCallback();
|
||||||
|
// assertNotDisconnected waited for TEST_CALLBACK_TIMEOUT_MS, so waiting for the
|
||||||
|
// linger period gives TEST_CALLBACK_TIMEOUT_MS time for the event to process.
|
||||||
|
net1.expectDisconnected(UNREASONABLY_LONG_ALARM_WAIT_MS);
|
||||||
|
} else {
|
||||||
|
net1.expectDisconnected(TEST_CALLBACK_TIMEOUT_MS);
|
||||||
|
}
|
||||||
|
net1.disconnect();
|
||||||
|
generalCb.expectCallback(CallbackEntry.LOST, net1);
|
||||||
|
|
||||||
|
// Remove primary from net 2
|
||||||
|
net2.setScore(new NetworkScore.Builder().build());
|
||||||
|
// Request MMS
|
||||||
|
final TestNetworkCallback mmsCallback = new TestNetworkCallback();
|
||||||
|
mCm.requestNetwork(new NetworkRequest.Builder().addCapability(NET_CAPABILITY_MMS).build(),
|
||||||
|
mmsCallback);
|
||||||
|
mmsCallback.expectAvailableCallbacksValidated(net2);
|
||||||
|
|
||||||
|
// Bring up net 3 with primary but without MMS
|
||||||
|
final TestNetworkAgentWrapper net3 = new TestNetworkAgentWrapper(transport);
|
||||||
|
net3.setScore(new NetworkScore.Builder().setTransportPrimary(true).build());
|
||||||
|
net3.connect(true);
|
||||||
|
|
||||||
|
// Make sure default goes to net 3, but the MMS request doesn't
|
||||||
|
generalCb.expectAvailableThenValidatedCallbacks(net3);
|
||||||
|
defaultCb.expectAvailableDoubleValidatedCallbacks(net3);
|
||||||
|
mmsCallback.assertNoCallback();
|
||||||
|
net2.assertNotDisconnected(TEST_CALLBACK_TIMEOUT_MS); // Always incurs the timeout
|
||||||
|
|
||||||
|
// Revoke MMS request and make sure net 2 is torn down with the appropriate delay
|
||||||
|
mCm.unregisterNetworkCallback(mmsCallback);
|
||||||
|
if (expectLingering) {
|
||||||
|
// If the radio can time share, the linger delay hasn't elapsed yet, so apps will
|
||||||
|
// get LOSING. If the radio can't time share, this is a hard loss, since the last
|
||||||
|
// request keeping up this network has been removed and the network isn't lingering
|
||||||
|
// for any other request.
|
||||||
|
generalCb.expectCallback(CallbackEntry.LOSING, net2);
|
||||||
|
net2.assertNotDisconnected(TEST_CALLBACK_TIMEOUT_MS);
|
||||||
|
generalCb.assertNoCallback();
|
||||||
|
net2.expectDisconnected(UNREASONABLY_LONG_ALARM_WAIT_MS);
|
||||||
|
} else {
|
||||||
|
net2.expectDisconnected(TEST_CALLBACK_TIMEOUT_MS);
|
||||||
|
}
|
||||||
|
net2.disconnect();
|
||||||
|
generalCb.expectCallback(CallbackEntry.LOST, net2);
|
||||||
|
defaultCb.assertNoCallback();
|
||||||
|
|
||||||
|
net3.disconnect();
|
||||||
|
mCm.unregisterNetworkCallback(defaultCb);
|
||||||
|
mCm.unregisterNetworkCallback(generalCb);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO : migrate to @Parameterized
|
||||||
|
@Test
|
||||||
|
public void testCellularOutscoresWeakWifi_CanTimeShare() throws Exception {
|
||||||
|
// The behavior of this test should be the same whether the radio can time share or not.
|
||||||
|
doTestCellularOutscoresWeakWifi(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO : migrate to @Parameterized
|
||||||
|
@Test
|
||||||
|
public void testCellularOutscoresWeakWifi_CannotTimeShare() throws Exception {
|
||||||
|
doTestCellularOutscoresWeakWifi(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doTestCellularOutscoresWeakWifi(
|
||||||
|
final boolean cellRadioTimesharingCapable) throws Exception {
|
||||||
|
mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
|
||||||
// Test bringing up validated cellular.
|
// Test bringing up validated cellular.
|
||||||
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
|
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
|
||||||
ExpectedBroadcast b = registerConnectivityBroadcast(1);
|
ExpectedBroadcast b = registerConnectivityBroadcast(1);
|
||||||
@@ -2388,8 +2556,21 @@ public class ConnectivityServiceTest {
|
|||||||
verifyActiveNetwork(TRANSPORT_WIFI);
|
verifyActiveNetwork(TRANSPORT_WIFI);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO : migrate to @Parameterized
|
||||||
@Test
|
@Test
|
||||||
public void testReapingNetwork() throws Exception {
|
public void testReapingNetwork_CanTimeShare() throws Exception {
|
||||||
|
doTestReapingNetwork(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO : migrate to @Parameterized
|
||||||
|
@Test
|
||||||
|
public void testReapingNetwork_CannotTimeShare() throws Exception {
|
||||||
|
doTestReapingNetwork(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doTestReapingNetwork(
|
||||||
|
final boolean cellRadioTimesharingCapable) throws Exception {
|
||||||
|
mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
|
||||||
// Test bringing up WiFi without NET_CAPABILITY_INTERNET.
|
// Test bringing up WiFi without NET_CAPABILITY_INTERNET.
|
||||||
// Expect it to be torn down immediately because it satisfies no requests.
|
// Expect it to be torn down immediately because it satisfies no requests.
|
||||||
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
|
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
|
||||||
@@ -2417,8 +2598,21 @@ public class ConnectivityServiceTest {
|
|||||||
mWiFiNetworkAgent.expectDisconnected();
|
mWiFiNetworkAgent.expectDisconnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO : migrate to @Parameterized
|
||||||
@Test
|
@Test
|
||||||
public void testCellularFallback() throws Exception {
|
public void testCellularFallback_CanTimeShare() throws Exception {
|
||||||
|
doTestCellularFallback(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO : migrate to @Parameterized
|
||||||
|
@Test
|
||||||
|
public void testCellularFallback_CannotTimeShare() throws Exception {
|
||||||
|
doTestCellularFallback(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doTestCellularFallback(
|
||||||
|
final boolean cellRadioTimesharingCapable) throws Exception {
|
||||||
|
mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
|
||||||
// Test bringing up validated cellular.
|
// Test bringing up validated cellular.
|
||||||
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
|
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
|
||||||
ExpectedBroadcast b = registerConnectivityBroadcast(1);
|
ExpectedBroadcast b = registerConnectivityBroadcast(1);
|
||||||
@@ -2455,8 +2649,21 @@ public class ConnectivityServiceTest {
|
|||||||
verifyActiveNetwork(TRANSPORT_WIFI);
|
verifyActiveNetwork(TRANSPORT_WIFI);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO : migrate to @Parameterized
|
||||||
@Test
|
@Test
|
||||||
public void testWiFiFallback() throws Exception {
|
public void testWiFiFallback_CanTimeShare() throws Exception {
|
||||||
|
doTestWiFiFallback(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO : migrate to @Parameterized
|
||||||
|
@Test
|
||||||
|
public void testWiFiFallback_CannotTimeShare() throws Exception {
|
||||||
|
doTestWiFiFallback(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doTestWiFiFallback(
|
||||||
|
final boolean cellRadioTimesharingCapable) throws Exception {
|
||||||
|
mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
|
||||||
// Test bringing up unvalidated WiFi.
|
// Test bringing up unvalidated WiFi.
|
||||||
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
|
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
|
||||||
ExpectedBroadcast b = registerConnectivityBroadcast(1);
|
ExpectedBroadcast b = registerConnectivityBroadcast(1);
|
||||||
|
|||||||
Reference in New Issue
Block a user