/*
 * 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 static android.net.ConnectivityDiagnosticsManager.ConnectivityReport;
import static android.net.NetworkCapabilities.transportNamesOf;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.net.CaptivePortalData;
import android.net.IDnsResolver;
import android.net.INetd;
import android.net.INetworkMonitor;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkAgentConfig;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkMonitorManager;
import android.net.NetworkRequest;
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 NetworkAgentConfig networkAgentConfig;
    // 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;

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

    // Captive portal info of the network, if any.
    // Obtained by ConnectivityService and merged into NetworkAgent-provided information.
    public CaptivePortalData captivePortalData;

    // 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 quality of the network with no clear scale.
    private int mScore;

    // 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;

    // The last ConnectivityReport made available for this network. This value is only null before a
    // report is generated. Once non-null, it will never be null again.
    @Nullable private ConnectivityReport mConnectivityReport;

    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, int score, Context context,
            Handler handler, NetworkAgentConfig config, ConnectivityService connService, INetd netd,
            IDnsResolver dnsResolver, INetworkManagementService nms, int factorySerialNumber) {
        this.messenger = messenger;
        asyncChannel = ac;
        network = net;
        networkInfo = info;
        linkProperties = lp;
        networkCapabilities = nc;
        mScore = score;
        clatd = new Nat464Xlat(this, netd, dnsResolver, nms);
        mConnService = connService;
        mContext = context;
        mHandler = handler;
        networkAgentConfig = config;
        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.
     *
     * @return the old capabilities of this network.
     */
    public synchronized NetworkCapabilities getAndSetNetworkCapabilities(
            @NonNull final NetworkCapabilities nc) {
        final NetworkCapabilities oldNc = networkCapabilities;
        networkCapabilities = nc;
        final NetworkMonitorManager nm = mNetworkMonitor;
        if (nm != null) {
            nm.notifyNetworkCapabilitiesChanged(nc);
        }
        return oldNc;
    }

    public ConnectivityService connService() {
        return mConnService;
    }

    public NetworkAgentConfig netAgentConfig() {
        return networkAgentConfig;
    }

    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, toShortString()));
            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();
    }

    // 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 (networkAgentConfig.explicitlySelected
                && (networkAgentConfig.acceptUnvalidated || pretendValidated)) {
            return ConnectivityConstants.EXPLICITLY_SELECTED_NETWORK_SCORE;
        }

        int score = mScore;
        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 setScore(final int score) {
        mScore = score;
    }

    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 = (networkAgentConfig != null)
                    ? networkAgentConfig.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, toShortString() + ": 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 " + toShortString());
        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 " + toShortString());
            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 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); }
    }

    /**
     * Sets the most recent ConnectivityReport for this network.
     *
     * <p>This should only be called from the ConnectivityService thread.
     *
     * @hide
     */
    public void setConnectivityReport(@NonNull ConnectivityReport connectivityReport) {
        mConnectivityReport = connectivityReport;
    }

    /**
     * Returns the most recent ConnectivityReport for this network, or null if none have been
     * reported yet.
     *
     * <p>This should only be called from the ConnectivityService thread.
     *
     * @hide
     */
    @Nullable
    public ConnectivityReport getConnectivityReport() {
        return mConnectivityReport;
    }

    // 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{" + networkAgentConfig.explicitlySelected + "} "
                + "acceptUnvalidated{" + networkAgentConfig.acceptUnvalidated + "} "
                + "everCaptivePortalDetected{" + everCaptivePortalDetected + "} "
                + "lastCaptivePortalDetected{" + lastCaptivePortalDetected + "} "
                + "partialConnectivity{" + partialConnectivity + "} "
                + "acceptPartialConnectivity{" + networkAgentConfig.acceptPartialConnectivity + "} "
                + "clat{" + clatd + "} "
                + "}";
    }

    /**
     * Show a short string representing a Network.
     *
     * This is often not enough for debugging purposes for anything complex, but the full form
     * is very long and hard to read, so this is useful when there isn't a lot of ambiguity.
     * This represents the network with something like "[100 WIFI|VPN]" or "[108 MOBILE]".
     */
    public String toShortString() {
        return "[" + network.netId + " "
                + transportNamesOf(networkCapabilities.getTransportTypes()) + "]";
    }

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

    /**
     * Null-guarding version of NetworkAgentInfo#toShortString()
     */
    @NonNull
    public static String toShortString(@Nullable final NetworkAgentInfo nai) {
        return null != nai ? nai.toShortString() : "[null]";
    }
}
