Loading services/core/java/com/android/server/connectivity/Tethering.java +2 −54 Original line number Diff line number Diff line Loading @@ -1247,8 +1247,8 @@ public class Tethering extends BaseNetworkObserver { protected void chooseUpstreamType(boolean tryCell) { updateConfiguration(); // TODO - remove? final int upstreamType = findPreferredUpstreamType( getConnectivityManager(), mConfig); final int upstreamType = mUpstreamNetworkMonitor.selectPreferredUpstreamType( mConfig.preferredUpstreamIfaceTypes); if (upstreamType == ConnectivityManager.TYPE_NONE) { if (tryCell) { mUpstreamNetworkMonitor.registerMobileNetworkRequest(); Loading @@ -1260,58 +1260,6 @@ public class Tethering extends BaseNetworkObserver { setUpstreamByType(upstreamType); } // TODO: Move this function into UpstreamNetworkMonitor. protected int findPreferredUpstreamType(ConnectivityManager cm, TetheringConfiguration cfg) { int upType = ConnectivityManager.TYPE_NONE; if (VDBG) { Log.d(TAG, "chooseUpstreamType has upstream iface types:"); for (Integer netType : cfg.preferredUpstreamIfaceTypes) { Log.d(TAG, " " + netType); } } for (Integer netType : cfg.preferredUpstreamIfaceTypes) { NetworkInfo info = cm.getNetworkInfo(netType.intValue()); // TODO: if the network is suspended we should consider // that to be the same as connected here. if ((info != null) && info.isConnected()) { upType = netType.intValue(); break; } } final int preferredUpstreamMobileApn = cfg.isDunRequired ? ConnectivityManager.TYPE_MOBILE_DUN : ConnectivityManager.TYPE_MOBILE_HIPRI; mLog.log(String.format( "findPreferredUpstreamType(), preferredApn=%s, got type=%s", getNetworkTypeName(preferredUpstreamMobileApn), getNetworkTypeName(upType))); switch (upType) { case ConnectivityManager.TYPE_MOBILE_DUN: case ConnectivityManager.TYPE_MOBILE_HIPRI: // If we're on DUN, put our own grab on it. mUpstreamNetworkMonitor.registerMobileNetworkRequest(); break; case ConnectivityManager.TYPE_NONE: break; default: /* If we've found an active upstream connection that's not DUN/HIPRI * we should stop any outstanding DUN/HIPRI start requests. * * If we found NONE we don't want to do this as we want any previous * requests to keep trying to bring up something we can use. */ mUpstreamNetworkMonitor.releaseMobileNetworkRequest(); break; } return upType; } protected void setUpstreamByType(int upType) { final ConnectivityManager cm = getConnectivityManager(); Network network = null; Loading services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java +70 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server.connectivity.tethering; import static android.net.ConnectivityManager.getNetworkTypeName; import static android.net.ConnectivityManager.TYPE_NONE; import static android.net.ConnectivityManager.TYPE_MOBILE_DUN; import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI; Loading Loading @@ -176,6 +178,41 @@ public class UpstreamNetworkMonitor { return (network != null) ? mNetworkMap.get(network) : null; } // So many TODOs here, but chief among them is: make this functionality an // integral part of this class such that whenever a higher priority network // becomes available and useful we (a) file a request to keep it up as // necessary and (b) change all upstream tracking state accordingly (by // passing LinkProperties up to Tethering). // // Next TODO: return NetworkState instead of just the type. public int selectPreferredUpstreamType(Iterable<Integer> preferredTypes) { final TypeStatePair typeStatePair = findFirstAvailableUpstreamByType( mNetworkMap.values(), preferredTypes); mLog.log("preferred upstream type: " + getNetworkTypeName(typeStatePair.type)); switch (typeStatePair.type) { case TYPE_MOBILE_DUN: case TYPE_MOBILE_HIPRI: // If we're on DUN, put our own grab on it. registerMobileNetworkRequest(); break; case TYPE_NONE: break; default: /* If we've found an active upstream connection that's not DUN/HIPRI * we should stop any outstanding DUN/HIPRI start requests. * * If we found NONE we don't want to do this as we want any previous * requests to keep trying to bring up something we can use. */ releaseMobileNetworkRequest(); break; } return typeStatePair.type; } private void handleAvailable(int callbackType, Network network) { if (VDBG) Log.d(TAG, "EVENT_ON_AVAILABLE for " + network); Loading Loading @@ -365,4 +402,37 @@ public class UpstreamNetworkMonitor { private void notifyTarget(int which, NetworkState netstate) { mTarget.sendMessage(mWhat, which, 0, netstate); } static private class TypeStatePair { public int type = TYPE_NONE; public NetworkState ns = null; } static private TypeStatePair findFirstAvailableUpstreamByType( Iterable<NetworkState> netStates, Iterable<Integer> preferredTypes) { final TypeStatePair result = new TypeStatePair(); for (int type : preferredTypes) { NetworkCapabilities nc; try { nc = ConnectivityManager.networkCapabilitiesForType(type); } catch (IllegalArgumentException iae) { Log.e(TAG, "No NetworkCapabilities mapping for legacy type: " + ConnectivityManager.getNetworkTypeName(type)); continue; } for (NetworkState value : netStates) { if (!nc.satisfiedByNetworkCapabilities(value.networkCapabilities)) { continue; } result.type = type; result.ns = value; return result; } } return result; } } tests/net/java/com/android/server/connectivity/TetheringTest.java +0 −1 Original line number Diff line number Diff line Loading @@ -394,7 +394,6 @@ public class TetheringTest { any(NetworkCallback.class), any(Handler.class)); // In tethering mode, in the default configuration, an explicit request // for a mobile network is also made. verify(mConnectivityManager, atLeastOnce()).getNetworkInfo(anyInt()); verify(mConnectivityManager, times(1)).requestNetwork( any(NetworkRequest.class), any(NetworkCallback.class), eq(0), anyInt(), any(Handler.class)); Loading tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java +109 −0 Original line number Diff line number Diff line Loading @@ -18,7 +18,12 @@ package com.android.server.connectivity.tethering; import static android.net.ConnectivityManager.TYPE_MOBILE_DUN; import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI; import static android.net.ConnectivityManager.TYPE_NONE; import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN; import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; Loading Loading @@ -59,6 +64,7 @@ import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; Loading Loading @@ -240,6 +246,72 @@ public class UpstreamNetworkMonitorTest { assertFalse(mUNM.mobileNetworkRequested()); } @Test public void testSelectPreferredUpstreamType() throws Exception { final Collection<Integer> preferredTypes = new ArrayList<>(); preferredTypes.add(TYPE_WIFI); mUNM.start(); // There are no networks, so there is nothing to select. assertEquals(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes)); final TestNetworkAgent wifiAgent = new TestNetworkAgent(mCM, TRANSPORT_WIFI); wifiAgent.fakeConnect(); // WiFi is up, we should prefer it. assertEquals(TYPE_WIFI, mUNM.selectPreferredUpstreamType(preferredTypes)); wifiAgent.fakeDisconnect(); // There are no networks, so there is nothing to select. assertEquals(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes)); final TestNetworkAgent cellAgent = new TestNetworkAgent(mCM, TRANSPORT_CELLULAR); cellAgent.fakeConnect(); assertEquals(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes)); preferredTypes.add(TYPE_MOBILE_DUN); // This is coupled with preferred types in TetheringConfiguration. mUNM.updateMobileRequiresDun(true); // DUN is available, but only use regular cell: no upstream selected. assertEquals(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes)); preferredTypes.remove(TYPE_MOBILE_DUN); // No WiFi, but our preferred flavour of cell is up. preferredTypes.add(TYPE_MOBILE_HIPRI); // This is coupled with preferred types in TetheringConfiguration. mUNM.updateMobileRequiresDun(false); assertEquals(TYPE_MOBILE_HIPRI, mUNM.selectPreferredUpstreamType(preferredTypes)); // Check to see we filed an explicit request. assertEquals(1, mCM.requested.size()); NetworkRequest netReq = (NetworkRequest) mCM.requested.values().toArray()[0]; assertTrue(netReq.networkCapabilities.hasTransport(TRANSPORT_CELLULAR)); assertFalse(netReq.networkCapabilities.hasCapability(NET_CAPABILITY_DUN)); wifiAgent.fakeConnect(); // WiFi is up, and we should prefer it over cell. assertEquals(TYPE_WIFI, mUNM.selectPreferredUpstreamType(preferredTypes)); assertEquals(0, mCM.requested.size()); preferredTypes.remove(TYPE_MOBILE_HIPRI); preferredTypes.add(TYPE_MOBILE_DUN); // This is coupled with preferred types in TetheringConfiguration. mUNM.updateMobileRequiresDun(true); assertEquals(TYPE_WIFI, mUNM.selectPreferredUpstreamType(preferredTypes)); final TestNetworkAgent dunAgent = new TestNetworkAgent(mCM, TRANSPORT_CELLULAR); dunAgent.networkCapabilities.addCapability(NET_CAPABILITY_DUN); dunAgent.fakeConnect(); // WiFi is still preferred. assertEquals(TYPE_WIFI, mUNM.selectPreferredUpstreamType(preferredTypes)); // WiFi goes down, cell and DUN are still up but only DUN is preferred. wifiAgent.fakeDisconnect(); assertEquals(TYPE_MOBILE_DUN, mUNM.selectPreferredUpstreamType(preferredTypes)); // Check to see we filed an explicit request. assertEquals(1, mCM.requested.size()); netReq = (NetworkRequest) mCM.requested.values().toArray()[0]; assertTrue(netReq.networkCapabilities.hasTransport(TRANSPORT_CELLULAR)); assertTrue(netReq.networkCapabilities.hasCapability(NET_CAPABILITY_DUN)); } private void assertUpstreamTypeRequested(int upstreamType) throws Exception { assertEquals(1, mCM.requested.size()); assertEquals(1, mCM.legacyTypeMap.size()); Loading @@ -254,6 +326,8 @@ public class UpstreamNetworkMonitorTest { public Map<NetworkCallback, NetworkRequest> requested = new HashMap<>(); public Map<NetworkCallback, Integer> legacyTypeMap = new HashMap<>(); private int mNetworkId = 100; public TestConnectivityManager(Context ctx, IConnectivityManager svc) { super(ctx, svc); } Loading Loading @@ -287,6 +361,8 @@ public class UpstreamNetworkMonitorTest { return false; } int getNetworkId() { return ++mNetworkId; } @Override public void requestNetwork(NetworkRequest req, NetworkCallback cb, Handler h) { assertFalse(allCallbacks.containsKey(cb)); Loading Loading @@ -360,6 +436,35 @@ public class UpstreamNetworkMonitorTest { } } public static class TestNetworkAgent { public final TestConnectivityManager cm; public final Network networkId; public final int transportType; public final NetworkCapabilities networkCapabilities; public TestNetworkAgent(TestConnectivityManager cm, int transportType) { this.cm = cm; this.networkId = new Network(cm.getNetworkId()); this.transportType = transportType; networkCapabilities = new NetworkCapabilities(); networkCapabilities.addTransportType(transportType); networkCapabilities.addCapability(NET_CAPABILITY_INTERNET); } public void fakeConnect() { for (NetworkCallback cb : cm.listening.keySet()) { cb.onAvailable(networkId); cb.onCapabilitiesChanged(networkId, copy(networkCapabilities)); } } public void fakeDisconnect() { for (NetworkCallback cb : cm.listening.keySet()) { cb.onLost(networkId); } } } public static class TestStateMachine extends StateMachine { public final ArrayList<Message> messages = new ArrayList<>(); private final State mLoggingState = new LoggingState(); Loading @@ -382,4 +487,8 @@ public class UpstreamNetworkMonitorTest { super.start(); } } static NetworkCapabilities copy(NetworkCapabilities nc) { return new NetworkCapabilities(nc); } } Loading
services/core/java/com/android/server/connectivity/Tethering.java +2 −54 Original line number Diff line number Diff line Loading @@ -1247,8 +1247,8 @@ public class Tethering extends BaseNetworkObserver { protected void chooseUpstreamType(boolean tryCell) { updateConfiguration(); // TODO - remove? final int upstreamType = findPreferredUpstreamType( getConnectivityManager(), mConfig); final int upstreamType = mUpstreamNetworkMonitor.selectPreferredUpstreamType( mConfig.preferredUpstreamIfaceTypes); if (upstreamType == ConnectivityManager.TYPE_NONE) { if (tryCell) { mUpstreamNetworkMonitor.registerMobileNetworkRequest(); Loading @@ -1260,58 +1260,6 @@ public class Tethering extends BaseNetworkObserver { setUpstreamByType(upstreamType); } // TODO: Move this function into UpstreamNetworkMonitor. protected int findPreferredUpstreamType(ConnectivityManager cm, TetheringConfiguration cfg) { int upType = ConnectivityManager.TYPE_NONE; if (VDBG) { Log.d(TAG, "chooseUpstreamType has upstream iface types:"); for (Integer netType : cfg.preferredUpstreamIfaceTypes) { Log.d(TAG, " " + netType); } } for (Integer netType : cfg.preferredUpstreamIfaceTypes) { NetworkInfo info = cm.getNetworkInfo(netType.intValue()); // TODO: if the network is suspended we should consider // that to be the same as connected here. if ((info != null) && info.isConnected()) { upType = netType.intValue(); break; } } final int preferredUpstreamMobileApn = cfg.isDunRequired ? ConnectivityManager.TYPE_MOBILE_DUN : ConnectivityManager.TYPE_MOBILE_HIPRI; mLog.log(String.format( "findPreferredUpstreamType(), preferredApn=%s, got type=%s", getNetworkTypeName(preferredUpstreamMobileApn), getNetworkTypeName(upType))); switch (upType) { case ConnectivityManager.TYPE_MOBILE_DUN: case ConnectivityManager.TYPE_MOBILE_HIPRI: // If we're on DUN, put our own grab on it. mUpstreamNetworkMonitor.registerMobileNetworkRequest(); break; case ConnectivityManager.TYPE_NONE: break; default: /* If we've found an active upstream connection that's not DUN/HIPRI * we should stop any outstanding DUN/HIPRI start requests. * * If we found NONE we don't want to do this as we want any previous * requests to keep trying to bring up something we can use. */ mUpstreamNetworkMonitor.releaseMobileNetworkRequest(); break; } return upType; } protected void setUpstreamByType(int upType) { final ConnectivityManager cm = getConnectivityManager(); Network network = null; Loading
services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java +70 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server.connectivity.tethering; import static android.net.ConnectivityManager.getNetworkTypeName; import static android.net.ConnectivityManager.TYPE_NONE; import static android.net.ConnectivityManager.TYPE_MOBILE_DUN; import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI; Loading Loading @@ -176,6 +178,41 @@ public class UpstreamNetworkMonitor { return (network != null) ? mNetworkMap.get(network) : null; } // So many TODOs here, but chief among them is: make this functionality an // integral part of this class such that whenever a higher priority network // becomes available and useful we (a) file a request to keep it up as // necessary and (b) change all upstream tracking state accordingly (by // passing LinkProperties up to Tethering). // // Next TODO: return NetworkState instead of just the type. public int selectPreferredUpstreamType(Iterable<Integer> preferredTypes) { final TypeStatePair typeStatePair = findFirstAvailableUpstreamByType( mNetworkMap.values(), preferredTypes); mLog.log("preferred upstream type: " + getNetworkTypeName(typeStatePair.type)); switch (typeStatePair.type) { case TYPE_MOBILE_DUN: case TYPE_MOBILE_HIPRI: // If we're on DUN, put our own grab on it. registerMobileNetworkRequest(); break; case TYPE_NONE: break; default: /* If we've found an active upstream connection that's not DUN/HIPRI * we should stop any outstanding DUN/HIPRI start requests. * * If we found NONE we don't want to do this as we want any previous * requests to keep trying to bring up something we can use. */ releaseMobileNetworkRequest(); break; } return typeStatePair.type; } private void handleAvailable(int callbackType, Network network) { if (VDBG) Log.d(TAG, "EVENT_ON_AVAILABLE for " + network); Loading Loading @@ -365,4 +402,37 @@ public class UpstreamNetworkMonitor { private void notifyTarget(int which, NetworkState netstate) { mTarget.sendMessage(mWhat, which, 0, netstate); } static private class TypeStatePair { public int type = TYPE_NONE; public NetworkState ns = null; } static private TypeStatePair findFirstAvailableUpstreamByType( Iterable<NetworkState> netStates, Iterable<Integer> preferredTypes) { final TypeStatePair result = new TypeStatePair(); for (int type : preferredTypes) { NetworkCapabilities nc; try { nc = ConnectivityManager.networkCapabilitiesForType(type); } catch (IllegalArgumentException iae) { Log.e(TAG, "No NetworkCapabilities mapping for legacy type: " + ConnectivityManager.getNetworkTypeName(type)); continue; } for (NetworkState value : netStates) { if (!nc.satisfiedByNetworkCapabilities(value.networkCapabilities)) { continue; } result.type = type; result.ns = value; return result; } } return result; } }
tests/net/java/com/android/server/connectivity/TetheringTest.java +0 −1 Original line number Diff line number Diff line Loading @@ -394,7 +394,6 @@ public class TetheringTest { any(NetworkCallback.class), any(Handler.class)); // In tethering mode, in the default configuration, an explicit request // for a mobile network is also made. verify(mConnectivityManager, atLeastOnce()).getNetworkInfo(anyInt()); verify(mConnectivityManager, times(1)).requestNetwork( any(NetworkRequest.class), any(NetworkCallback.class), eq(0), anyInt(), any(Handler.class)); Loading
tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java +109 −0 Original line number Diff line number Diff line Loading @@ -18,7 +18,12 @@ package com.android.server.connectivity.tethering; import static android.net.ConnectivityManager.TYPE_MOBILE_DUN; import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI; import static android.net.ConnectivityManager.TYPE_NONE; import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN; import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; Loading Loading @@ -59,6 +64,7 @@ import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; Loading Loading @@ -240,6 +246,72 @@ public class UpstreamNetworkMonitorTest { assertFalse(mUNM.mobileNetworkRequested()); } @Test public void testSelectPreferredUpstreamType() throws Exception { final Collection<Integer> preferredTypes = new ArrayList<>(); preferredTypes.add(TYPE_WIFI); mUNM.start(); // There are no networks, so there is nothing to select. assertEquals(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes)); final TestNetworkAgent wifiAgent = new TestNetworkAgent(mCM, TRANSPORT_WIFI); wifiAgent.fakeConnect(); // WiFi is up, we should prefer it. assertEquals(TYPE_WIFI, mUNM.selectPreferredUpstreamType(preferredTypes)); wifiAgent.fakeDisconnect(); // There are no networks, so there is nothing to select. assertEquals(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes)); final TestNetworkAgent cellAgent = new TestNetworkAgent(mCM, TRANSPORT_CELLULAR); cellAgent.fakeConnect(); assertEquals(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes)); preferredTypes.add(TYPE_MOBILE_DUN); // This is coupled with preferred types in TetheringConfiguration. mUNM.updateMobileRequiresDun(true); // DUN is available, but only use regular cell: no upstream selected. assertEquals(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes)); preferredTypes.remove(TYPE_MOBILE_DUN); // No WiFi, but our preferred flavour of cell is up. preferredTypes.add(TYPE_MOBILE_HIPRI); // This is coupled with preferred types in TetheringConfiguration. mUNM.updateMobileRequiresDun(false); assertEquals(TYPE_MOBILE_HIPRI, mUNM.selectPreferredUpstreamType(preferredTypes)); // Check to see we filed an explicit request. assertEquals(1, mCM.requested.size()); NetworkRequest netReq = (NetworkRequest) mCM.requested.values().toArray()[0]; assertTrue(netReq.networkCapabilities.hasTransport(TRANSPORT_CELLULAR)); assertFalse(netReq.networkCapabilities.hasCapability(NET_CAPABILITY_DUN)); wifiAgent.fakeConnect(); // WiFi is up, and we should prefer it over cell. assertEquals(TYPE_WIFI, mUNM.selectPreferredUpstreamType(preferredTypes)); assertEquals(0, mCM.requested.size()); preferredTypes.remove(TYPE_MOBILE_HIPRI); preferredTypes.add(TYPE_MOBILE_DUN); // This is coupled with preferred types in TetheringConfiguration. mUNM.updateMobileRequiresDun(true); assertEquals(TYPE_WIFI, mUNM.selectPreferredUpstreamType(preferredTypes)); final TestNetworkAgent dunAgent = new TestNetworkAgent(mCM, TRANSPORT_CELLULAR); dunAgent.networkCapabilities.addCapability(NET_CAPABILITY_DUN); dunAgent.fakeConnect(); // WiFi is still preferred. assertEquals(TYPE_WIFI, mUNM.selectPreferredUpstreamType(preferredTypes)); // WiFi goes down, cell and DUN are still up but only DUN is preferred. wifiAgent.fakeDisconnect(); assertEquals(TYPE_MOBILE_DUN, mUNM.selectPreferredUpstreamType(preferredTypes)); // Check to see we filed an explicit request. assertEquals(1, mCM.requested.size()); netReq = (NetworkRequest) mCM.requested.values().toArray()[0]; assertTrue(netReq.networkCapabilities.hasTransport(TRANSPORT_CELLULAR)); assertTrue(netReq.networkCapabilities.hasCapability(NET_CAPABILITY_DUN)); } private void assertUpstreamTypeRequested(int upstreamType) throws Exception { assertEquals(1, mCM.requested.size()); assertEquals(1, mCM.legacyTypeMap.size()); Loading @@ -254,6 +326,8 @@ public class UpstreamNetworkMonitorTest { public Map<NetworkCallback, NetworkRequest> requested = new HashMap<>(); public Map<NetworkCallback, Integer> legacyTypeMap = new HashMap<>(); private int mNetworkId = 100; public TestConnectivityManager(Context ctx, IConnectivityManager svc) { super(ctx, svc); } Loading Loading @@ -287,6 +361,8 @@ public class UpstreamNetworkMonitorTest { return false; } int getNetworkId() { return ++mNetworkId; } @Override public void requestNetwork(NetworkRequest req, NetworkCallback cb, Handler h) { assertFalse(allCallbacks.containsKey(cb)); Loading Loading @@ -360,6 +436,35 @@ public class UpstreamNetworkMonitorTest { } } public static class TestNetworkAgent { public final TestConnectivityManager cm; public final Network networkId; public final int transportType; public final NetworkCapabilities networkCapabilities; public TestNetworkAgent(TestConnectivityManager cm, int transportType) { this.cm = cm; this.networkId = new Network(cm.getNetworkId()); this.transportType = transportType; networkCapabilities = new NetworkCapabilities(); networkCapabilities.addTransportType(transportType); networkCapabilities.addCapability(NET_CAPABILITY_INTERNET); } public void fakeConnect() { for (NetworkCallback cb : cm.listening.keySet()) { cb.onAvailable(networkId); cb.onCapabilitiesChanged(networkId, copy(networkCapabilities)); } } public void fakeDisconnect() { for (NetworkCallback cb : cm.listening.keySet()) { cb.onLost(networkId); } } } public static class TestStateMachine extends StateMachine { public final ArrayList<Message> messages = new ArrayList<>(); private final State mLoggingState = new LoggingState(); Loading @@ -382,4 +487,8 @@ public class UpstreamNetworkMonitorTest { super.start(); } } static NetworkCapabilities copy(NetworkCapabilities nc) { return new NetworkCapabilities(nc); } }