/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.connectivity;

import android.annotation.NonNull;
import android.content.Context;
import android.net.IDnsResolver;
import android.net.INetd;
import android.net.INetworkMonitor;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkMisc;
import android.net.NetworkMonitorManager;
import android.net.NetworkRequest;
import android.net.NetworkScore;
import android.net.NetworkState;
import android.os.Handler;
import android.os.INetworkManagementService;
import android.os.Messenger;
import android.os.SystemClock;
import android.util.Log;
import android.util.SparseArray;

import com.android.internal.util.AsyncChannel;
import com.android.internal.util.WakeupMessage;
import com.android.server.ConnectivityService;

import java.io.PrintWriter;
import java.util.Objects;
import java.util.SortedSet;
import java.util.TreeSet;

/**
 * A bag class used by ConnectivityService for holding a collection of most recent
 * information published by a particular NetworkAgent as well as the
 * AsyncChannel/messenger for reaching that NetworkAgent and lists of NetworkRequests
 * interested in using it.  Default sort order is descending by score.
 */
// States of a network:
// --------------------
// 1. registered, uncreated, disconnected, unvalidated
//    This state is entered when a NetworkFactory registers a NetworkAgent in any state except
//    the CONNECTED state.
// 2. registered, uncreated, connecting, unvalidated
//    This state is entered when a registered NetworkAgent for a VPN network transitions to the
//    CONNECTING state (TODO: go through this state for every network, not just VPNs).
//    ConnectivityService will tell netd to create the network early in order to add extra UID
//    routing rules referencing the netID. These rules need to be in place before the network is
//    connected to avoid racing against client apps trying to connect to a half-setup network.
// 3. registered, uncreated, connected, unvalidated
//    This state is entered when a registered NetworkAgent transitions to the CONNECTED state.
//    ConnectivityService will tell netd to create the network if it was not already created, and
//    immediately transition to state #4.
// 4. registered, created, connected, unvalidated
//    If this network can satisfy the default NetworkRequest, then NetworkMonitor will
//    probe for Internet connectivity.
//    If this network cannot satisfy the default NetworkRequest, it will immediately be
//    transitioned to state #5.
//    A network may remain in this state if NetworkMonitor fails to find Internet connectivity,
//    for example:
//    a. a captive portal is present, or
//    b. a WiFi router whose Internet backhaul is down, or
//    c. a wireless connection stops transfering packets temporarily (e.g. device is in elevator
//       or tunnel) but does not disconnect from the AP/cell tower, or
//    d. a stand-alone device offering a WiFi AP without an uplink for configuration purposes.
// 5. registered, created, connected, validated
//
// The device's default network connection:
// ----------------------------------------
// Networks in states #4 and #5 may be used as a device's default network connection if they
// satisfy the default NetworkRequest.
// A network, that satisfies the default NetworkRequest, in state #5 should always be chosen
// in favor of a network, that satisfies the default NetworkRequest, in state #4.
// When deciding between two networks, that both satisfy the default NetworkRequest, to select
// for the default network connection, the one with the higher score should be chosen.
//
// When a network disconnects:
// ---------------------------
// If a network's transport disappears, for example:
// a. WiFi turned off, or
// b. cellular data turned off, or
// c. airplane mode is turned on, or
// d. a wireless connection disconnects from AP/cell tower entirely (e.g. device is out of range
//    of AP for an extended period of time, or switches to another AP without roaming)
// then that network can transition from any state (#1-#5) to unregistered.  This happens by
// the transport disconnecting their NetworkAgent's AsyncChannel with ConnectivityManager.
// ConnectivityService also tells netd to destroy the network.
//
// When ConnectivityService disconnects a network:
// -----------------------------------------------
// If a network has no chance of satisfying any requests (even if it were to become validated
// and enter state #5), ConnectivityService will disconnect the NetworkAgent's AsyncChannel.
//
// If the network was satisfying a foreground NetworkRequest (i.e. had been the highest scoring that
// satisfied the NetworkRequest's constraints), but is no longer the highest scoring network for any
// foreground NetworkRequest, then there will be a 30s pause to allow network communication to be
// wrapped up rather than abruptly terminated. During this pause the network is said to be
// "lingering". During this pause if the network begins satisfying a foreground NetworkRequest,
// ConnectivityService will cancel the future disconnection of the NetworkAgent's AsyncChannel, and
// the network is no longer considered "lingering". After the linger timer expires, if the network
// is satisfying one or more background NetworkRequests it is kept up in the background. If it is
// not, ConnectivityService disconnects the NetworkAgent's AsyncChannel.
public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {

    @NonNull public NetworkInfo networkInfo;
    // This Network object should always be used if possible, so as to encourage reuse of the
    // enclosed socket factory and connection pool.  Avoid creating other Network objects.
    // This Network object is always valid.
    public final Network network;
    public LinkProperties linkProperties;
    // This should only be modified by ConnectivityService, via setNetworkCapabilities().
    // TODO: make this private with a getter.
    public NetworkCapabilities networkCapabilities;
    public final NetworkMisc networkMisc;
    // Indicates if netd has been told to create this Network. From this point on the appropriate
    // routing rules are setup and routes are added so packets can begin flowing over the Network.
    // This is a sticky bit; once set it is never cleared.
    public boolean created;
    // Set to true after the first time this network is marked as CONNECTED. Once set, the network
    // shows up in API calls, is able to satisfy NetworkRequests and can become the default network.
    // This is a sticky bit; once set it is never cleared.
    public boolean everConnected;
    // Set to true if this Network successfully passed validation or if it did not satisfy the
    // default NetworkRequest in which case validation will not be attempted.
    // This is a sticky bit; once set it is never cleared even if future validation attempts fail.
    public boolean everValidated;

    // The result of the last validation attempt on this network (true if validated, false if not).
    public boolean lastValidated;

    // If true, becoming unvalidated will lower the network's score. This is only meaningful if the
    // system is configured not to do this for certain networks, e.g., if the
    // config_networkAvoidBadWifi option is set to 0 and the user has not overridden that via
    // Settings.Global.NETWORK_AVOID_BAD_WIFI.
    public boolean avoidUnvalidated;

    // Whether a captive portal was ever detected on this network.
    // This is a sticky bit; once set it is never cleared.
    public boolean everCaptivePortalDetected;

    // Whether a captive portal was found during the last network validation attempt.
    public boolean lastCaptivePortalDetected;

    // Indicates the captive portal app was opened to show a login UI to the user, but the network
    // has not validated yet.
    public volatile boolean captivePortalValidationPending;

    // Set to true when partial connectivity was detected.
    public boolean partialConnectivity;

    // Networks are lingered when they become unneeded as a result of their NetworkRequests being
    // satisfied by a higher-scoring network. so as to allow communication to wrap up before the
    // network is taken down.  This usually only happens to the default network. Lingering ends with
    // either the linger timeout expiring and the network being taken down, or the network
    // satisfying a request again.
    public static class LingerTimer implements Comparable<LingerTimer> {
        public final NetworkRequest request;
        public final long expiryMs;

        public LingerTimer(NetworkRequest request, long expiryMs) {
            this.request = request;
            this.expiryMs = expiryMs;
        }
        public boolean equals(Object o) {
            if (!(o instanceof LingerTimer)) return false;
            LingerTimer other = (LingerTimer) o;
            return (request.requestId == other.request.requestId) && (expiryMs == other.expiryMs);
        }
        public int hashCode() {
            return Objects.hash(request.requestId, expiryMs);
        }
        public int compareTo(LingerTimer other) {
            return (expiryMs != other.expiryMs) ?
                    Long.compare(expiryMs, other.expiryMs) :
                    Integer.compare(request.requestId, other.request.requestId);
        }
        public String toString() {
            return String.format("%s, expires %dms", request.toString(),
                    expiryMs - SystemClock.elapsedRealtime());
        }
    }

    /**
     * Inform ConnectivityService that the network LINGER period has
     * expired.
     * obj = this NetworkAgentInfo
     */
    public static final int EVENT_NETWORK_LINGER_COMPLETE = 1001;

    // All linger timers for this network, sorted by expiry time. A linger timer is added whenever
    // a request is moved to a network with a better score, regardless of whether the network is or
    // was lingering or not.
    // TODO: determine if we can replace this with a smaller or unsorted data structure. (e.g.,
    // SparseLongArray) combined with the timestamp of when the last timer is scheduled to fire.
    private final SortedSet<LingerTimer> mLingerTimers = new TreeSet<>();

    // For fast lookups. Indexes into mLingerTimers by request ID.
    private final SparseArray<LingerTimer> mLingerTimerForRequest = new SparseArray<>();

    // Linger expiry timer. Armed whenever mLingerTimers is non-empty, regardless of whether the
    // network is lingering or not. Always set to the expiry of the LingerTimer that expires last.
    // When the timer fires, all linger state is cleared, and if the network has no requests, it is
    // torn down.
    private WakeupMessage mLingerMessage;

    // Linger expiry. Holds the expiry time of the linger timer, or 0 if the timer is not armed.
    private long mLingerExpiryMs;

    // Whether the network is lingering or not. Must be maintained separately from the above because
    // it depends on the state of other networks and requests, which only ConnectivityService knows.
    // (Example: we don't linger a network if it would become the best for a NetworkRequest if it
    // validated).
    private boolean mLingering;

    // This represents the characteristics of a network that affects how good the network is
    // considered for a particular use.
    @NonNull
    private NetworkScore mNetworkScore;

    // The list of NetworkRequests being satisfied by this Network.
    private final SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>();

    // How many of the satisfied requests are actual requests and not listens.
    private int mNumRequestNetworkRequests = 0;

    // How many of the satisfied requests are of type BACKGROUND_REQUEST.
    private int mNumBackgroundNetworkRequests = 0;

    public final Messenger messenger;
    public final AsyncChannel asyncChannel;

    public final int factorySerialNumber;

    // Used by ConnectivityService to keep track of 464xlat.
    public final Nat464Xlat clatd;

    // Set after asynchronous creation of the NetworkMonitor.
    private volatile NetworkMonitorManager mNetworkMonitor;

    private static final String TAG = ConnectivityService.class.getSimpleName();
    private static final boolean VDBG = false;
    private final ConnectivityService mConnService;
    private final Context mContext;
    private final Handler mHandler;

    public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, Network net, NetworkInfo info,
            LinkProperties lp, NetworkCapabilities nc, @NonNull NetworkScore ns, Context context,
            Handler handler, NetworkMisc misc, ConnectivityService connService, INetd netd,
            IDnsResolver dnsResolver, INetworkManagementService nms, int factorySerialNumber) {
        this.messenger = messenger;
        asyncChannel = ac;
        network = net;
        networkInfo = info;
        linkProperties = lp;
        networkCapabilities = nc;
        mNetworkScore = ns;
        clatd = new Nat464Xlat(this, netd, dnsResolver, nms);
        mConnService = connService;
        mContext = context;
        mHandler = handler;
        networkMisc = misc;
        this.factorySerialNumber = factorySerialNumber;
    }

    /**
     * Inform NetworkAgentInfo that a new NetworkMonitor was created.
     */
    public void onNetworkMonitorCreated(INetworkMonitor networkMonitor) {
        mNetworkMonitor = new NetworkMonitorManager(networkMonitor);
    }

    /**
     * Set the NetworkCapabilities on this NetworkAgentInfo. Also attempts to notify NetworkMonitor
     * of the new capabilities, if NetworkMonitor has been created.
     *
     * <p>If {@link NetworkMonitor#notifyNetworkCapabilitiesChanged(NetworkCapabilities)} fails,
     * the exception is logged but not reported to callers.
     */
    public void setNetworkCapabilities(NetworkCapabilities nc) {
        networkCapabilities = nc;
        final NetworkMonitorManager nm = mNetworkMonitor;
        if (nm != null) {
            nm.notifyNetworkCapabilitiesChanged(nc);
        }
    }

    public ConnectivityService connService() {
        return mConnService;
    }

    public NetworkMisc netMisc() {
        return networkMisc;
    }

    public Handler handler() {
        return mHandler;
    }

    public Network network() {
        return network;
    }

    /**
     * Get the NetworkMonitorManager in this NetworkAgentInfo.
     *
     * <p>This will be null before {@link #onNetworkMonitorCreated(INetworkMonitor)} is called.
     */
    public NetworkMonitorManager networkMonitor() {
        return mNetworkMonitor;
    }

    // Functions for manipulating the requests satisfied by this network.
    //
    // These functions must only called on ConnectivityService's main thread.

    private static final boolean ADD = true;
    private static final boolean REMOVE = false;

    private void updateRequestCounts(boolean add, NetworkRequest request) {
        int delta = add ? +1 : -1;
        switch (request.type) {
            case REQUEST:
                mNumRequestNetworkRequests += delta;
                break;

            case BACKGROUND_REQUEST:
                mNumRequestNetworkRequests += delta;
                mNumBackgroundNetworkRequests += delta;
                break;

            case TRACK_DEFAULT:
            case LISTEN:
                break;

            case NONE:
            default:
                Log.wtf(TAG, "Unhandled request type " + request.type);
                break;
        }
    }

    /**
     * Add {@code networkRequest} to this network as it's satisfied by this network.
     * @return true if {@code networkRequest} was added or false if {@code networkRequest} was
     *         already present.
     */
    public boolean addRequest(NetworkRequest networkRequest) {
        NetworkRequest existing = mNetworkRequests.get(networkRequest.requestId);
        if (existing == networkRequest) return false;
        if (existing != null) {
            // Should only happen if the requestId wraps. If that happens lots of other things will
            // be broken as well.
            Log.wtf(TAG, String.format("Duplicate requestId for %s and %s on %s",
                    networkRequest, existing, name()));
            updateRequestCounts(REMOVE, existing);
        }
        mNetworkRequests.put(networkRequest.requestId, networkRequest);
        updateRequestCounts(ADD, networkRequest);
        return true;
    }

    /**
     * Remove the specified request from this network.
     */
    public void removeRequest(int requestId) {
        NetworkRequest existing = mNetworkRequests.get(requestId);
        if (existing == null) return;
        updateRequestCounts(REMOVE, existing);
        mNetworkRequests.remove(requestId);
        if (existing.isRequest()) {
            unlingerRequest(existing);
        }
    }

    /**
     * Returns whether this network is currently satisfying the request with the specified ID.
     */
    public boolean isSatisfyingRequest(int id) {
        return mNetworkRequests.get(id) != null;
    }

    /**
     * Returns the request at the specified position in the list of requests satisfied by this
     * network.
     */
    public NetworkRequest requestAt(int index) {
        return mNetworkRequests.valueAt(index);
    }

    /**
     * Returns the number of requests currently satisfied by this network for which
     * {@link android.net.NetworkRequest#isRequest} returns {@code true}.
     */
    public int numRequestNetworkRequests() {
        return mNumRequestNetworkRequests;
    }

    /**
     * Returns the number of requests currently satisfied by this network of type
     * {@link android.net.NetworkRequest.Type.BACKGROUND_REQUEST}.
     */
    public int numBackgroundNetworkRequests() {
        return mNumBackgroundNetworkRequests;
    }

    /**
     * Returns the number of foreground requests currently satisfied by this network.
     */
    public int numForegroundNetworkRequests() {
        return mNumRequestNetworkRequests - mNumBackgroundNetworkRequests;
    }

    /**
     * Returns the number of requests of any type currently satisfied by this network.
     */
    public int numNetworkRequests() {
        return mNetworkRequests.size();
    }

    /**
     * Returns whether the network is a background network. A network is a background network if it
     * does not have the NET_CAPABILITY_FOREGROUND capability, which implies it is satisfying no
     * foreground request, is not lingering (i.e. kept for a while after being outscored), and is
     * not a speculative network (i.e. kept pending validation when validation would have it
     * outscore another foreground network). That implies it is being kept up by some background
     * request (otherwise it would be torn down), maybe the mobile always-on request.
     */
    public boolean isBackgroundNetwork() {
        return !isVPN() && numForegroundNetworkRequests() == 0 && mNumBackgroundNetworkRequests > 0
                && !isLingering();
    }

    /**
     * Returns whether this network is currently suspended. A network is suspended if it is still
     * connected but data temporarily fails to transfer. See {@link NetworkInfo.State#SUSPENDED}
     * and {@link NetworkCapabilities#NET_CAPABILITY_NOT_SUSPENDED}.
     */
    public boolean isSuspended() {
        return networkInfo.getState() == NetworkInfo.State.SUSPENDED;
    }

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

    public boolean satisfiesImmutableCapabilitiesOf(NetworkRequest request) {
        return created &&
                request.networkCapabilities.satisfiedByImmutableNetworkCapabilities(
                        networkCapabilities);
    }

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

    private int getCurrentScore(boolean pretendValidated) {
        // TODO: We may want to refactor this into a NetworkScore class that takes a base score from
        // the NetworkAgent and signals from the NetworkAgent and uses those signals to modify the
        // score.  The NetworkScore class would provide a nice place to centralize score constants
        // so they are not scattered about the transports.

        // If this network is explicitly selected and the user has decided to use it even if it's
        // unvalidated, give it the maximum score. Also give it the maximum score if it's explicitly
        // selected and we're trying to see what its score could be. This ensures that we don't tear
        // down an explicitly selected network before the user gets a chance to prefer it when
        // a higher-scoring network (e.g., Ethernet) is available.
        if (networkMisc.explicitlySelected && (networkMisc.acceptUnvalidated || pretendValidated)) {
            return ConnectivityConstants.EXPLICITLY_SELECTED_NETWORK_SCORE;
        }

        int score = mNetworkScore.getIntExtension(NetworkScore.LEGACY_SCORE);
        if (!lastValidated && !pretendValidated && !ignoreWifiUnvalidationPenalty() && !isVPN()) {
            score -= ConnectivityConstants.UNVALIDATED_SCORE_PENALTY;
        }
        if (score < 0) score = 0;
        return score;
    }

    // Return true on devices configured to ignore score penalty for wifi networks
    // that become unvalidated (b/31075769).
    private boolean ignoreWifiUnvalidationPenalty() {
        boolean isWifi = networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) &&
                networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
        boolean avoidBadWifi = mConnService.avoidBadWifi() || avoidUnvalidated;
        return isWifi && !avoidBadWifi && everValidated;
    }

    // Get the current score for this Network.  This may be modified from what the
    // NetworkAgent sent, as it has modifiers applied to it.
    public int getCurrentScore() {
        return getCurrentScore(false);
    }

    // Get the current score for this Network as if it was validated.  This may be modified from
    // what the NetworkAgent sent, as it has modifiers applied to it.
    public int getCurrentScoreAsValidated() {
        return getCurrentScore(true);
    }

    public void setNetworkScore(@NonNull NetworkScore ns) {
        mNetworkScore = ns;
    }

    @NonNull
    public NetworkScore getNetworkScore() {
        return mNetworkScore;
    }

    public NetworkState getNetworkState() {
        synchronized (this) {
            // Network objects are outwardly immutable so there is no point in duplicating.
            // Duplicating also precludes sharing socket factories and connection pools.
            final String subscriberId = (networkMisc != null) ? networkMisc.subscriberId : null;
            return new NetworkState(new NetworkInfo(networkInfo),
                    new LinkProperties(linkProperties),
                    new NetworkCapabilities(networkCapabilities), network, subscriberId, null);
        }
    }

    /**
     * Sets the specified request to linger on this network for the specified time. Called by
     * ConnectivityService when the request is moved to another network with a higher score.
     */
    public void lingerRequest(NetworkRequest request, long now, long duration) {
        if (mLingerTimerForRequest.get(request.requestId) != null) {
            // Cannot happen. Once a request is lingering on a particular network, we cannot
            // re-linger it unless that network becomes the best for that request again, in which
            // case we should have unlingered it.
            Log.wtf(TAG, this.name() + ": request " + request.requestId + " already lingered");
        }
        final long expiryMs = now + duration;
        LingerTimer timer = new LingerTimer(request, expiryMs);
        if (VDBG) Log.d(TAG, "Adding LingerTimer " + timer + " to " + this.name());
        mLingerTimers.add(timer);
        mLingerTimerForRequest.put(request.requestId, timer);
    }

    /**
     * Cancel lingering. Called by ConnectivityService when a request is added to this network.
     * Returns true if the given request was lingering on this network, false otherwise.
     */
    public boolean unlingerRequest(NetworkRequest request) {
        LingerTimer timer = mLingerTimerForRequest.get(request.requestId);
        if (timer != null) {
            if (VDBG) Log.d(TAG, "Removing LingerTimer " + timer + " from " + this.name());
            mLingerTimers.remove(timer);
            mLingerTimerForRequest.remove(request.requestId);
            return true;
        }
        return false;
    }

    public long getLingerExpiry() {
        return mLingerExpiryMs;
    }

    public void updateLingerTimer() {
        long newExpiry = mLingerTimers.isEmpty() ? 0 : mLingerTimers.last().expiryMs;
        if (newExpiry == mLingerExpiryMs) return;

        // Even if we're going to reschedule the timer, cancel it first. This is because the
        // semantics of WakeupMessage guarantee that if cancel is called then the alarm will
        // never call its callback (handleLingerComplete), even if it has already fired.
        // WakeupMessage makes no such guarantees about rescheduling a message, so if mLingerMessage
        // has already been dispatched, rescheduling to some time in the future it won't stop it
        // from calling its callback immediately.
        if (mLingerMessage != null) {
            mLingerMessage.cancel();
            mLingerMessage = null;
        }

        if (newExpiry > 0) {
            mLingerMessage = new WakeupMessage(
                    mContext, mHandler,
                    "NETWORK_LINGER_COMPLETE." + network.netId /* cmdName */,
                    EVENT_NETWORK_LINGER_COMPLETE /* cmd */,
                    0 /* arg1 (unused) */, 0 /* arg2 (unused) */,
                    this /* obj (NetworkAgentInfo) */);
            mLingerMessage.schedule(newExpiry);
        }

        mLingerExpiryMs = newExpiry;
    }

    public void linger() {
        mLingering = true;
    }

    public void unlinger() {
        mLingering = false;
    }

    public boolean isLingering() {
        return mLingering;
    }

    public void clearLingerState() {
        if (mLingerMessage != null) {
            mLingerMessage.cancel();
            mLingerMessage = null;
        }
        mLingerTimers.clear();
        mLingerTimerForRequest.clear();
        updateLingerTimer();  // Sets mLingerExpiryMs, cancels and nulls out mLingerMessage.
        mLingering = false;
    }

    public void dumpLingerTimers(PrintWriter pw) {
        for (LingerTimer timer : mLingerTimers) { pw.println(timer); }
    }

    // TODO: Print shorter members first and only print the boolean variable which value is true
    // to improve readability.
    public String toString() {
        return "NetworkAgentInfo{ ni{" + networkInfo + "}  "
                + "network{" + network + "}  nethandle{" + network.getNetworkHandle() + "}  "
                + "lp{" + linkProperties + "}  "
                + "nc{" + networkCapabilities + "}  Score{" + getCurrentScore() + "}  "
                + "everValidated{" + everValidated + "}  lastValidated{" + lastValidated + "}  "
                + "created{" + created + "} lingering{" + isLingering() + "} "
                + "explicitlySelected{" + networkMisc.explicitlySelected + "} "
                + "acceptUnvalidated{" + networkMisc.acceptUnvalidated + "} "
                + "everCaptivePortalDetected{" + everCaptivePortalDetected + "} "
                + "lastCaptivePortalDetected{" + lastCaptivePortalDetected + "} "
                + "captivePortalValidationPending{" + captivePortalValidationPending + "} "
                + "partialConnectivity{" + partialConnectivity + "} "
                + "acceptPartialConnectivity{" + networkMisc.acceptPartialConnectivity + "} "
                + "clat{" + clatd + "} "
                + "}";
    }

    public String name() {
        return "NetworkAgentInfo [" + networkInfo.getTypeName() + " (" +
                networkInfo.getSubtypeName() + ") - " + Objects.toString(network) + "]";
    }

    // Enables sorting in descending order of score.
    @Override
    public int compareTo(NetworkAgentInfo other) {
        return other.getCurrentScore() - getCurrentScore();
    }
}
