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

Commit 7ee82891 authored by Chalard Jean's avatar Chalard Jean Committed by junyulai
Browse files

Allow network providers to set the linger duration.

Test: atest CtsNetTestCases:NetworkAgentTest#testSetLingerDuration
Ignore-AOSP-First: prevent merge conflict
CTS-Coverage-Bug: 184796264
Bug: 184227264
Change-Id: I7f420faa40863385114705d6971cf00887d03318
parent f3779061
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -239,6 +239,7 @@ package android.net {
    method public final void sendQosSessionLost(int, int, int);
    method public final void sendSocketKeepaliveEvent(int, int);
    method @Deprecated public void setLegacySubtype(int, @NonNull String);
    method public void setLingerDuration(@NonNull java.time.Duration);
    method public void setTeardownDelayMs(@IntRange(from=0, to=0x1388) int);
    method public final void setUnderlyingNetworks(@Nullable java.util.List<android.net.Network>);
    method public void unregister();
+1 −0
Original line number Diff line number Diff line
@@ -42,4 +42,5 @@ oneway interface INetworkAgentRegistry {
    void sendQosSessionLost(int qosCallbackId, in QosSession session);
    void sendQosCallbackError(int qosCallbackId, int exceptionType);
    void sendTeardownDelayMs(int teardownDelayMs);
    void sendLingerDuration(int durationMs);
}
+29 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Build;
@@ -106,6 +107,9 @@ public abstract class NetworkAgent {
    private final String LOG_TAG;
    private static final boolean DBG = true;
    private static final boolean VDBG = false;
    /** @hide */
    @TestApi
    public static final int MIN_LINGER_TIMER_MS = 2000;
    private final ArrayList<RegistryAction> mPreConnectedQueue = new ArrayList<>();
    private volatile long mLastBwRefreshTime = 0;
    private static final long BW_REFRESH_MIN_WIN_MS = 500;
@@ -391,6 +395,15 @@ public abstract class NetworkAgent {
     */
    public static final int CMD_NETWORK_DESTROYED = BASE + 23;

    /**
     * Sent by the NetworkAgent to ConnectivityService to set the linger duration for this network
     * agent.
     * arg1 = the linger duration, represents by {@link Duration}.
     *
     * @hide
     */
    public static final int EVENT_LINGER_DURATION_CHANGED = BASE + 24;

    private static NetworkInfo getLegacyNetworkInfo(final NetworkAgentConfig config) {
        final NetworkInfo ni = new NetworkInfo(config.legacyType, config.legacySubType,
                config.legacyTypeName, config.legacySubTypeName);
@@ -1287,6 +1300,22 @@ public abstract class NetworkAgent {
        queueOrSendMessage(ra -> ra.sendQosCallbackError(qosCallbackId, exceptionType));
    }

    /**
     * Set the linger duration for this network agent.
     * @param duration the delay between the moment the network becomes unneeded and the
     *                 moment the network is disconnected or moved into the background.
     *                 Note that If this duration has greater than millisecond precision, then
     *                 the internal implementation will drop any excess precision.
     */
    public void setLingerDuration(@NonNull final Duration duration) {
        Objects.requireNonNull(duration);
        final long durationMs = duration.toMillis();
        if (durationMs < MIN_LINGER_TIMER_MS || durationMs > Integer.MAX_VALUE) {
            throw new IllegalArgumentException("Duration must be within ["
                    + MIN_LINGER_TIMER_MS + "," + Integer.MAX_VALUE + "]ms");
        }
        queueOrSendMessage(ra -> ra.sendLingerDuration((int) durationMs));
    }

    /** @hide */
    protected void log(final String s) {
+10 −4
Original line number Diff line number Diff line
@@ -1353,8 +1353,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
                new NetworkInfo(TYPE_NONE, 0, "", ""),
                new LinkProperties(), new NetworkCapabilities(),
                new NetworkScore.Builder().setLegacyInt(0).build(), mContext, null,
                new NetworkAgentConfig(), this, null, null, 0, INVALID_UID, mQosCallbackTracker,
                mDeps);
                new NetworkAgentConfig(), this, null, null, 0, INVALID_UID,
                mLingerDelayMs, mQosCallbackTracker, mDeps);
    }

    private static NetworkCapabilities createDefaultNetworkCapabilitiesForUid(int uid) {
@@ -3167,6 +3167,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
                    } else {
                        logwtf(nai.toShortString() + " set invalid teardown delay " + msg.arg1);
                    }
                    break;
                }
                case NetworkAgent.EVENT_LINGER_DURATION_CHANGED: {
                    nai.setLingerDuration((int) arg.second);
                    break;
                }
            }
        }
@@ -6516,7 +6521,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
        final NetworkAgentInfo nai = new NetworkAgentInfo(na,
                new Network(mNetIdManager.reserveNetId()), new NetworkInfo(networkInfo), lp, nc,
                currentScore, mContext, mTrackerHandler, new NetworkAgentConfig(networkAgentConfig),
                this, mNetd, mDnsResolver, providerId, uid, mQosCallbackTracker, mDeps);
                this, mNetd, mDnsResolver, providerId, uid, mLingerDelayMs,
                mQosCallbackTracker, mDeps);

        // Make sure the LinkProperties and NetworkCapabilities reflect what the agent info says.
        processCapabilitiesFromAgent(nai, nc);
@@ -7759,7 +7765,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
                    log("   accepting network in place of " + previousSatisfier.toShortString());
                }
                previousSatisfier.removeRequest(previousRequest.requestId);
                previousSatisfier.lingerRequest(previousRequest.requestId, now, mLingerDelayMs);
                previousSatisfier.lingerRequest(previousRequest.requestId, now);
            } else {
                if (VDBG || DDBG) log("   accepting network in place of null");
            }
+57 −5
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ import com.android.internal.util.WakeupMessage;
import com.android.server.ConnectivityService;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.NoSuchElementException;
@@ -281,6 +282,9 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo>, NetworkRa
     */
    public static final int ARG_AGENT_SUCCESS = 1;

    // How long this network should linger for.
    private int mLingerDurationMs;

    // All inactivity timers for this network, sorted by expiry time. A 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. An inactivity timer is also added when a network connects
@@ -349,7 +353,8 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo>, NetworkRa
            @NonNull NetworkScore score, Context context,
            Handler handler, NetworkAgentConfig config, ConnectivityService connService, INetd netd,
            IDnsResolver dnsResolver, int factorySerialNumber, int creatorUid,
            QosCallbackTracker qosCallbackTracker, ConnectivityService.Dependencies deps) {
            int lingerDurationMs, QosCallbackTracker qosCallbackTracker,
            ConnectivityService.Dependencies deps) {
        Objects.requireNonNull(net);
        Objects.requireNonNull(info);
        Objects.requireNonNull(lp);
@@ -370,6 +375,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo>, NetworkRa
        mHandler = handler;
        this.factorySerialNumber = factorySerialNumber;
        this.creatorUid = creatorUid;
        mLingerDurationMs = lingerDurationMs;
        mQosCallbackTracker = qosCallbackTracker;
    }

@@ -685,6 +691,12 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo>, NetworkRa
            mHandler.obtainMessage(NetworkAgent.EVENT_TEARDOWN_DELAY_CHANGED,
                    teardownDelayMs, 0, new Pair<>(NetworkAgentInfo.this, null)).sendToTarget();
        }

        @Override
        public void sendLingerDuration(final int durationMs) {
            mHandler.obtainMessage(NetworkAgent.EVENT_LINGER_DURATION_CHANGED,
                    new Pair<>(NetworkAgentInfo.this, durationMs)).sendToTarget();
        }
    }

    /**
@@ -954,13 +966,14 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo>, NetworkRa

    /**
     * Sets the specified requestId to linger on this network for the specified time. Called by
     * ConnectivityService when the request is moved to another network with a higher score, or
     * ConnectivityService when any request is moved to another network with a higher score, or
     * when a network is newly created.
     *
     * @param requestId The requestId of the request that no longer need to be served by this
     *                  network. Or {@link NetworkRequest.REQUEST_ID_NONE} if this is the
     *                  {@code LingerTimer} for a newly created network.
     *                  {@code InactivityTimer} for a newly created network.
     */
    // TODO: Consider creating a dedicated function for nascent network, e.g. start/stopNascent.
    public void lingerRequest(int requestId, long now, long duration) {
        if (mInactivityTimerForRequest.get(requestId) != null) {
            // Cannot happen. Once a request is lingering on a particular network, we cannot
@@ -975,6 +988,19 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo>, NetworkRa
        mInactivityTimerForRequest.put(requestId, timer);
    }

    /**
     * Sets the specified requestId to linger on this network for the timeout set when
     * initializing or modified by {@link #setLingerDuration(int)}. Called by
     * ConnectivityService when any request is moved to another network with a higher score.
     *
     * @param requestId The requestId of the request that no longer need to be served by this
     *                  network.
     * @param now current system timestamp obtained by {@code SystemClock.elapsedRealtime}.
     */
    public void lingerRequest(int requestId, long now) {
        lingerRequest(requestId, now, mLingerDurationMs);
    }

    /**
     * Cancel lingering. Called by ConnectivityService when a request is added to this network.
     * Returns true if the given requestId was lingering on this network, false otherwise.
@@ -1012,6 +1038,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo>, NetworkRa
        }

        if (newExpiry > 0) {
            // If the newExpiry timestamp is in the past, the wakeup message will fire immediately.
            mInactivityMessage = new WakeupMessage(
                    mContext, mHandler,
                    "NETWORK_LINGER_COMPLETE." + network.getNetId() /* cmdName */,
@@ -1041,8 +1068,33 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo>, NetworkRa
    }

    /**
     * Return whether the network is just connected and about to be torn down because of not
     * satisfying any request.
     * Set the linger duration for this NAI.
     * @param durationMs The new linger duration, in milliseconds.
     */
    public void setLingerDuration(final int durationMs) {
        final long diff = durationMs - mLingerDurationMs;
        final ArrayList<InactivityTimer> newTimers = new ArrayList<>();
        for (final InactivityTimer timer : mInactivityTimers) {
            if (timer.requestId == NetworkRequest.REQUEST_ID_NONE) {
                // Don't touch nascent timer, re-add as is.
                newTimers.add(timer);
            } else {
                newTimers.add(new InactivityTimer(timer.requestId, timer.expiryMs + diff));
            }
        }
        mInactivityTimers.clear();
        mInactivityTimers.addAll(newTimers);
        updateInactivityTimer();
        mLingerDurationMs = durationMs;
    }

    /**
     * Return whether the network satisfies no request, but is still being kept up
     * because it has just connected less than
     * {@code ConnectivityService#DEFAULT_NASCENT_DELAY_MS}ms ago and is thus still considered
     * nascent. Note that nascent mechanism uses inactivity timer which isn't
     * associated with a request. Thus, use {@link NetworkRequest#REQUEST_ID_NONE} to identify it.
     *
     */
    public boolean isNascent() {
        return mInactive && mInactivityTimers.size() == 1
Loading