Fix CS/NetworkMonitor race.

If we have a message in flight about a NetworkAgentInfo when it gets disconnected
we are left with a zombie network.  Fixes this by verifing the network is still
live before we process the msg.

bug:17142206
Change-Id: I2c94a39b3ea97c1562066571b277280c1f69f71c
This commit is contained in:
Robert Greenwalt
2014-08-19 18:58:04 -07:00
parent ef734f8a3b
commit a6fd83dc4b

View File

@@ -1733,6 +1733,19 @@ public class ConnectivityService extends IConnectivityManager.Stub {
} }
} }
private boolean isLiveNetworkAgent(NetworkAgentInfo nai, String msg) {
final NetworkAgentInfo officialNai;
synchronized (mNetworkForNetId) {
officialNai = mNetworkForNetId.get(nai.network.netId);
}
if (officialNai != null && officialNai.equals(nai)) return true;
if (officialNai != null || VDBG) {
loge(msg + " - validateNetworkAgent found mismatched netId: " + officialNai +
" - " + nai);
}
return false;
}
// must be stateless - things change under us. // must be stateless - things change under us.
private class NetworkStateTrackerHandler extends Handler { private class NetworkStateTrackerHandler extends Handler {
public NetworkStateTrackerHandler(Looper looper) { public NetworkStateTrackerHandler(Looper looper) {
@@ -1862,23 +1875,30 @@ public class ConnectivityService extends IConnectivityManager.Stub {
} }
case NetworkMonitor.EVENT_NETWORK_VALIDATED: { case NetworkMonitor.EVENT_NETWORK_VALIDATED: {
NetworkAgentInfo nai = (NetworkAgentInfo)msg.obj; NetworkAgentInfo nai = (NetworkAgentInfo)msg.obj;
handleConnectionValidated(nai); if (isLiveNetworkAgent(nai, "EVENT_NETWORK_VALIDATED")) {
handleConnectionValidated(nai);
}
break; break;
} }
case NetworkMonitor.EVENT_NETWORK_LINGER_COMPLETE: { case NetworkMonitor.EVENT_NETWORK_LINGER_COMPLETE: {
NetworkAgentInfo nai = (NetworkAgentInfo)msg.obj; NetworkAgentInfo nai = (NetworkAgentInfo)msg.obj;
handleLingerComplete(nai); if (isLiveNetworkAgent(nai, "EVENT_NETWORK_LINGER_COMPLETE")) {
handleLingerComplete(nai);
}
break; break;
} }
case NetworkMonitor.EVENT_PROVISIONING_NOTIFICATION: { case NetworkMonitor.EVENT_PROVISIONING_NOTIFICATION: {
NetworkAgentInfo nai = null;
synchronized (mNetworkForNetId) {
nai = mNetworkForNetId.get(msg.arg2);
}
if (nai == null) {
loge("EVENT_PROVISIONING_NOTIFICATION from unknown NetworkMonitor");
break;
}
if (msg.arg1 == 0) { if (msg.arg1 == 0) {
setProvNotificationVisibleIntent(false, msg.arg2, 0, null, null); setProvNotificationVisibleIntent(false, msg.arg2, 0, null, null);
} else { } else {
NetworkAgentInfo nai = mNetworkForNetId.get(msg.arg2);
if (nai == null) {
loge("EVENT_PROVISIONING_NOTIFICATION from unknown NetworkMonitor");
break;
}
setProvNotificationVisibleIntent(true, msg.arg2, nai.networkInfo.getType(), setProvNotificationVisibleIntent(true, msg.arg2, nai.networkInfo.getType(),
nai.networkInfo.getExtraInfo(), (PendingIntent)msg.obj); nai.networkInfo.getExtraInfo(), (PendingIntent)msg.obj);
} }