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.GregorianCalendar;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@@ -272,6 +273,26 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
private static final int ENABLED = 1;
|
private static final int ENABLED = 1;
|
||||||
private static final int DISABLED = 0;
|
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
|
* 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);
|
boolean valid = (msg.arg1 == NetworkMonitor.NETWORK_TEST_RESULT_VALID);
|
||||||
if (valid) {
|
if (valid) {
|
||||||
if (DBG) log("Validated " + nai.name());
|
if (DBG) log("Validated " + nai.name());
|
||||||
final boolean previouslyValidated = nai.validated;
|
if (!nai.validated) {
|
||||||
final int previousScore = nai.getCurrentScore();
|
nai.validated = true;
|
||||||
nai.validated = true;
|
rematchNetworkAndRequests(nai, NascentState.JUST_VALIDATED,
|
||||||
rematchNetworkAndRequests(nai, !previouslyValidated);
|
ReapUnvalidatedNetworks.REAP);
|
||||||
// If score has changed, rebroadcast to NetworkFactories. b/17726566
|
// If score has changed, rebroadcast to NetworkFactories. b/17726566
|
||||||
if (nai.getCurrentScore() != previousScore) {
|
|
||||||
sendUpdatedScoreToFactories(nai);
|
sendUpdatedScoreToFactories(nai);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2238,7 +2258,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
}
|
}
|
||||||
for (NetworkAgentInfo networkToActivate : toActivate) {
|
for (NetworkAgentInfo networkToActivate : toActivate) {
|
||||||
unlinger(networkToActivate);
|
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
|
// satisfied by newNetwork, and reassigns to newNetwork
|
||||||
// any such requests for which newNetwork is the best.
|
// 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
|
// needed. A network is needed if it is the best network for
|
||||||
// one or more NetworkRequests, or if it is a VPN.
|
// one or more NetworkRequests, or if it is a VPN.
|
||||||
//
|
//
|
||||||
// - Tears down newNetwork if it just became validated
|
// - Tears down newNetwork if it just became validated
|
||||||
// (i.e. nascent==true) but turns out to be unneeded.
|
// (i.e. nascent==JUST_VALIDATED) but turns out to be unneeded.
|
||||||
// Does not tear down newNetwork if it is unvalidated,
|
//
|
||||||
// because future validation may improve newNetwork's
|
// - If reapUnvalidatedNetworks==REAP, tears down unvalidated
|
||||||
// score enough that it is needed.
|
// 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,
|
// NOTE: This function only adds NetworkRequests that "newNetwork" could satisfy,
|
||||||
// it does not remove NetworkRequests that other Networks could better 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}
|
// This function should be used when possible instead of {@code rematchAllNetworksAndRequests}
|
||||||
// as it performs better by a factor of the number of Networks.
|
// 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
|
// @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
|
// torn down if unneeded.
|
||||||
// is found to be unneeded by this call. Presumably, in this case, either:
|
// @param reapUnvalidatedNetworks indicates if an additional pass over all networks should be
|
||||||
// - newNetwork is unvalidated (and left alive), or
|
// performed to tear down unvalidated networks that have no chance (i.e. even if
|
||||||
// - the NetworkRequests keeping newNetwork alive have been transitioned to
|
// validated) of becoming the highest scoring network.
|
||||||
// another higher scoring network by another call to rematchNetworkAndRequests()
|
private void rematchNetworkAndRequests(NetworkAgentInfo newNetwork, NascentState nascent,
|
||||||
// and this other call also lingered newNetwork.
|
ReapUnvalidatedNetworks reapUnvalidatedNetworks) {
|
||||||
private void rematchNetworkAndRequests(NetworkAgentInfo newNetwork, boolean nascent) {
|
|
||||||
if (!newNetwork.created) return;
|
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 keep = newNetwork.isVPN();
|
||||||
boolean isNewDefault = false;
|
boolean isNewDefault = false;
|
||||||
if (DBG) log("rematching " + newNetwork.name());
|
if (DBG) log("rematching " + newNetwork.name());
|
||||||
@@ -4136,17 +4160,44 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
if (newNetwork.isVPN()) {
|
if (newNetwork.isVPN()) {
|
||||||
mLegacyTypeTracker.add(TYPE_VPN, newNetwork);
|
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
|
// Only tear down newly validated networks here. Leave unvalidated to either become
|
||||||
// validated (and get evaluated against peers, one losing here) or
|
// validated (and get evaluated against peers, one losing here), or get reaped (see
|
||||||
// NetworkMonitor reports a bad network and we tear it down then.
|
// reapUnvalidatedNetworks) if they have no chance of becoming the highest scoring
|
||||||
// Networks that have been up for a while and are validated should be torn down via
|
// network. Networks that have been up for a while and are validated should be torn
|
||||||
// the lingering process so communication on that network is given time to wrap up.
|
// down via the lingering process so communication on that network is given time to
|
||||||
// TODO: Could teardown unvalidated networks when their NetworkCapabilities
|
// wrap up.
|
||||||
// satisfy no NetworkRequests.
|
|
||||||
if (DBG) log("Validated network turns out to be unwanted. Tear it down.");
|
if (DBG) log("Validated network turns out to be unwanted. Tear it down.");
|
||||||
teardownUnneededNetwork(newNetwork);
|
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
|
// 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
|
// can only add more NetworkRequests satisfied by "changed", and this is exactly what
|
||||||
// rematchNetworkAndRequests() handles.
|
// rematchNetworkAndRequests() handles.
|
||||||
if (changed != null && oldScore < changed.getCurrentScore()) {
|
if (changed != null && oldScore < changed.getCurrentScore()) {
|
||||||
rematchNetworkAndRequests(changed, false);
|
rematchNetworkAndRequests(changed, NascentState.NOT_JUST_VALIDATED,
|
||||||
|
ReapUnvalidatedNetworks.REAP);
|
||||||
} else {
|
} else {
|
||||||
for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
|
for (Iterator i = mNetworkAgentInfos.values().iterator(); i.hasNext(); ) {
|
||||||
rematchNetworkAndRequests(nai, false);
|
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.
|
// TODO: support proxy per network.
|
||||||
}
|
}
|
||||||
// Consider network even though it is not yet validated.
|
// 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 ||
|
} else if (state == NetworkInfo.State.DISCONNECTED ||
|
||||||
state == NetworkInfo.State.SUSPENDED) {
|
state == NetworkInfo.State.SUSPENDED) {
|
||||||
networkAgent.asyncChannel.disconnect();
|
networkAgent.asyncChannel.disconnect();
|
||||||
|
|||||||
@@ -106,9 +106,7 @@ public class NetworkAgentInfo {
|
|||||||
return networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN);
|
return networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the current score for this Network. This may be modified from what the
|
private int getCurrentScore(boolean pretendValidated) {
|
||||||
// NetworkAgent sent, as it has modifiers applied to it.
|
|
||||||
public int getCurrentScore() {
|
|
||||||
// TODO: We may want to refactor this into a NetworkScore class that takes a base score from
|
// 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
|
// 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
|
// score. The NetworkScore class would provide a nice place to centralize score constants
|
||||||
@@ -116,7 +114,7 @@ public class NetworkAgentInfo {
|
|||||||
|
|
||||||
int score = currentScore;
|
int score = currentScore;
|
||||||
|
|
||||||
if (!validated) score -= UNVALIDATED_SCORE_PENALTY;
|
if (!validated && !pretendValidated) score -= UNVALIDATED_SCORE_PENALTY;
|
||||||
if (score < 0) score = 0;
|
if (score < 0) score = 0;
|
||||||
|
|
||||||
if (networkMisc.explicitlySelected) score = EXPLICITLY_SELECTED_NETWORK_SCORE;
|
if (networkMisc.explicitlySelected) score = EXPLICITLY_SELECTED_NETWORK_SCORE;
|
||||||
@@ -124,6 +122,18 @@ public class NetworkAgentInfo {
|
|||||||
return score;
|
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) {
|
public void setCurrentScore(int newScore) {
|
||||||
currentScore = newScore;
|
currentScore = newScore;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user