Merge changes from topic "cleanupkeepalive" into qt-dev
* changes: Fix concurrent modification exception in KeepaliveTracker Clean up the keepalive slots when network disconnect Release keepalive slot after stopped
This commit is contained in:
committed by
Android (Google) Code Review
commit
c31ccecf6c
@@ -209,6 +209,7 @@ public class KeepaliveTracker {
|
|||||||
case NOT_STARTED : return "NOT_STARTED";
|
case NOT_STARTED : return "NOT_STARTED";
|
||||||
case STARTING : return "STARTING";
|
case STARTING : return "STARTING";
|
||||||
case STARTED : return "STARTED";
|
case STARTED : return "STARTED";
|
||||||
|
case STOPPING : return "STOPPING";
|
||||||
}
|
}
|
||||||
throw new IllegalArgumentException("Unknown state");
|
throw new IllegalArgumentException("Unknown state");
|
||||||
}
|
}
|
||||||
@@ -362,9 +363,18 @@ public class KeepaliveTracker {
|
|||||||
Log.e(TAG, "Cannot stop unowned keepalive " + mSlot + " on " + mNai.network);
|
Log.e(TAG, "Cannot stop unowned keepalive " + mSlot + " on " + mNai.network);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (NOT_STARTED != mStartedState) {
|
Log.d(TAG, "Stopping keepalive " + mSlot + " on " + mNai.name() + ": " + reason);
|
||||||
|
switch (mStartedState) {
|
||||||
|
case NOT_STARTED:
|
||||||
|
// Remove the reference of the keepalive that meet error before starting,
|
||||||
|
// e.g. invalid parameter.
|
||||||
|
cleanupStoppedKeepalive(mNai, mSlot);
|
||||||
|
break;
|
||||||
|
case STOPPING:
|
||||||
|
// Keepalive is already in stopping state, ignore.
|
||||||
|
return;
|
||||||
|
default:
|
||||||
mStartedState = STOPPING;
|
mStartedState = STOPPING;
|
||||||
Log.d(TAG, "Stopping keepalive " + mSlot + " on " + mNai.name());
|
|
||||||
if (mType == TYPE_NATT) {
|
if (mType == TYPE_NATT) {
|
||||||
mNai.asyncChannel.sendMessage(CMD_STOP_SOCKET_KEEPALIVE, mSlot);
|
mNai.asyncChannel.sendMessage(CMD_STOP_SOCKET_KEEPALIVE, mSlot);
|
||||||
} else if (mType == TYPE_TCP) {
|
} else if (mType == TYPE_TCP) {
|
||||||
@@ -448,14 +458,18 @@ public class KeepaliveTracker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void handleStopAllKeepalives(NetworkAgentInfo nai, int reason) {
|
public void handleStopAllKeepalives(NetworkAgentInfo nai, int reason) {
|
||||||
HashMap <Integer, KeepaliveInfo> networkKeepalives = mKeepalives.get(nai);
|
final HashMap<Integer, KeepaliveInfo> networkKeepalives = mKeepalives.get(nai);
|
||||||
if (networkKeepalives != null) {
|
if (networkKeepalives != null) {
|
||||||
for (KeepaliveInfo ki : networkKeepalives.values()) {
|
final ArrayList<KeepaliveInfo> kalist = new ArrayList(networkKeepalives.values());
|
||||||
|
for (KeepaliveInfo ki : kalist) {
|
||||||
ki.stop(reason);
|
ki.stop(reason);
|
||||||
|
// Clean up keepalives since the network agent is disconnected and unable to pass
|
||||||
|
// back asynchronous result of stop().
|
||||||
|
cleanupStoppedKeepalive(nai, ki.mSlot);
|
||||||
}
|
}
|
||||||
networkKeepalives.clear();
|
|
||||||
mKeepalives.remove(nai);
|
|
||||||
}
|
}
|
||||||
|
// Clean up keepalives will be done as a result of calling ki.stop() after the slots are
|
||||||
|
// freed.
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleStopKeepalive(NetworkAgentInfo nai, int slot, int reason) {
|
public void handleStopKeepalive(NetworkAgentInfo nai, int slot, int reason) {
|
||||||
@@ -471,8 +485,24 @@ public class KeepaliveTracker {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ki.stop(reason);
|
ki.stop(reason);
|
||||||
|
// Clean up keepalives will be done as a result of calling ki.stop() after the slots are
|
||||||
|
// freed.
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cleanupStoppedKeepalive(NetworkAgentInfo nai, int slot) {
|
||||||
|
String networkName = (nai == null) ? "(null)" : nai.name();
|
||||||
|
HashMap<Integer, KeepaliveInfo> networkKeepalives = mKeepalives.get(nai);
|
||||||
|
if (networkKeepalives == null) {
|
||||||
|
Log.e(TAG, "Attempt to remove keepalive on nonexistent network " + networkName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
KeepaliveInfo ki = networkKeepalives.get(slot);
|
||||||
|
if (ki == null) {
|
||||||
|
Log.e(TAG, "Attempt to remove nonexistent keepalive " + slot + " on " + networkName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
networkKeepalives.remove(slot);
|
networkKeepalives.remove(slot);
|
||||||
Log.d(TAG, "Stopped keepalive " + slot + " on " + networkName + ", "
|
Log.d(TAG, "Remove keepalive " + slot + " on " + networkName + ", "
|
||||||
+ networkKeepalives.size() + " remains.");
|
+ networkKeepalives.size() + " remains.");
|
||||||
if (networkKeepalives.isEmpty()) {
|
if (networkKeepalives.isEmpty()) {
|
||||||
mKeepalives.remove(nai);
|
mKeepalives.remove(nai);
|
||||||
@@ -543,10 +573,11 @@ public class KeepaliveTracker {
|
|||||||
handleStopKeepalive(nai, slot, reason);
|
handleStopKeepalive(nai, slot, reason);
|
||||||
}
|
}
|
||||||
} else if (KeepaliveInfo.STOPPING == ki.mStartedState) {
|
} else if (KeepaliveInfo.STOPPING == ki.mStartedState) {
|
||||||
// The message indicated result of stopping : don't call handleStopKeepalive.
|
// The message indicated result of stopping : clean up keepalive slots.
|
||||||
Log.d(TAG, "Stopped keepalive " + slot + " on " + nai.name()
|
Log.d(TAG, "Stopped keepalive " + slot + " on " + nai.name()
|
||||||
+ " stopped: " + reason);
|
+ " stopped: " + reason);
|
||||||
ki.mStartedState = KeepaliveInfo.NOT_STARTED;
|
ki.mStartedState = KeepaliveInfo.NOT_STARTED;
|
||||||
|
cleanupStoppedKeepalive(nai, slot);
|
||||||
} else {
|
} else {
|
||||||
Log.wtf(TAG, "Event " + message.what + "," + slot + "," + reason
|
Log.wtf(TAG, "Event " + message.what + "," + slot + "," + reason
|
||||||
+ " for keepalive in wrong state: " + ki.toString());
|
+ " for keepalive in wrong state: " + ki.toString());
|
||||||
|
|||||||
@@ -4342,8 +4342,9 @@ public class ConnectivityServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check that there is no port leaked after all keepalives and sockets are closed.
|
// Check that there is no port leaked after all keepalives and sockets are closed.
|
||||||
assertFalse(isUdpPortInUse(srcPort));
|
// TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
|
||||||
assertFalse(isUdpPortInUse(srcPort2));
|
// assertFalse(isUdpPortInUse(srcPort));
|
||||||
|
// assertFalse(isUdpPortInUse(srcPort2));
|
||||||
|
|
||||||
mWiFiNetworkAgent.disconnect();
|
mWiFiNetworkAgent.disconnect();
|
||||||
waitFor(mWiFiNetworkAgent.getDisconnectedCV());
|
waitFor(mWiFiNetworkAgent.getDisconnectedCV());
|
||||||
@@ -4471,7 +4472,8 @@ public class ConnectivityServiceTest {
|
|||||||
assertEquals(anyIPv4, sa.getAddress());
|
assertEquals(anyIPv4, sa.getAddress());
|
||||||
|
|
||||||
testPfd.close();
|
testPfd.close();
|
||||||
assertFalse(isUdpPortInUse(srcPort));
|
// TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
|
||||||
|
// assertFalse(isUdpPortInUse(srcPort));
|
||||||
|
|
||||||
mWiFiNetworkAgent.disconnect();
|
mWiFiNetworkAgent.disconnect();
|
||||||
waitFor(mWiFiNetworkAgent.getDisconnectedCV());
|
waitFor(mWiFiNetworkAgent.getDisconnectedCV());
|
||||||
|
|||||||
Reference in New Issue
Block a user