Merge "Don't blindly teardown unvalidated networks when releasing NetworkRequests." into lmp-mr1-dev

This commit is contained in:
Paul Jensen
2015-01-14 12:38:57 +00:00
committed by Android (Google) Code Review

View File

@@ -2271,6 +2271,46 @@ public class ConnectivityService extends IConnectivityManager.Stub
} }
} }
// Is nai unneeded by all NetworkRequests (and should be disconnected)?
// For validated Networks this is simply whether it is satsifying any NetworkRequests.
// For unvalidated Networks this is whether it is satsifying any NetworkRequests or
// were it to become validated, would it have a chance of satisfying any NetworkRequests.
private boolean unneeded(NetworkAgentInfo nai) {
if (!nai.created || nai.isVPN()) return false;
boolean unneeded = true;
if (nai.everValidated) {
for (int i = 0; i < nai.networkRequests.size() && unneeded; i++) {
final NetworkRequest nr = nai.networkRequests.valueAt(i);
try {
if (isRequest(nr)) unneeded = false;
} catch (Exception e) {
loge("Request " + nr + " not found in mNetworkRequests.");
loge(" it came from request list of " + nai.name());
}
}
} else {
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 it is needed.
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())) {
unneeded = false;
break;
}
}
}
return unneeded;
}
private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid) { private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid) {
NetworkRequestInfo nri = mNetworkRequests.get(request); NetworkRequestInfo nri = mNetworkRequests.get(request);
if (nri != null) { if (nri != null) {
@@ -2292,16 +2332,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
", leaving " + nai.networkRequests.size() + ", leaving " + nai.networkRequests.size() +
" requests."); " requests.");
} }
// check if has any requests remaining and if not, if (unneeded(nai)) {
// disconnect (unless it's a VPN).
boolean keep = nai.isVPN();
for (int i = 0; i < nai.networkRequests.size() && !keep; i++) {
NetworkRequest r = nai.networkRequests.valueAt(i);
if (isRequest(r)) keep = true;
}
if (!keep) {
if (DBG) log("no live requests for " + nai.name() + "; disconnecting"); if (DBG) log("no live requests for " + nai.name() + "; disconnecting");
nai.asyncChannel.disconnect(); teardownUnneededNetwork(nai);
} }
} }
} }
@@ -4056,19 +4089,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
} }
// Linger any networks that are no longer needed. // Linger any networks that are no longer needed.
for (NetworkAgentInfo nai : affectedNetworks) { for (NetworkAgentInfo nai : affectedNetworks) {
boolean teardown = !nai.isVPN() && nai.everValidated; if (nai.everValidated && unneeded(nai)) {
for (int i = 0; i < nai.networkRequests.size() && teardown; i++) {
NetworkRequest nr = nai.networkRequests.valueAt(i);
try {
if (isRequest(nr)) {
teardown = false;
}
} catch (Exception e) {
loge("Request " + nr + " not found in mNetworkRequests.");
loge(" it came from request list of " + nai.name());
}
}
if (teardown) {
nai.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_LINGER); nai.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_LINGER);
notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOSING); notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOSING);
} else { } else {
@@ -4168,27 +4189,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
} }
if (reapUnvalidatedNetworks == ReapUnvalidatedNetworks.REAP) { if (reapUnvalidatedNetworks == ReapUnvalidatedNetworks.REAP) {
for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) { for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
if (!nai.created || nai.everValidated || nai.isVPN()) continue; if (!nai.everValidated && unneeded(nai)) {
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()); if (DBG) log("Reaping " + nai.name());
teardownUnneededNetwork(nai); teardownUnneededNetwork(nai);
} }