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

Commit 0cc1732c authored by Paul Jensen's avatar Paul Jensen
Browse files

Remember to cancel lingering when a network again satsifies a NetworkRequest.

When WiFi's score drops and then comes back up we would previously linger
WiFi but forget to cancel the linger timeout, so 30s later WiFi would
unexpectedly tear down.  Also, make sure this is only done for created
Networks as "created" is the signal to initialy match Networks and requests.

bug:18169560
Change-Id: Ia69b110f6473371e556c60b950253758e023b7aa
parent c3056190
Loading
Loading
Loading
Loading
+30 −36
Original line number Diff line number Diff line
@@ -2043,6 +2043,17 @@ public class ConnectivityService extends IConnectivityManager.Stub
        }
    }

    // Cancel any lingering so the linger timeout doesn't teardown a network.
    // This should be called when a network begins satisfying a NetworkRequest.
    // Note: depending on what state the NetworkMonitor is in (e.g.,
    // if it's awaiting captive portal login, or if validation failed), this
    // may trigger a re-evaluation of the network.
    private void unlinger(NetworkAgentInfo nai) {
        if (VDBG) log("Canceling linger of " + nai.name());
        nai.networkLingered.clear();
        nai.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_CONNECTED);
    }

    private void handleAsyncChannelHalfConnect(Message msg) {
        AsyncChannel ac = (AsyncChannel) msg.obj;
        if (mNetworkFactoryInfos.containsKey(msg.replyTo)) {
@@ -2078,6 +2089,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
            }
        }
    }

    private void handleAsyncChannelDisconnected(Message msg) {
        NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
        if (nai != null) {
@@ -2127,11 +2139,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
                    mNetworkForRequestId.remove(request.requestId);
                    sendUpdatedScoreToFactories(request, 0);
                    NetworkAgentInfo alternative = null;
                    for (Map.Entry entry : mNetworkAgentInfos.entrySet()) {
                        NetworkAgentInfo existing = (NetworkAgentInfo)entry.getValue();
                        if (existing.networkInfo.isConnected() &&
                                request.networkCapabilities.satisfiedByNetworkCapabilities(
                                existing.networkCapabilities) &&
                    for (NetworkAgentInfo existing : mNetworkAgentInfos.values()) {
                        if (existing.satisfies(request) &&
                                (alternative == null ||
                                 alternative.getCurrentScore() < existing.getCurrentScore())) {
                            alternative = existing;
@@ -2151,8 +2160,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
                requestNetworkTransitionWakelock(nai.name());
            }
            for (NetworkAgentInfo networkToActivate : toActivate) {
                networkToActivate.networkLingered.clear();
                networkToActivate.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_CONNECTED);
                unlinger(networkToActivate);
                rematchNetworkAndRequests(networkToActivate, false);
            }
        }
@@ -2187,44 +2195,35 @@ public class ConnectivityService extends IConnectivityManager.Stub

    private void handleRegisterNetworkRequest(Message msg) {
        final NetworkRequestInfo nri = (NetworkRequestInfo) (msg.obj);
        final NetworkCapabilities newCap = nri.request.networkCapabilities;
        int score = 0;

        mNetworkRequests.put(nri.request, nri);

        // TODO: This logic may be better replaced with a call to rematchNetworkAndRequests

        // Check for the best currently alive network that satisfies this request
        NetworkAgentInfo bestNetwork = null;
        for (NetworkAgentInfo network : mNetworkAgentInfos.values()) {
            if (DBG) log("handleRegisterNetworkRequest checking " + network.name());
            if (newCap.satisfiedByNetworkCapabilities(network.networkCapabilities)) {
            if (network.satisfies(nri.request)) {
                if (DBG) log("apparently satisfied.  currentScore=" + network.getCurrentScore());
                if ((bestNetwork == null) ||
                        bestNetwork.getCurrentScore() < network.getCurrentScore()) {
                if (!nri.isRequest) {
                    // Not setting bestNetwork here as a listening NetworkRequest may be
                    // satisfied by multiple Networks.  Instead the request is added to
                    // each satisfying Network and notified about each.
                    network.addRequest(nri.request);
                    notifyNetworkCallback(network, nri);
                    } else {
                } else if (bestNetwork == null ||
                        bestNetwork.getCurrentScore() < network.getCurrentScore()) {
                    bestNetwork = network;
                }
            }
        }
        }
        if (bestNetwork != null) {
            if (DBG) log("using " + bestNetwork.name());
            if (bestNetwork.networkInfo.isConnected()) {
                // Cancel any lingering so the linger timeout doesn't teardown this network
                // even though we have a request for it.
                bestNetwork.networkLingered.clear();
                bestNetwork.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_CONNECTED);
            }
            // TODO: This logic may be better replaced with a call to rematchNetworkAndRequests
            unlinger(bestNetwork);
            bestNetwork.addRequest(nri.request);
            mNetworkForRequestId.put(nri.request.requestId, bestNetwork);
            notifyNetworkCallback(bestNetwork, nri);
            score = bestNetwork.getCurrentScore();
            if (nri.request.legacyType != TYPE_NONE) {
                mLegacyTypeTracker.add(nri.request.legacyType, bestNetwork);
            }
@@ -2232,6 +2231,7 @@ public class ConnectivityService extends IConnectivityManager.Stub

        if (nri.isRequest) {
            if (DBG) log("sending new NetworkRequest to factories");
            final int score = bestNetwork == null ? 0 : bestNetwork.getCurrentScore();
            for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
                nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score,
                        0, nri.request);
@@ -3929,8 +3929,7 @@ public class ConnectivityService extends IConnectivityManager.Stub

            // check if it satisfies the NetworkCapabilities
            if (VDBG) log("  checking if request is satisfied: " + nri.request);
            if (nri.request.networkCapabilities.satisfiedByNetworkCapabilities(
                    newNetwork.networkCapabilities)) {
            if (newNetwork.satisfies(nri.request)) {
                if (!nri.isRequest) {
                    // This is not a request, it's a callback listener.
                    // Add it to newNetwork regardless of score.
@@ -4010,12 +4009,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
                nai.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_LINGER);
                notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOSING);
            } else {
                // not going to linger, so kill the list of linger networks..  only
                // notify them of linger if it happens as the result of gaining another,
                // but if they transition and old network stays up, don't tell them of linger
                // or very delayed loss
                nai.networkLingered.clear();
                if (VDBG) log("Lingered for " + nai.name() + " cleared");
                unlinger(nai);
            }
        }
        if (keep) {
+6 −0
Original line number Diff line number Diff line
@@ -96,6 +96,12 @@ public class NetworkAgentInfo {
        networkRequests.put(networkRequest.requestId, networkRequest);
    }

    // Does this network satisfy request?
    public boolean satisfies(NetworkRequest request) {
        return created &&
                request.networkCapabilities.satisfiedByNetworkCapabilities(networkCapabilities);
    }

    public boolean isVPN() {
        return networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN);
    }