Merge "Reap unvalidated networks that have no chance of becoming highest scoring." into lmp-mr1-dev
This commit is contained in:
@@ -170,6 +170,7 @@ import java.util.Collection;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
@@ -272,6 +273,26 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
private static final int ENABLED = 1;
|
||||
private static final int DISABLED = 0;
|
||||
|
||||
// Arguments to rematchNetworkAndRequests()
|
||||
private enum NascentState {
|
||||
// Indicates a network was just validated for the first time. If the network is found to
|
||||
// be unwanted (i.e. not satisfy any NetworkRequests) it is torn down.
|
||||
JUST_VALIDATED,
|
||||
// Indicates a network was not validated for the first time immediately prior to this call.
|
||||
NOT_JUST_VALIDATED
|
||||
};
|
||||
private enum ReapUnvalidatedNetworks {
|
||||
// Tear down unvalidated networks that have no chance (i.e. even if validated) of becoming
|
||||
// the highest scoring network satisfying a NetworkRequest. This should be passed when it's
|
||||
// known that there may be unvalidated networks that could potentially be reaped, and when
|
||||
// all networks have been rematched against all NetworkRequests.
|
||||
REAP,
|
||||
// Don't reap unvalidated networks. This should be passed when it's known that there are
|
||||
// no unvalidated networks that could potentially be reaped, and when some networks have
|
||||
// not yet been rematched against all NetworkRequests.
|
||||
DONT_REAP
|
||||
};
|
||||
|
||||
/**
|
||||
* used internally to change our mobile data enabled flag
|
||||
*/
|
||||
@@ -2014,12 +2035,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
boolean valid = (msg.arg1 == NetworkMonitor.NETWORK_TEST_RESULT_VALID);
|
||||
if (valid) {
|
||||
if (DBG) log("Validated " + nai.name());
|
||||
final boolean previouslyValidated = nai.validated;
|
||||
final int previousScore = nai.getCurrentScore();
|
||||
if (!nai.validated) {
|
||||
nai.validated = true;
|
||||
rematchNetworkAndRequests(nai, !previouslyValidated);
|
||||
rematchNetworkAndRequests(nai, NascentState.JUST_VALIDATED,
|
||||
ReapUnvalidatedNetworks.REAP);
|
||||
// If score has changed, rebroadcast to NetworkFactories. b/17726566
|
||||
if (nai.getCurrentScore() != previousScore) {
|
||||
sendUpdatedScoreToFactories(nai);
|
||||
}
|
||||
}
|
||||
@@ -2238,7 +2258,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
}
|
||||
for (NetworkAgentInfo networkToActivate : toActivate) {
|
||||
unlinger(networkToActivate);
|
||||
rematchNetworkAndRequests(networkToActivate, false);
|
||||
rematchNetworkAndRequests(networkToActivate, NascentState.NOT_JUST_VALIDATED,
|
||||
ReapUnvalidatedNetworks.DONT_REAP);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3964,15 +3985,16 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
// satisfied by newNetwork, and reassigns to newNetwork
|
||||
// any such requests for which newNetwork is the best.
|
||||
//
|
||||
// - Lingers any Networks that as a result are no longer
|
||||
// - Lingers any validated Networks that as a result are no longer
|
||||
// needed. A network is needed if it is the best network for
|
||||
// one or more NetworkRequests, or if it is a VPN.
|
||||
//
|
||||
// - Tears down newNetwork if it just became validated
|
||||
// (i.e. nascent==true) but turns out to be unneeded.
|
||||
// Does not tear down newNetwork if it is unvalidated,
|
||||
// because future validation may improve newNetwork's
|
||||
// score enough that it is needed.
|
||||
// (i.e. nascent==JUST_VALIDATED) but turns out to be unneeded.
|
||||
//
|
||||
// - If reapUnvalidatedNetworks==REAP, tears down unvalidated
|
||||
// networks that have no chance (i.e. even if validated)
|
||||
// of becoming the highest scoring network.
|
||||
//
|
||||
// NOTE: This function only adds NetworkRequests that "newNetwork" could satisfy,
|
||||
// it does not remove NetworkRequests that other Networks could better satisfy.
|
||||
@@ -3980,16 +4002,18 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
// This function should be used when possible instead of {@code rematchAllNetworksAndRequests}
|
||||
// as it performs better by a factor of the number of Networks.
|
||||
//
|
||||
// @param newNetwork is the network to be matched against NetworkRequests.
|
||||
// @param nascent indicates if newNetwork just became validated, in which case it should be
|
||||
// torn down if unneeded. If nascent is false, no action is taken if newNetwork
|
||||
// is found to be unneeded by this call. Presumably, in this case, either:
|
||||
// - newNetwork is unvalidated (and left alive), or
|
||||
// - the NetworkRequests keeping newNetwork alive have been transitioned to
|
||||
// another higher scoring network by another call to rematchNetworkAndRequests()
|
||||
// and this other call also lingered newNetwork.
|
||||
private void rematchNetworkAndRequests(NetworkAgentInfo newNetwork, boolean nascent) {
|
||||
// torn down if unneeded.
|
||||
// @param reapUnvalidatedNetworks indicates if an additional pass over all networks should be
|
||||
// performed to tear down unvalidated networks that have no chance (i.e. even if
|
||||
// validated) of becoming the highest scoring network.
|
||||
private void rematchNetworkAndRequests(NetworkAgentInfo newNetwork, NascentState nascent,
|
||||
ReapUnvalidatedNetworks reapUnvalidatedNetworks) {
|
||||
if (!newNetwork.created) return;
|
||||
if (nascent && !newNetwork.validated) loge("ERROR: nascent network not validated.");
|
||||
if (nascent == NascentState.JUST_VALIDATED && !newNetwork.validated) {
|
||||
loge("ERROR: nascent network not validated.");
|
||||
}
|
||||
boolean keep = newNetwork.isVPN();
|
||||
boolean isNewDefault = false;
|
||||
if (DBG) log("rematching " + newNetwork.name());
|
||||
@@ -4136,17 +4160,44 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
if (newNetwork.isVPN()) {
|
||||
mLegacyTypeTracker.add(TYPE_VPN, newNetwork);
|
||||
}
|
||||
} else if (nascent) {
|
||||
} else if (nascent == NascentState.JUST_VALIDATED) {
|
||||
// Only tear down newly validated networks here. Leave unvalidated to either become
|
||||
// validated (and get evaluated against peers, one losing here) or
|
||||
// NetworkMonitor reports a bad network and we tear it down then.
|
||||
// Networks that have been up for a while and are validated should be torn down via
|
||||
// the lingering process so communication on that network is given time to wrap up.
|
||||
// TODO: Could teardown unvalidated networks when their NetworkCapabilities
|
||||
// satisfy no NetworkRequests.
|
||||
// validated (and get evaluated against peers, one losing here), or get reaped (see
|
||||
// reapUnvalidatedNetworks) if they have no chance of becoming the highest scoring
|
||||
// network. Networks that have been up for a while and are validated should be torn
|
||||
// down via the lingering process so communication on that network is given time to
|
||||
// wrap up.
|
||||
if (DBG) log("Validated network turns out to be unwanted. Tear it down.");
|
||||
teardownUnneededNetwork(newNetwork);
|
||||
}
|
||||
if (reapUnvalidatedNetworks == ReapUnvalidatedNetworks.REAP) {
|
||||
for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
|
||||
if (!nai.created || nai.validated || nai.isVPN()) continue;
|
||||
boolean reap = true;
|
||||
for (NetworkRequestInfo nri : mNetworkRequests.values()) {
|
||||
// If this Network is already the highest scoring Network for a request, or if
|
||||
// there is hope for it to become one if it validated, then don't reap it.
|
||||
if (nri.isRequest && nai.satisfies(nri.request) &&
|
||||
(nai.networkRequests.get(nri.request.requestId) != null ||
|
||||
// Note that this catches two important cases:
|
||||
// 1. Unvalidated cellular will not be reaped when unvalidated WiFi
|
||||
// is currently satisfying the request. This is desirable when
|
||||
// cellular ends up validating but WiFi does not.
|
||||
// 2. Unvalidated WiFi will not be reaped when validated cellular
|
||||
// is currently satsifying the request. This is desirable when
|
||||
// WiFi ends up validating and out scoring cellular.
|
||||
mNetworkForRequestId.get(nri.request.requestId).getCurrentScore() <
|
||||
nai.getCurrentScoreAsValidated())) {
|
||||
reap = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (reap) {
|
||||
if (DBG) log("Reaping " + nai.name());
|
||||
teardownUnneededNetwork(nai);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt to rematch all Networks with NetworkRequests. This may result in Networks
|
||||
@@ -4167,10 +4218,17 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
// can only add more NetworkRequests satisfied by "changed", and this is exactly what
|
||||
// rematchNetworkAndRequests() handles.
|
||||
if (changed != null && oldScore < changed.getCurrentScore()) {
|
||||
rematchNetworkAndRequests(changed, false);
|
||||
rematchNetworkAndRequests(changed, NascentState.NOT_JUST_VALIDATED,
|
||||
ReapUnvalidatedNetworks.REAP);
|
||||
} else {
|
||||
for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
|
||||
rematchNetworkAndRequests(nai, false);
|
||||
for (Iterator i = mNetworkAgentInfos.values().iterator(); i.hasNext(); ) {
|
||||
rematchNetworkAndRequests((NetworkAgentInfo)i.next(),
|
||||
NascentState.NOT_JUST_VALIDATED,
|
||||
// Only reap the last time through the loop. Reaping before all rematching
|
||||
// is complete could incorrectly teardown a network that hasn't yet been
|
||||
// rematched.
|
||||
i.hasNext() ? ReapUnvalidatedNetworks.DONT_REAP
|
||||
: ReapUnvalidatedNetworks.REAP);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4252,7 +4310,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
// TODO: support proxy per network.
|
||||
}
|
||||
// Consider network even though it is not yet validated.
|
||||
rematchNetworkAndRequests(networkAgent, false);
|
||||
rematchNetworkAndRequests(networkAgent, NascentState.NOT_JUST_VALIDATED,
|
||||
ReapUnvalidatedNetworks.REAP);
|
||||
} else if (state == NetworkInfo.State.DISCONNECTED ||
|
||||
state == NetworkInfo.State.SUSPENDED) {
|
||||
networkAgent.asyncChannel.disconnect();
|
||||
|
||||
@@ -106,9 +106,7 @@ public class NetworkAgentInfo {
|
||||
return networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN);
|
||||
}
|
||||
|
||||
// Get the current score for this Network. This may be modified from what the
|
||||
// NetworkAgent sent, as it has modifiers applied to it.
|
||||
public int getCurrentScore() {
|
||||
private int getCurrentScore(boolean pretendValidated) {
|
||||
// TODO: We may want to refactor this into a NetworkScore class that takes a base score from
|
||||
// the NetworkAgent and signals from the NetworkAgent and uses those signals to modify the
|
||||
// score. The NetworkScore class would provide a nice place to centralize score constants
|
||||
@@ -116,7 +114,7 @@ public class NetworkAgentInfo {
|
||||
|
||||
int score = currentScore;
|
||||
|
||||
if (!validated) score -= UNVALIDATED_SCORE_PENALTY;
|
||||
if (!validated && !pretendValidated) score -= UNVALIDATED_SCORE_PENALTY;
|
||||
if (score < 0) score = 0;
|
||||
|
||||
if (networkMisc.explicitlySelected) score = EXPLICITLY_SELECTED_NETWORK_SCORE;
|
||||
@@ -124,6 +122,18 @@ public class NetworkAgentInfo {
|
||||
return score;
|
||||
}
|
||||
|
||||
// Get the current score for this Network. This may be modified from what the
|
||||
// NetworkAgent sent, as it has modifiers applied to it.
|
||||
public int getCurrentScore() {
|
||||
return getCurrentScore(false);
|
||||
}
|
||||
|
||||
// Get the current score for this Network as if it was validated. This may be modified from
|
||||
// what the NetworkAgent sent, as it has modifiers applied to it.
|
||||
public int getCurrentScoreAsValidated() {
|
||||
return getCurrentScore(true);
|
||||
}
|
||||
|
||||
public void setCurrentScore(int newScore) {
|
||||
currentScore = newScore;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user