Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c31ccecf authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

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
parents d7affe71 4fbc24fe
Loading
Loading
Loading
Loading
+49 −18
Original line number Diff line number Diff line
@@ -209,6 +209,7 @@ public class KeepaliveTracker {
                case NOT_STARTED : return "NOT_STARTED";
                case STARTING : return "STARTING";
                case STARTED : return "STARTED";
                case STOPPING : return "STOPPING";
            }
            throw new IllegalArgumentException("Unknown state");
        }
@@ -362,9 +363,18 @@ public class KeepaliveTracker {
                    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;
                Log.d(TAG, "Stopping keepalive " + mSlot + " on " + mNai.name());
                    if (mType == TYPE_NATT) {
                        mNai.asyncChannel.sendMessage(CMD_STOP_SOCKET_KEEPALIVE, mSlot);
                    } else if (mType == TYPE_TCP) {
@@ -448,14 +458,18 @@ public class KeepaliveTracker {
    }

    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) {
            for (KeepaliveInfo ki : networkKeepalives.values()) {
            final ArrayList<KeepaliveInfo> kalist = new ArrayList(networkKeepalives.values());
            for (KeepaliveInfo ki : kalist) {
                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) {
@@ -471,8 +485,24 @@ public class KeepaliveTracker {
            return;
        }
        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);
        Log.d(TAG, "Stopped keepalive " + slot + " on " + networkName + ", "
        Log.d(TAG, "Remove keepalive " + slot + " on " + networkName + ", "
                + networkKeepalives.size() + " remains.");
        if (networkKeepalives.isEmpty()) {
            mKeepalives.remove(nai);
@@ -543,10 +573,11 @@ public class KeepaliveTracker {
                handleStopKeepalive(nai, slot, reason);
            }
        } 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()
                    + " stopped: " + reason);
            ki.mStartedState = KeepaliveInfo.NOT_STARTED;
            cleanupStoppedKeepalive(nai, slot);
        } else {
            Log.wtf(TAG, "Event " + message.what + "," + slot + "," + reason
                    + " for keepalive in wrong state: " + ki.toString());
+5 −3
Original line number Diff line number Diff line
@@ -4342,8 +4342,9 @@ public class ConnectivityServiceTest {
        }

        // Check that there is no port leaked after all keepalives and sockets are closed.
        assertFalse(isUdpPortInUse(srcPort));
        assertFalse(isUdpPortInUse(srcPort2));
        // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
        // assertFalse(isUdpPortInUse(srcPort));
        // assertFalse(isUdpPortInUse(srcPort2));

        mWiFiNetworkAgent.disconnect();
        waitFor(mWiFiNetworkAgent.getDisconnectedCV());
@@ -4471,7 +4472,8 @@ public class ConnectivityServiceTest {
        assertEquals(anyIPv4, sa.getAddress());

        testPfd.close();
        assertFalse(isUdpPortInUse(srcPort));
        // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
        // assertFalse(isUdpPortInUse(srcPort));

        mWiFiNetworkAgent.disconnect();
        waitFor(mWiFiNetworkAgent.getDisconnectedCV());