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

Commit 2c2e476b authored by Chalard Jean's avatar Chalard Jean
Browse files

[NS07] Add the rest of the scoring policy

Bug: 167544279
Test: FrameworksNetTests
Change-Id: I5ea44a94ac6f16486274e9091f15a84734db2341
parent ba049548
Loading
Loading
Loading
Loading
+144 −4
Original line number Original line Diff line number Diff line
@@ -52,11 +52,27 @@ public final class NetworkScore implements Parcelable {
    public static final int KEEP_CONNECTED_FOR_HANDOVER = 1;
    public static final int KEEP_CONNECTED_FOR_HANDOVER = 1;


    // Agent-managed policies
    // Agent-managed policies
    // TODO : add them here, starting from 1
    // This network should lose to a wifi that has ever been validated
    // NOTE : temporarily this policy is managed by ConnectivityService, because of legacy. The
    // legacy design has this bit global to the system and tacked on WiFi which means it will affect
    // networks from carriers who don't want it and non-carrier networks, which is bad for users.
    // The S design has this on mobile networks only, so this can be fixed eventually ; as CS
    // doesn't know what carriers need this bit, the initial S implementation will continue to
    // affect other carriers but will at least leave non-mobile networks alone. Eventually Telephony
    // should set this on networks from carriers that require it.
    /** @hide */
    /** @hide */
    public static final int MIN_AGENT_MANAGED_POLICY = 0;
    public static final int POLICY_YIELD_TO_BAD_WIFI = 1;
    // This network is primary for this transport.
    /** @hide */
    /** @hide */
    public static final int MAX_AGENT_MANAGED_POLICY = -1;
    public static final int POLICY_TRANSPORT_PRIMARY = 2;
    // This network is exiting : it will likely disconnect in a few seconds.
    /** @hide */
    public static final int POLICY_EXITING = 3;

    /** @hide */
    public static final int MIN_AGENT_MANAGED_POLICY = POLICY_YIELD_TO_BAD_WIFI;
    /** @hide */
    public static final int MAX_AGENT_MANAGED_POLICY = POLICY_EXITING;


    // Bitmask of all the policies applied to this score.
    // Bitmask of all the policies applied to this score.
    private final long mPolicies;
    private final long mPolicies;
@@ -98,6 +114,60 @@ public final class NetworkScore implements Parcelable {
        return 0 != (mPolicies & (1L << policy));
        return 0 != (mPolicies & (1L << policy));
    }
    }


    /**
     * To the exclusive usage of FullScore
     * @hide
     */
    public long getPolicies() {
        return mPolicies;
    }

    /**
     * Whether this network should yield to a previously validated wifi gone bad.
     *
     * If this policy is set, other things being equal, the device will prefer a previously
     * validated WiFi even if this network is validated and the WiFi is not.
     * If this policy is not set, the device prefers the validated network.
     *
     * @hide
     */
    // TODO : Unhide this for telephony and have telephony call it on the relevant carriers.
    // In the mean time this is handled by Connectivity in a backward-compatible manner.
    public boolean shouldYieldToBadWifi() {
        return hasPolicy(POLICY_YIELD_TO_BAD_WIFI);
    }

    /**
     * Whether this network is primary for this transport.
     *
     * When multiple networks of the same transport are active, the device prefers the ones that
     * are primary. This is meant in particular for DS-DA devices with a user setting to choose the
     * default SIM card, or for WiFi STA+STA and make-before-break cases.
     *
     * @hide
     */
    // TODO : @SystemApi
    public boolean isTransportPrimary() {
        return hasPolicy(POLICY_TRANSPORT_PRIMARY);
    }

    /**
     * Whether this network is exiting.
     *
     * If this policy is set, the device will expect this network to disconnect within seconds.
     * It will try to migrate to some other network if any is available, policy permitting, to
     * avoid service disruption.
     * This is useful in particular when a good cellular network is available and WiFi is getting
     * weak and risks disconnecting soon. The WiFi network should be marked as exiting so that
     * the device will prefer the reliable mobile network over this soon-to-be-lost WiFi.
     *
     * @hide
     */
    // TODO : @SystemApi
    public boolean isExiting() {
        return hasPolicy(POLICY_EXITING);
    }

    @Override
    @Override
    public String toString() {
    public String toString() {
        return "Score(" + mLegacyInt + ")";
        return "Score(" + mLegacyInt + ")";
@@ -137,6 +207,7 @@ public final class NetworkScore implements Parcelable {
        private static final int INVALID_LEGACY_INT = Integer.MIN_VALUE;
        private static final int INVALID_LEGACY_INT = Integer.MIN_VALUE;
        private int mLegacyInt = INVALID_LEGACY_INT;
        private int mLegacyInt = INVALID_LEGACY_INT;
        private int mKeepConnectedReason = KEEP_CONNECTED_NONE;
        private int mKeepConnectedReason = KEEP_CONNECTED_NONE;
        private int mPolicies = 0;


        /**
        /**
         * Sets the legacy int for this score.
         * Sets the legacy int for this score.
@@ -152,6 +223,75 @@ public final class NetworkScore implements Parcelable {
            return this;
            return this;
        }
        }



        /**
         * Set for a network that should never be preferred to a wifi that has ever been validated
         *
         * If this policy is set, other things being equal, the device will prefer a previously
         * validated WiFi even if this network is validated and the WiFi is not.
         * If this policy is not set, the device prefers the validated network.
         *
         * @return this builder
         * @hide
         */
        // TODO : Unhide this for telephony and have telephony call it on the relevant carriers.
        // In the mean time this is handled by Connectivity in a backward-compatible manner.
        @NonNull
        public Builder setShouldYieldToBadWifi(final boolean val) {
            if (val) {
                mPolicies |= (1L << POLICY_YIELD_TO_BAD_WIFI);
            } else {
                mPolicies &= ~(1L << POLICY_YIELD_TO_BAD_WIFI);
            }
            return this;
        }

        /**
         * Set for a network that is primary for this transport.
         *
         * When multiple networks of the same transport are active, the device prefers the ones that
         * are primary. This is meant in particular for DS-DA devices with a user setting to choose
         * the default SIM card, or for WiFi STA+STA and make-before-break cases.
         *
         * @return this builder
         * @hide
         */
        // TODO : @SystemApi
        @NonNull
        public Builder setTransportPrimary(final boolean val) {
            if (val) {
                mPolicies |= (1L << POLICY_TRANSPORT_PRIMARY);
            } else {
                mPolicies &= ~(1L << POLICY_TRANSPORT_PRIMARY);
            }
            return this;
        }

        /**
         * Set for a network that will likely disconnect in a few seconds.
         *
         * If this policy is set, the device will expect this network to disconnect within seconds.
         * It will try to migrate to some other network if any is available, policy permitting, to
         * avoid service disruption.
         * This is useful in particular when a good cellular network is available and WiFi is
         * getting weak and risks disconnecting soon. The WiFi network should be marked as exiting
         * so that the device will prefer the reliable mobile network over this soon-to-be-lost
         * WiFi.
         *
         * @return this builder
         * @hide
         */
        // TODO : @SystemApi
        @NonNull
        public Builder setExiting(final boolean val) {
            if (val) {
                mPolicies |= (1L << POLICY_EXITING);
            } else {
                mPolicies &= ~(1L << POLICY_EXITING);
            }
            return this;
        }

        /**
        /**
         * Set the keep-connected reason.
         * Set the keep-connected reason.
         *
         *
@@ -169,7 +309,7 @@ public final class NetworkScore implements Parcelable {
         */
         */
        @NonNull
        @NonNull
        public NetworkScore build() {
        public NetworkScore build() {
            return new NetworkScore(mLegacyInt, POLICY_NONE, mKeepConnectedReason);
            return new NetworkScore(mLegacyInt, mPolicies, mKeepConnectedReason);
        }
        }
    }
    }
}
}
+5 −3
Original line number Original line Diff line number Diff line
@@ -1324,7 +1324,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
        mLingerMonitor = new LingerMonitor(mContext, mNotifier, dailyLimit, rateLimit);
        mLingerMonitor = new LingerMonitor(mContext, mNotifier, dailyLimit, rateLimit);


        mMultinetworkPolicyTracker = mDeps.makeMultinetworkPolicyTracker(
        mMultinetworkPolicyTracker = mDeps.makeMultinetworkPolicyTracker(
                mContext, mHandler, () -> rematchForAvoidBadWifiUpdate());
                mContext, mHandler, () -> updateAvoidBadWifi());
        mMultinetworkPolicyTracker.start();
        mMultinetworkPolicyTracker.start();


        mDnsManager = new DnsManager(mContext, mDnsResolver);
        mDnsManager = new DnsManager(mContext, mDnsResolver);
@@ -4370,8 +4370,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
        return avoidBadWifi();
        return avoidBadWifi();
    }
    }


    // TODO : this function is now useless.
    private void updateAvoidBadWifi() {
    private void rematchForAvoidBadWifiUpdate() {
        for (final NetworkAgentInfo nai : mNetworkAgentInfos) {
            nai.updateScoreForNetworkAgentConfigUpdate();
        }
        rematchAllNetworksAndRequests();
        rematchAllNetworksAndRequests();
    }
    }


+60 −15
Original line number Original line Diff line number Diff line
@@ -17,9 +17,13 @@
package com.android.server.connectivity;
package com.android.server.connectivity;


import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkScore.KEEP_CONNECTED_NONE;
import static android.net.NetworkScore.KEEP_CONNECTED_NONE;
import static android.net.NetworkScore.POLICY_EXITING;
import static android.net.NetworkScore.POLICY_TRANSPORT_PRIMARY;
import static android.net.NetworkScore.POLICY_YIELD_TO_BAD_WIFI;


import android.annotation.IntDef;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.NonNull;
@@ -52,7 +56,8 @@ public class FullScore {
            POLICY_IS_VALIDATED,
            POLICY_IS_VALIDATED,
            POLICY_IS_VPN,
            POLICY_IS_VPN,
            POLICY_EVER_USER_SELECTED,
            POLICY_EVER_USER_SELECTED,
            POLICY_ACCEPT_UNVALIDATED
            POLICY_ACCEPT_UNVALIDATED,
            POLICY_IS_UNMETERED
    })
    })
    public @interface Policy {
    public @interface Policy {
    }
    }
@@ -77,12 +82,22 @@ public class FullScore {
    /** @hide */
    /** @hide */
    public static final int POLICY_ACCEPT_UNVALIDATED = 60;
    public static final int POLICY_ACCEPT_UNVALIDATED = 60;


    // This network is unmetered. {@see NetworkCapabilities.NET_CAPABILITY_NOT_METERED}.
    /** @hide */
    public static final int POLICY_IS_UNMETERED = 59;

    // To help iterate when printing
    // To help iterate when printing
    @VisibleForTesting
    @VisibleForTesting
    static final int MIN_CS_MANAGED_POLICY = POLICY_ACCEPT_UNVALIDATED;
    static final int MIN_CS_MANAGED_POLICY = POLICY_IS_UNMETERED;
    @VisibleForTesting
    @VisibleForTesting
    static final int MAX_CS_MANAGED_POLICY = POLICY_IS_VALIDATED;
    static final int MAX_CS_MANAGED_POLICY = POLICY_IS_VALIDATED;


    // Mask for policies in NetworkScore. This should have all bits managed by NetworkScore set
    // and all bits managed by FullScore unset. As bits are handled from 0 up in NetworkScore and
    // from 63 down in FullScore, cut at the 32rd bit for simplicity, but change this if some day
    // there are more than 32 bits handled on either side.
    private static final int EXTERNAL_POLICIES_MASK = 0x0000FFFF;

    @VisibleForTesting
    @VisibleForTesting
    static @NonNull String policyNameOf(final int policy) {
    static @NonNull String policyNameOf(final int policy) {
        switch (policy) {
        switch (policy) {
@@ -90,6 +105,10 @@ public class FullScore {
            case POLICY_IS_VPN: return "IS_VPN";
            case POLICY_IS_VPN: return "IS_VPN";
            case POLICY_EVER_USER_SELECTED: return "EVER_USER_SELECTED";
            case POLICY_EVER_USER_SELECTED: return "EVER_USER_SELECTED";
            case POLICY_ACCEPT_UNVALIDATED: return "ACCEPT_UNVALIDATED";
            case POLICY_ACCEPT_UNVALIDATED: return "ACCEPT_UNVALIDATED";
            case POLICY_IS_UNMETERED: return "IS_UNMETERED";
            case POLICY_YIELD_TO_BAD_WIFI: return "YIELD_TO_BAD_WIFI";
            case POLICY_TRANSPORT_PRIMARY: return "TRANSPORT_PRIMARY";
            case POLICY_EXITING: return "EXITING";
        }
        }
        throw new IllegalArgumentException("Unknown policy : " + policy);
        throw new IllegalArgumentException("Unknown policy : " + policy);
    }
    }
@@ -112,15 +131,23 @@ public class FullScore {
     * @param score the score supplied by the agent
     * @param score the score supplied by the agent
     * @param caps the NetworkCapabilities of the network
     * @param caps the NetworkCapabilities of the network
     * @param config the NetworkAgentConfig of the network
     * @param config the NetworkAgentConfig of the network
     * @return an FullScore that is appropriate to use for ranking.
     * @param yieldToBadWiFi whether this network yields to a previously validated wifi gone bad
     * @return a FullScore that is appropriate to use for ranking.
     */
     */
    // TODO : this shouldn't manage bad wifi avoidance – instead this should be done by the
    // telephony factory, so that it depends on the carrier. For now this is handled by
    // connectivity for backward compatibility.
    public static FullScore fromNetworkScore(@NonNull final NetworkScore score,
    public static FullScore fromNetworkScore(@NonNull final NetworkScore score,
            @NonNull final NetworkCapabilities caps, @NonNull final NetworkAgentConfig config) {
            @NonNull final NetworkCapabilities caps, @NonNull final NetworkAgentConfig config,
        return withPolicies(score.getLegacyInt(), score.getKeepConnectedReason(),
            final boolean yieldToBadWiFi) {
        return withPolicies(score.getLegacyInt(), score.getPolicies(),
                score.getKeepConnectedReason(),
                caps.hasCapability(NET_CAPABILITY_VALIDATED),
                caps.hasCapability(NET_CAPABILITY_VALIDATED),
                caps.hasTransport(TRANSPORT_VPN),
                caps.hasTransport(TRANSPORT_VPN),
                caps.hasCapability(NET_CAPABILITY_NOT_METERED),
                config.explicitlySelected,
                config.explicitlySelected,
                config.acceptUnvalidated);
                config.acceptUnvalidated,
                yieldToBadWiFi);
    }
    }


    /**
    /**
@@ -142,12 +169,17 @@ public class FullScore {
        final boolean mayValidate = caps.hasCapability(NET_CAPABILITY_INTERNET);
        final boolean mayValidate = caps.hasCapability(NET_CAPABILITY_INTERNET);
        // VPN transports are known in advance.
        // VPN transports are known in advance.
        final boolean vpn = caps.hasTransport(TRANSPORT_VPN);
        final boolean vpn = caps.hasTransport(TRANSPORT_VPN);
        // Prospective scores are always unmetered, because unmetered networks are stronger
        // than metered networks, and it's not known in advance whether the network is metered.
        final boolean unmetered = true;
        // The network hasn't been chosen by the user (yet, at least).
        // The network hasn't been chosen by the user (yet, at least).
        final boolean everUserSelected = false;
        final boolean everUserSelected = false;
        // Don't assume the user will accept unvalidated connectivity.
        // Don't assume the user will accept unvalidated connectivity.
        final boolean acceptUnvalidated = false;
        final boolean acceptUnvalidated = false;
        return withPolicies(score.getLegacyInt(), KEEP_CONNECTED_NONE,
        // Don't assume clinging to bad wifi
                mayValidate, vpn, everUserSelected, acceptUnvalidated);
        final boolean yieldToBadWiFi = false;
        return withPolicies(score.getLegacyInt(), score.getPolicies(), KEEP_CONNECTED_NONE,
                mayValidate, vpn, unmetered, everUserSelected, acceptUnvalidated, yieldToBadWiFi);
    }
    }


    /**
    /**
@@ -157,26 +189,39 @@ public class FullScore {
     * @param config the NetworkAgentConfig of the network
     * @param config the NetworkAgentConfig of the network
     * @return a score with the policies from the arguments reset
     * @return a score with the policies from the arguments reset
     */
     */
    // TODO : this shouldn't manage bad wifi avoidance – instead this should be done by the
    // telephony factory, so that it depends on the carrier. For now this is handled by
    // connectivity for backward compatibility.
    public FullScore mixInScore(@NonNull final NetworkCapabilities caps,
    public FullScore mixInScore(@NonNull final NetworkCapabilities caps,
            @NonNull final NetworkAgentConfig config) {
            @NonNull final NetworkAgentConfig config, final boolean avoidBadWiFi) {
        return withPolicies(mLegacyInt, mKeepConnectedReason,
        return withPolicies(mLegacyInt, mPolicies, mKeepConnectedReason,
                caps.hasCapability(NET_CAPABILITY_VALIDATED),
                caps.hasCapability(NET_CAPABILITY_VALIDATED),
                caps.hasTransport(TRANSPORT_VPN),
                caps.hasTransport(TRANSPORT_VPN),
                caps.hasCapability(NET_CAPABILITY_NOT_METERED),
                config.explicitlySelected,
                config.explicitlySelected,
                config.acceptUnvalidated);
                config.acceptUnvalidated,
                avoidBadWiFi);
    }
    }


    // TODO : this shouldn't manage bad wifi avoidance – instead this should be done by the
    // telephony factory, so that it depends on the carrier. For now this is handled by
    // connectivity for backward compatibility.
    private static FullScore withPolicies(@NonNull final int legacyInt,
    private static FullScore withPolicies(@NonNull final int legacyInt,
            final long externalPolicies,
            @KeepConnectedReason final int keepConnectedReason,
            @KeepConnectedReason final int keepConnectedReason,
            final boolean isValidated,
            final boolean isValidated,
            final boolean isVpn,
            final boolean isVpn,
            final boolean isUnmetered,
            final boolean everUserSelected,
            final boolean everUserSelected,
            final boolean acceptUnvalidated) {
            final boolean acceptUnvalidated,
        return new FullScore(legacyInt,
            final boolean yieldToBadWiFi) {
                (isValidated         ? 1L << POLICY_IS_VALIDATED : 0)
        return new FullScore(legacyInt, (externalPolicies & EXTERNAL_POLICIES_MASK)
                | (isValidated       ? 1L << POLICY_IS_VALIDATED : 0)
                | (isVpn             ? 1L << POLICY_IS_VPN : 0)
                | (isVpn             ? 1L << POLICY_IS_VPN : 0)
                | (isUnmetered       ? 1L << POLICY_IS_UNMETERED : 0)
                | (everUserSelected  ? 1L << POLICY_EVER_USER_SELECTED : 0)
                | (everUserSelected  ? 1L << POLICY_EVER_USER_SELECTED : 0)
                | (acceptUnvalidated ? 1L << POLICY_ACCEPT_UNVALIDATED : 0),
                | (acceptUnvalidated ? 1L << POLICY_ACCEPT_UNVALIDATED : 0)
                | (yieldToBadWiFi    ? 1L << POLICY_YIELD_TO_BAD_WIFI : 0),
                keepConnectedReason);
                keepConnectedReason);
    }
    }


+13 −15
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.connectivity;
package com.android.server.connectivity;


import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport;
import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.transportNamesOf;
import static android.net.NetworkCapabilities.transportNamesOf;


import android.annotation.NonNull;
import android.annotation.NonNull;
@@ -362,9 +363,9 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
        linkProperties = lp;
        linkProperties = lp;
        networkCapabilities = nc;
        networkCapabilities = nc;
        networkAgentConfig = config;
        networkAgentConfig = config;
        setScore(score); // uses members networkCapabilities and networkAgentConfig
        clatd = new Nat464Xlat(this, netd, dnsResolver, deps);
        mConnService = connService;
        mConnService = connService;
        setScore(score); // uses members connService, networkCapabilities and networkAgentConfig
        clatd = new Nat464Xlat(this, netd, dnsResolver, deps);
        mContext = context;
        mContext = context;
        mHandler = handler;
        mHandler = handler;
        this.factorySerialNumber = factorySerialNumber;
        this.factorySerialNumber = factorySerialNumber;
@@ -706,7 +707,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
            @NonNull final NetworkCapabilities nc) {
            @NonNull final NetworkCapabilities nc) {
        final NetworkCapabilities oldNc = networkCapabilities;
        final NetworkCapabilities oldNc = networkCapabilities;
        networkCapabilities = nc;
        networkCapabilities = nc;
        mScore = mScore.mixInScore(networkCapabilities, networkAgentConfig);
        mScore = mScore.mixInScore(networkCapabilities, networkAgentConfig, yieldToBadWiFi());
        final NetworkMonitorManager nm = mNetworkMonitor;
        final NetworkMonitorManager nm = mNetworkMonitor;
        if (nm != null) {
        if (nm != null) {
            nm.notifyNetworkCapabilitiesChanged(nc);
            nm.notifyNetworkCapabilitiesChanged(nc);
@@ -714,6 +715,11 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
        return oldNc;
        return oldNc;
    }
    }


    private boolean yieldToBadWiFi() {
        // Only cellular networks yield to bad wifi
        return networkCapabilities.hasTransport(TRANSPORT_CELLULAR) && !mConnService.avoidBadWifi();
    }

    public ConnectivityService connService() {
    public ConnectivityService connService() {
        return mConnService;
        return mConnService;
    }
    }
@@ -884,15 +890,6 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
        return isVPN();
        return isVPN();
    }
    }


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

    public FullScore getScore() {
    public FullScore getScore() {
        return mScore;
        return mScore;
    }
    }
@@ -913,7 +910,8 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
     * Mix-in the ConnectivityService-managed bits in the score.
     * Mix-in the ConnectivityService-managed bits in the score.
     */
     */
    public void setScore(final NetworkScore score) {
    public void setScore(final NetworkScore score) {
        mScore = FullScore.fromNetworkScore(score, networkCapabilities, networkAgentConfig);
        mScore = FullScore.fromNetworkScore(score, networkCapabilities, networkAgentConfig,
                yieldToBadWiFi());
    }
    }


    /**
    /**
@@ -922,7 +920,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
     * Call this after updating the network agent config.
     * Call this after updating the network agent config.
     */
     */
    public void updateScoreForNetworkAgentConfigUpdate() {
    public void updateScoreForNetworkAgentConfigUpdate() {
        mScore = mScore.mixInScore(networkCapabilities, networkAgentConfig);
        mScore = mScore.mixInScore(networkCapabilities, networkAgentConfig, yieldToBadWiFi());
    }
    }


    /**
    /**
@@ -1085,7 +1083,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
        return "NetworkAgentInfo{"
        return "NetworkAgentInfo{"
                + "network{" + network + "}  handle{" + network.getNetworkHandle() + "}  ni{"
                + "network{" + network + "}  handle{" + network.getNetworkHandle() + "}  ni{"
                + networkInfo.toShortString() + "} "
                + networkInfo.toShortString() + "} "
                + "  Score{" + getCurrentScore() + "} "
                + mScore + " "
                + (isNascent() ? " nascent" : (isLingering() ? " lingering" : ""))
                + (isNascent() ? " nascent" : (isLingering() ? " lingering" : ""))
                + (everValidated ? " everValidated" : "")
                + (everValidated ? " everValidated" : "")
                + (lastValidated ? " lastValidated" : "")
                + (lastValidated ? " lastValidated" : "")
+1 −1
Original line number Original line Diff line number Diff line
@@ -56,7 +56,7 @@ class FullScoreTest {
            if (vpn) addTransportType(NetworkCapabilities.TRANSPORT_VPN)
            if (vpn) addTransportType(NetworkCapabilities.TRANSPORT_VPN)
            if (validated) addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
            if (validated) addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
        }.build()
        }.build()
        return mixInScore(nc, nac)
        return mixInScore(nc, nac, false /* avoidBadWifi */)
    }
    }


    @Test
    @Test