Merge "Release keepalive slot after stopped"

This commit is contained in:
Junyu Lai
2019-04-16 04:46:18 +00:00
committed by Gerrit Code Review
2 changed files with 48 additions and 19 deletions

View File

@@ -191,6 +191,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");
} }
@@ -314,18 +315,27 @@ 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);
mStartedState = STOPPING; switch (mStartedState) {
Log.d(TAG, "Stopping keepalive " + mSlot + " on " + mNai.name()); case NOT_STARTED:
if (mType == TYPE_NATT) { // Remove the reference of the keepalive that meet error before starting,
mNai.asyncChannel.sendMessage(CMD_STOP_SOCKET_KEEPALIVE, mSlot); // e.g. invalid parameter.
} else if (mType == TYPE_TCP) { cleanupStoppedKeepalive(mNai, mSlot);
mNai.asyncChannel.sendMessage(CMD_STOP_SOCKET_KEEPALIVE, mSlot); break;
mNai.asyncChannel.sendMessage(CMD_REMOVE_KEEPALIVE_PACKET_FILTER, mSlot); case STOPPING:
mTcpController.stopSocketMonitor(mSlot); // Keepalive is already in stopping state, ignore.
} else { return;
Log.wtf(TAG, "Stopping keepalive with unknown type: " + mType); default:
} mStartedState = STOPPING;
if (mType == TYPE_NATT) {
mNai.asyncChannel.sendMessage(CMD_STOP_SOCKET_KEEPALIVE, mSlot);
} else if (mType == TYPE_TCP) {
mNai.asyncChannel.sendMessage(CMD_STOP_SOCKET_KEEPALIVE, mSlot);
mNai.asyncChannel.sendMessage(CMD_REMOVE_KEEPALIVE_PACKET_FILTER, mSlot);
mTcpController.stopSocketMonitor(mSlot);
} else {
Log.wtf(TAG, "Stopping keepalive with unknown type: " + mType);
}
} }
// Close the duplicated fd that maintains the lifecycle of socket whenever // Close the duplicated fd that maintains the lifecycle of socket whenever
@@ -405,9 +415,9 @@ public class KeepaliveTracker {
for (KeepaliveInfo ki : networkKeepalives.values()) { for (KeepaliveInfo ki : networkKeepalives.values()) {
ki.stop(reason); ki.stop(reason);
} }
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) {
@@ -423,8 +433,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);
@@ -495,10 +521,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());

View File

@@ -4292,8 +4292,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());
@@ -4421,7 +4422,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());