Merge "Move findPreferredUpstreamType into UNM"
am: 32703994fe
Change-Id: I20e90906e72bc8bba9f0f535d54ba430f96191ff
This commit is contained in:
@@ -1232,8 +1232,8 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
||||
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();
|
||||
@@ -1245,58 +1245,6 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
||||
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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -368,7 +368,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));
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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());
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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));
|
||||
@@ -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();
|
||||
@@ -382,4 +487,8 @@ public class UpstreamNetworkMonitorTest {
|
||||
super.start();
|
||||
}
|
||||
}
|
||||
|
||||
static NetworkCapabilities copy(NetworkCapabilities nc) {
|
||||
return new NetworkCapabilities(nc);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user