Make TestConnectivityManager send CONNECTIVITY_ACTION.
The tethering code still depends on CONNECTIVITY_ACTION for upstream selection. Make TestConnectivityManager send these broadcasts. Bug: 173068192 Test: atest TetheringTests Change-Id: I6a32e99fafef9d6d2abec438ffc68164ab4c5bdf
This commit is contained in:
@@ -16,19 +16,20 @@
|
||||
|
||||
package com.android.networkstack.tethering;
|
||||
|
||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.IConnectivityManager;
|
||||
import android.net.LinkProperties;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.NetworkRequest;
|
||||
import android.os.Handler;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@@ -39,6 +40,10 @@ import java.util.Set;
|
||||
/**
|
||||
* Simulates upstream switching and sending NetworkCallbacks and CONNECTIVITY_ACTION broadcasts.
|
||||
*
|
||||
* Unlike any real networking code, this class is single-threaded and entirely synchronous.
|
||||
* The effects of all method calls (including sending fake broadcasts, sending callbacks, etc.) are
|
||||
* performed immediately on the caller's thread before returning.
|
||||
*
|
||||
* TODO: this duplicates a fair amount of code from ConnectivityManager and ConnectivityService.
|
||||
* Consider using a ConnectivityService object instead, as used in ConnectivityServiceTest.
|
||||
*
|
||||
@@ -63,11 +68,21 @@ public class TestConnectivityManager extends ConnectivityManager {
|
||||
public Map<NetworkCallback, Integer> legacyTypeMap = new HashMap<>();
|
||||
|
||||
private final NetworkRequest mDefaultRequest;
|
||||
private final Context mContext;
|
||||
|
||||
private int mNetworkId = 100;
|
||||
|
||||
/**
|
||||
* Constructs a TestConnectivityManager.
|
||||
* @param ctx the context to use. Must be a fake or a mock because otherwise the test will
|
||||
* attempt to send real broadcasts and resulting in permission denials.
|
||||
* @param svc an IConnectivityManager. Should be a fake or a mock.
|
||||
* @param defaultRequest the default NetworkRequest that will be used by Tethering.
|
||||
*/
|
||||
public TestConnectivityManager(Context ctx, IConnectivityManager svc,
|
||||
NetworkRequest defaultRequest) {
|
||||
super(ctx, svc);
|
||||
mContext = ctx;
|
||||
mDefaultRequest = defaultRequest;
|
||||
}
|
||||
|
||||
@@ -109,6 +124,13 @@ public class TestConnectivityManager extends ConnectivityManager {
|
||||
final TestNetworkAgent formerDefault = defaultNetwork;
|
||||
defaultNetwork = agent;
|
||||
|
||||
if (formerDefault != null) {
|
||||
sendConnectivityAction(formerDefault.legacyType, false /* connected */);
|
||||
}
|
||||
if (defaultNetwork != null) {
|
||||
sendConnectivityAction(defaultNetwork.legacyType, true /* connected */);
|
||||
}
|
||||
|
||||
for (NetworkCallback cb : trackingDefault) {
|
||||
if (defaultNetwork != null) {
|
||||
cb.onAvailable(defaultNetwork.networkId);
|
||||
@@ -194,24 +216,72 @@ public class TestConnectivityManager extends ConnectivityManager {
|
||||
assertFalse(requested.containsKey(cb));
|
||||
}
|
||||
|
||||
private void sendConnectivityAction(int type, boolean connected) {
|
||||
NetworkInfo ni = new NetworkInfo(type, 0 /* subtype */, getNetworkTypeName(type),
|
||||
"" /* subtypeName */);
|
||||
NetworkInfo.DetailedState state = connected
|
||||
? NetworkInfo.DetailedState.CONNECTED
|
||||
: NetworkInfo.DetailedState.DISCONNECTED;
|
||||
ni.setDetailedState(state, "" /* reason */, "" /* extraInfo */);
|
||||
Intent intent = new Intent(CONNECTIVITY_ACTION);
|
||||
intent.putExtra(EXTRA_NETWORK_INFO, ni);
|
||||
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
|
||||
}
|
||||
|
||||
public static class TestNetworkAgent {
|
||||
public final TestConnectivityManager cm;
|
||||
public final Network networkId;
|
||||
public final int transportType;
|
||||
public final NetworkCapabilities networkCapabilities;
|
||||
public final LinkProperties linkProperties;
|
||||
// TODO: delete when tethering no longer uses CONNECTIVITY_ACTION.
|
||||
public final int legacyType;
|
||||
|
||||
public TestNetworkAgent(TestConnectivityManager cm, int transportType) {
|
||||
public TestNetworkAgent(TestConnectivityManager cm, NetworkCapabilities nc) {
|
||||
this.cm = cm;
|
||||
this.networkId = new Network(cm.getNetworkId());
|
||||
this.transportType = transportType;
|
||||
networkCapabilities = new NetworkCapabilities();
|
||||
networkCapabilities.addTransportType(transportType);
|
||||
networkCapabilities.addCapability(NET_CAPABILITY_INTERNET);
|
||||
networkCapabilities = copy(nc);
|
||||
linkProperties = new LinkProperties();
|
||||
legacyType = toLegacyType(nc);
|
||||
}
|
||||
|
||||
public TestNetworkAgent(TestConnectivityManager cm, UpstreamNetworkState state) {
|
||||
this.cm = cm;
|
||||
networkId = state.network;
|
||||
networkCapabilities = state.networkCapabilities;
|
||||
linkProperties = state.linkProperties;
|
||||
this.legacyType = toLegacyType(networkCapabilities);
|
||||
}
|
||||
|
||||
private static int toLegacyType(NetworkCapabilities nc) {
|
||||
for (int type = 0; type < ConnectivityManager.TYPE_TEST; type++) {
|
||||
if (matchesLegacyType(nc, type)) return type;
|
||||
}
|
||||
throw new IllegalArgumentException(("Can't determine legacy type for: ") + nc);
|
||||
}
|
||||
|
||||
private static boolean matchesLegacyType(NetworkCapabilities nc, int legacyType) {
|
||||
final NetworkCapabilities typeNc;
|
||||
try {
|
||||
typeNc = ConnectivityManager.networkCapabilitiesForType(legacyType);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// networkCapabilitiesForType does not support all legacy types.
|
||||
return false;
|
||||
}
|
||||
return typeNc.satisfiedByNetworkCapabilities(nc);
|
||||
}
|
||||
|
||||
private boolean matchesLegacyType(int legacyType) {
|
||||
return matchesLegacyType(networkCapabilities, legacyType);
|
||||
}
|
||||
|
||||
public void fakeConnect() {
|
||||
for (NetworkRequest request : cm.requested.values()) {
|
||||
if (matchesLegacyType(request.legacyType)) {
|
||||
cm.sendConnectivityAction(legacyType, true /* connected */);
|
||||
// In practice, a given network can match only one legacy type.
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (NetworkCallback cb : cm.listening.keySet()) {
|
||||
cb.onAvailable(networkId);
|
||||
cb.onCapabilitiesChanged(networkId, copy(networkCapabilities));
|
||||
@@ -220,6 +290,12 @@ public class TestConnectivityManager extends ConnectivityManager {
|
||||
}
|
||||
|
||||
public void fakeDisconnect() {
|
||||
for (NetworkRequest request : cm.requested.values()) {
|
||||
if (matchesLegacyType(request.legacyType)) {
|
||||
cm.sendConnectivityAction(legacyType, false /* connected */);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (NetworkCallback cb : cm.listening.keySet()) {
|
||||
cb.onLost(networkId);
|
||||
}
|
||||
|
||||
@@ -85,6 +85,13 @@ public class UpstreamNetworkMonitorTest {
|
||||
// any specific TRANSPORT_* is sufficient to identify this request.
|
||||
private static final NetworkRequest sDefaultRequest = new NetworkRequest.Builder().build();
|
||||
|
||||
private static final NetworkCapabilities CELL_CAPABILITIES = new NetworkCapabilities.Builder()
|
||||
.addTransportType(TRANSPORT_CELLULAR).addCapability(NET_CAPABILITY_INTERNET).build();
|
||||
private static final NetworkCapabilities DUN_CAPABILITIES = new NetworkCapabilities.Builder()
|
||||
.addTransportType(TRANSPORT_CELLULAR).addCapability(NET_CAPABILITY_DUN).build();
|
||||
private static final NetworkCapabilities WIFI_CAPABILITIES = new NetworkCapabilities.Builder()
|
||||
.addTransportType(TRANSPORT_WIFI).addCapability(NET_CAPABILITY_INTERNET).build();
|
||||
|
||||
@Mock private Context mContext;
|
||||
@Mock private EntitlementManager mEntitleMgr;
|
||||
@Mock private IConnectivityManager mCS;
|
||||
@@ -288,7 +295,7 @@ public class UpstreamNetworkMonitorTest {
|
||||
// There are no networks, so there is nothing to select.
|
||||
assertSatisfiesLegacyType(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes));
|
||||
|
||||
final TestNetworkAgent wifiAgent = new TestNetworkAgent(mCM, TRANSPORT_WIFI);
|
||||
final TestNetworkAgent wifiAgent = new TestNetworkAgent(mCM, WIFI_CAPABILITIES);
|
||||
wifiAgent.fakeConnect();
|
||||
// WiFi is up, we should prefer it.
|
||||
assertSatisfiesLegacyType(TYPE_WIFI, mUNM.selectPreferredUpstreamType(preferredTypes));
|
||||
@@ -296,7 +303,7 @@ public class UpstreamNetworkMonitorTest {
|
||||
// There are no networks, so there is nothing to select.
|
||||
assertSatisfiesLegacyType(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes));
|
||||
|
||||
final TestNetworkAgent cellAgent = new TestNetworkAgent(mCM, TRANSPORT_CELLULAR);
|
||||
final TestNetworkAgent cellAgent = new TestNetworkAgent(mCM, CELL_CAPABILITIES);
|
||||
cellAgent.fakeConnect();
|
||||
assertSatisfiesLegacyType(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes));
|
||||
|
||||
@@ -337,8 +344,7 @@ public class UpstreamNetworkMonitorTest {
|
||||
mUNM.updateMobileRequiresDun(true);
|
||||
assertSatisfiesLegacyType(TYPE_WIFI, mUNM.selectPreferredUpstreamType(preferredTypes));
|
||||
|
||||
final TestNetworkAgent dunAgent = new TestNetworkAgent(mCM, TRANSPORT_CELLULAR);
|
||||
dunAgent.networkCapabilities.addCapability(NET_CAPABILITY_DUN);
|
||||
final TestNetworkAgent dunAgent = new TestNetworkAgent(mCM, DUN_CAPABILITIES);
|
||||
dunAgent.fakeConnect();
|
||||
|
||||
// WiFi is still preferred.
|
||||
@@ -370,7 +376,7 @@ public class UpstreamNetworkMonitorTest {
|
||||
mUNM.updateMobileRequiresDun(false);
|
||||
|
||||
// [0] Mobile connects, DUN not required -> mobile selected.
|
||||
final TestNetworkAgent cellAgent = new TestNetworkAgent(mCM, TRANSPORT_CELLULAR);
|
||||
final TestNetworkAgent cellAgent = new TestNetworkAgent(mCM, CELL_CAPABILITIES);
|
||||
cellAgent.fakeConnect();
|
||||
mCM.makeDefaultNetwork(cellAgent);
|
||||
assertEquals(cellAgent.networkId, mUNM.getCurrentPreferredUpstream().network);
|
||||
@@ -381,7 +387,7 @@ public class UpstreamNetworkMonitorTest {
|
||||
when(mEntitleMgr.isCellularUpstreamPermitted()).thenReturn(true);
|
||||
|
||||
// [2] WiFi connects but not validated/promoted to default -> mobile selected.
|
||||
final TestNetworkAgent wifiAgent = new TestNetworkAgent(mCM, TRANSPORT_WIFI);
|
||||
final TestNetworkAgent wifiAgent = new TestNetworkAgent(mCM, WIFI_CAPABILITIES);
|
||||
wifiAgent.fakeConnect();
|
||||
assertEquals(cellAgent.networkId, mUNM.getCurrentPreferredUpstream().network);
|
||||
|
||||
@@ -401,7 +407,7 @@ public class UpstreamNetworkMonitorTest {
|
||||
// into UNM we should test for this here.
|
||||
|
||||
// [6] DUN network arrives -> DUN selected
|
||||
final TestNetworkAgent dunAgent = new TestNetworkAgent(mCM, TRANSPORT_CELLULAR);
|
||||
final TestNetworkAgent dunAgent = new TestNetworkAgent(mCM, CELL_CAPABILITIES);
|
||||
dunAgent.networkCapabilities.addCapability(NET_CAPABILITY_DUN);
|
||||
dunAgent.networkCapabilities.removeCapability(NET_CAPABILITY_INTERNET);
|
||||
dunAgent.fakeConnect();
|
||||
@@ -424,7 +430,7 @@ public class UpstreamNetworkMonitorTest {
|
||||
final Set<String> alreadySeen = new HashSet<>();
|
||||
|
||||
// [1] Pretend Wi-Fi connects.
|
||||
final TestNetworkAgent wifiAgent = new TestNetworkAgent(mCM, TRANSPORT_WIFI);
|
||||
final TestNetworkAgent wifiAgent = new TestNetworkAgent(mCM, WIFI_CAPABILITIES);
|
||||
final LinkProperties wifiLp = wifiAgent.linkProperties;
|
||||
wifiLp.setInterfaceName("wlan0");
|
||||
final String[] wifi_addrs = {
|
||||
@@ -451,7 +457,7 @@ public class UpstreamNetworkMonitorTest {
|
||||
assertEquals(alreadySeen.size(), local.size());
|
||||
|
||||
// [2] Pretend mobile connects.
|
||||
final TestNetworkAgent cellAgent = new TestNetworkAgent(mCM, TRANSPORT_CELLULAR);
|
||||
final TestNetworkAgent cellAgent = new TestNetworkAgent(mCM, CELL_CAPABILITIES);
|
||||
final LinkProperties cellLp = cellAgent.linkProperties;
|
||||
cellLp.setInterfaceName("rmnet_data0");
|
||||
final String[] cell_addrs = {
|
||||
@@ -472,9 +478,7 @@ public class UpstreamNetworkMonitorTest {
|
||||
assertEquals(alreadySeen.size(), local.size());
|
||||
|
||||
// [3] Pretend DUN connects.
|
||||
final TestNetworkAgent dunAgent = new TestNetworkAgent(mCM, TRANSPORT_CELLULAR);
|
||||
dunAgent.networkCapabilities.addCapability(NET_CAPABILITY_DUN);
|
||||
dunAgent.networkCapabilities.removeCapability(NET_CAPABILITY_INTERNET);
|
||||
final TestNetworkAgent dunAgent = new TestNetworkAgent(mCM, DUN_CAPABILITIES);
|
||||
final LinkProperties dunLp = dunAgent.linkProperties;
|
||||
dunLp.setInterfaceName("rmnet_data1");
|
||||
final String[] dun_addrs = {
|
||||
@@ -524,11 +528,11 @@ public class UpstreamNetworkMonitorTest {
|
||||
mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr);
|
||||
mUNM.startObserveAllNetworks();
|
||||
// Setup wifi and make wifi as default network.
|
||||
final TestNetworkAgent wifiAgent = new TestNetworkAgent(mCM, TRANSPORT_WIFI);
|
||||
final TestNetworkAgent wifiAgent = new TestNetworkAgent(mCM, WIFI_CAPABILITIES);
|
||||
wifiAgent.fakeConnect();
|
||||
mCM.makeDefaultNetwork(wifiAgent);
|
||||
// Setup mobile network.
|
||||
final TestNetworkAgent cellAgent = new TestNetworkAgent(mCM, TRANSPORT_CELLULAR);
|
||||
final TestNetworkAgent cellAgent = new TestNetworkAgent(mCM, CELL_CAPABILITIES);
|
||||
cellAgent.fakeConnect();
|
||||
|
||||
assertSatisfiesLegacyType(TYPE_MOBILE_HIPRI,
|
||||
|
||||
Reference in New Issue
Block a user