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

Commit 95b65383 authored by Chalard Jean's avatar Chalard Jean
Browse files

[NS06] Implement the don't-reap mechanism

This exposes a mechanism for network providers to tell
the network stack that a given network must be kept up
for some specific reason. This is meant to be easier
for them than to have to file a request, in particular
because there is no guaranteed way to make sure the
request will be best matched by any given network.

Test: new test for this
Bug: 167544279
Change-Id: I238a3ee5ee9262477a23b897e4141769dd1505d1
parent 89bd2e2a
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -336,14 +336,18 @@ package android.net {

  public final class NetworkScore implements android.os.Parcelable {
    method public int describeContents();
    method public int getKeepConnectedReason();
    method public int getLegacyInt();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkScore> CREATOR;
    field public static final int KEEP_CONNECTED_FOR_HANDOVER = 1; // 0x1
    field public static final int KEEP_CONNECTED_NONE = 0; // 0x0
  }

  public static final class NetworkScore.Builder {
    ctor public NetworkScore.Builder();
    method @NonNull public android.net.NetworkScore build();
    method @NonNull public android.net.NetworkScore.Builder setKeepConnectedReason(int);
    method @NonNull public android.net.NetworkScore.Builder setLegacyInt(int);
  }

+42 −2
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.net;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.os.Parcel;
@@ -23,6 +24,9 @@ import android.os.Parcelable;

import com.android.internal.annotations.VisibleForTesting;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * Object representing the quality of a network as perceived by the user.
 *
@@ -36,6 +40,17 @@ public final class NetworkScore implements Parcelable {
    // a migration.
    private final int mLegacyInt;

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(value = {
            KEEP_CONNECTED_NONE,
            KEEP_CONNECTED_FOR_HANDOVER
    })
    public @interface KeepConnectedReason { }

    public static final int KEEP_CONNECTED_NONE = 0;
    public static final int KEEP_CONNECTED_FOR_HANDOVER = 1;

    // Agent-managed policies
    // TODO : add them here, starting from 1
    /** @hide */
@@ -46,21 +61,33 @@ public final class NetworkScore implements Parcelable {
    // Bitmask of all the policies applied to this score.
    private final long mPolicies;

    private final int mKeepConnectedReason;

    /** @hide */
    NetworkScore(final int legacyInt, final long policies) {
    NetworkScore(final int legacyInt, final long policies,
            @KeepConnectedReason final int keepConnectedReason) {
        mLegacyInt = legacyInt;
        mPolicies = policies;
        mKeepConnectedReason = keepConnectedReason;
    }

    private NetworkScore(@NonNull final Parcel in) {
        mLegacyInt = in.readInt();
        mPolicies = in.readLong();
        mKeepConnectedReason = in.readInt();
    }

    public int getLegacyInt() {
        return mLegacyInt;
    }

    /**
     * Returns the keep-connected reason, or KEEP_CONNECTED_NONE.
     */
    public int getKeepConnectedReason() {
        return mKeepConnectedReason;
    }

    /**
     * @return whether this score has a particular policy.
     *
@@ -80,6 +107,7 @@ public final class NetworkScore implements Parcelable {
    public void writeToParcel(@NonNull final Parcel dest, final int flags) {
        dest.writeInt(mLegacyInt);
        dest.writeLong(mPolicies);
        dest.writeInt(mKeepConnectedReason);
    }

    @Override
@@ -108,6 +136,7 @@ public final class NetworkScore implements Parcelable {
        private static final long POLICY_NONE = 0L;
        private static final int INVALID_LEGACY_INT = Integer.MIN_VALUE;
        private int mLegacyInt = INVALID_LEGACY_INT;
        private int mKeepConnectedReason = KEEP_CONNECTED_NONE;

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

        /**
         * Set the keep-connected reason.
         *
         * This can be reset by calling it again with {@link KEEP_CONNECTED_NONE}.
         */
        @NonNull
        public Builder setKeepConnectedReason(@KeepConnectedReason final int reason) {
            mKeepConnectedReason = reason;
            return this;
        }

        /**
         * Builds this NetworkScore.
         * @return The built NetworkScore object.
         */
        @NonNull
        public NetworkScore build() {
            return new NetworkScore(mLegacyInt, POLICY_NONE);
            return new NetworkScore(mLegacyInt, POLICY_NONE, mKeepConnectedReason);
        }
    }
}
+8 −3
Original line number Diff line number Diff line
@@ -3846,6 +3846,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
    //   then it should be lingered.
    private boolean unneeded(NetworkAgentInfo nai, UnneededFor reason) {
        ensureRunningOnConnectivityServiceThread();

        if (!nai.everConnected || nai.isVPN() || nai.isInactive()
                || nai.getScore().getKeepConnectedReason() != NetworkScore.KEEP_CONNECTED_NONE) {
            return false;
        }

        final int numRequests;
        switch (reason) {
            case TEARDOWN:
@@ -3859,9 +3865,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
                return true;
        }

        if (!nai.everConnected || nai.isVPN() || nai.isInactive() || numRequests > 0) {
            return false;
        }
        if (numRequests > 0) return false;

        for (NetworkRequestInfo nri : mNetworkRequests.values()) {
            if (reason == UnneededFor.LINGER
                    && !nri.isMultilayerRequest()
+26 −8
Original line number Diff line number Diff line
@@ -19,12 +19,14 @@ package com.android.server.connectivity;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkScore.KEEP_CONNECTED_NONE;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.net.NetworkAgentConfig;
import android.net.NetworkCapabilities;
import android.net.NetworkScore;
import android.net.NetworkScore.KeepConnectedReason;

import com.android.internal.annotations.VisibleForTesting;

@@ -95,9 +97,13 @@ public class FullScore {
    // Bitmask of all the policies applied to this score.
    private final long mPolicies;

    FullScore(final int legacyInt, final long policies) {
    private final int mKeepConnectedReason;

    FullScore(final int legacyInt, final long policies,
            @KeepConnectedReason final int keepConnectedReason) {
        mLegacyInt = legacyInt;
        mPolicies = policies;
        mKeepConnectedReason = keepConnectedReason;
    }

    /**
@@ -110,14 +116,15 @@ public class FullScore {
     */
    public static FullScore fromNetworkScore(@NonNull final NetworkScore score,
            @NonNull final NetworkCapabilities caps, @NonNull final NetworkAgentConfig config) {
        return withPolicies(score.getLegacyInt(), caps.hasCapability(NET_CAPABILITY_VALIDATED),
        return withPolicies(score.getLegacyInt(), score.getKeepConnectedReason(),
                caps.hasCapability(NET_CAPABILITY_VALIDATED),
                caps.hasTransport(TRANSPORT_VPN),
                config.explicitlySelected,
                config.acceptUnvalidated);
    }

    /**
     * Given a score supplied by the NetworkAgent, produce a prospective score for an offer.
     * Given a score supplied by a NetworkProvider, produce a prospective score for an offer.
     *
     * NetworkOffers have score filters that are compared to the scores of actual networks
     * to see if they could possibly beat the current satisfier. Some things the agent can't
@@ -139,8 +146,8 @@ public class FullScore {
        final boolean everUserSelected = false;
        // Don't assume the user will accept unvalidated connectivity.
        final boolean acceptUnvalidated = false;
        return withPolicies(score.getLegacyInt(), mayValidate, vpn, everUserSelected,
                acceptUnvalidated);
        return withPolicies(score.getLegacyInt(), KEEP_CONNECTED_NONE,
                mayValidate, vpn, everUserSelected, acceptUnvalidated);
    }

    /**
@@ -152,13 +159,15 @@ public class FullScore {
     */
    public FullScore mixInScore(@NonNull final NetworkCapabilities caps,
            @NonNull final NetworkAgentConfig config) {
        return withPolicies(mLegacyInt, caps.hasCapability(NET_CAPABILITY_VALIDATED),
        return withPolicies(mLegacyInt, mKeepConnectedReason,
                caps.hasCapability(NET_CAPABILITY_VALIDATED),
                caps.hasTransport(TRANSPORT_VPN),
                config.explicitlySelected,
                config.acceptUnvalidated);
    }

    private static FullScore withPolicies(@NonNull final int legacyInt,
            @KeepConnectedReason final int keepConnectedReason,
            final boolean isValidated,
            final boolean isVpn,
            final boolean everUserSelected,
@@ -167,7 +176,8 @@ public class FullScore {
                (isValidated         ? 1L << POLICY_IS_VALIDATED : 0)
                | (isVpn             ? 1L << POLICY_IS_VPN : 0)
                | (everUserSelected  ? 1L << POLICY_EVER_USER_SELECTED : 0)
                | (acceptUnvalidated ? 1L << POLICY_ACCEPT_UNVALIDATED : 0));
                | (acceptUnvalidated ? 1L << POLICY_ACCEPT_UNVALIDATED : 0),
                keepConnectedReason);
    }

    /**
@@ -219,13 +229,21 @@ public class FullScore {
        return 0 != (mPolicies & (1L << policy));
    }

    /**
     * Returns the keep-connected reason, or KEEP_CONNECTED_NONE.
     */
    public int getKeepConnectedReason() {
        return mKeepConnectedReason;
    }

    // Example output :
    // Score(50 ; Policies : EVER_USER_SELECTED&IS_VALIDATED)
    @Override
    public String toString() {
        final StringJoiner sj = new StringJoiner(
                "&", // delimiter
                "Score(" + mLegacyInt + " ; Policies : ", // prefix
                "Score(" + mLegacyInt + " ; KeepConnected : " + mKeepConnectedReason
                        + " ; Policies : ", // prefix
                ")"); // suffix
        for (int i = NetworkScore.MIN_AGENT_MANAGED_POLICY;
                i <= NetworkScore.MAX_AGENT_MANAGED_POLICY; ++i) {
+6 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import android.net.NetworkAgent;
import android.net.NetworkAgentConfig;
import android.net.NetworkCapabilities;
import android.net.NetworkProvider;
import android.net.NetworkScore;
import android.net.NetworkSpecifier;
import android.net.QosFilter;
import android.net.SocketKeepalive;
@@ -199,6 +200,11 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork {
        }
    }

    public void setScore(@NonNull final NetworkScore score) {
        mScore = score.getLegacyInt();
        mNetworkAgent.sendNetworkScore(score);
    }

    public void adjustScore(int change) {
        mScore += change;
        mNetworkAgent.sendNetworkScore(mScore);
Loading