Allow network providers to set the linger duration.
Test: atest CtsNetTestCases:NetworkAgentTest#testSetLingerDuration CTS-Coverage-Bug: 184796264 Bug: 184227264 Merged-In: I3c2563d4ae4e3715d0c6270344ba8f7ef067872f Merged-In: I7f420faa40863385114705d6971cf00887d03318 Change-Id: I7f420faa40863385114705d6971cf00887d03318 (cherry-picked from ag/14100410)
This commit is contained in:
@@ -239,6 +239,7 @@ package android.net {
|
|||||||
method public final void sendQosSessionLost(int, int, int);
|
method public final void sendQosSessionLost(int, int, int);
|
||||||
method public final void sendSocketKeepaliveEvent(int, int);
|
method public final void sendSocketKeepaliveEvent(int, int);
|
||||||
method @Deprecated public void setLegacySubtype(int, @NonNull String);
|
method @Deprecated public void setLegacySubtype(int, @NonNull String);
|
||||||
|
method public void setLingerDuration(@NonNull java.time.Duration);
|
||||||
method public void setTeardownDelayMillis(@IntRange(from=0, to=0x1388) int);
|
method public void setTeardownDelayMillis(@IntRange(from=0, to=0x1388) int);
|
||||||
method public final void setUnderlyingNetworks(@Nullable java.util.List<android.net.Network>);
|
method public final void setUnderlyingNetworks(@Nullable java.util.List<android.net.Network>);
|
||||||
method public void unregister();
|
method public void unregister();
|
||||||
|
|||||||
@@ -42,4 +42,5 @@ oneway interface INetworkAgentRegistry {
|
|||||||
void sendQosSessionLost(int qosCallbackId, in QosSession session);
|
void sendQosSessionLost(int qosCallbackId, in QosSession session);
|
||||||
void sendQosCallbackError(int qosCallbackId, int exceptionType);
|
void sendQosCallbackError(int qosCallbackId, int exceptionType);
|
||||||
void sendTeardownDelayMs(int teardownDelayMs);
|
void sendTeardownDelayMs(int teardownDelayMs);
|
||||||
|
void sendLingerDuration(int durationMs);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import android.annotation.NonNull;
|
|||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.annotation.SystemApi;
|
import android.annotation.SystemApi;
|
||||||
|
import android.annotation.TestApi;
|
||||||
import android.compat.annotation.UnsupportedAppUsage;
|
import android.compat.annotation.UnsupportedAppUsage;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
@@ -106,6 +107,9 @@ public abstract class NetworkAgent {
|
|||||||
private final String LOG_TAG;
|
private final String LOG_TAG;
|
||||||
private static final boolean DBG = true;
|
private static final boolean DBG = true;
|
||||||
private static final boolean VDBG = false;
|
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 final ArrayList<RegistryAction> mPreConnectedQueue = new ArrayList<>();
|
||||||
private volatile long mLastBwRefreshTime = 0;
|
private volatile long mLastBwRefreshTime = 0;
|
||||||
private static final long BW_REFRESH_MIN_WIN_MS = 500;
|
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;
|
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) {
|
private static NetworkInfo getLegacyNetworkInfo(final NetworkAgentConfig config) {
|
||||||
final NetworkInfo ni = new NetworkInfo(config.legacyType, config.legacySubType,
|
final NetworkInfo ni = new NetworkInfo(config.legacyType, config.legacySubType,
|
||||||
config.legacyTypeName, config.legacySubTypeName);
|
config.legacyTypeName, config.legacySubTypeName);
|
||||||
@@ -1287,6 +1300,22 @@ public abstract class NetworkAgent {
|
|||||||
queueOrSendMessage(ra -> ra.sendQosCallbackError(qosCallbackId, exceptionType));
|
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 */
|
/** @hide */
|
||||||
protected void log(final String s) {
|
protected void log(final String s) {
|
||||||
|
|||||||
@@ -1400,8 +1400,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
new NetworkInfo(TYPE_NONE, 0, "", ""),
|
new NetworkInfo(TYPE_NONE, 0, "", ""),
|
||||||
new LinkProperties(), new NetworkCapabilities(),
|
new LinkProperties(), new NetworkCapabilities(),
|
||||||
new NetworkScore.Builder().setLegacyInt(0).build(), mContext, null,
|
new NetworkScore.Builder().setLegacyInt(0).build(), mContext, null,
|
||||||
new NetworkAgentConfig(), this, null, null, 0, INVALID_UID, mQosCallbackTracker,
|
new NetworkAgentConfig(), this, null, null, 0, INVALID_UID,
|
||||||
mDeps);
|
mLingerDelayMs, mQosCallbackTracker, mDeps);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static NetworkCapabilities createDefaultNetworkCapabilitiesForUid(int uid) {
|
private static NetworkCapabilities createDefaultNetworkCapabilitiesForUid(int uid) {
|
||||||
@@ -3234,6 +3234,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
} else {
|
} else {
|
||||||
logwtf(nai.toShortString() + " set invalid teardown delay " + msg.arg1);
|
logwtf(nai.toShortString() + " set invalid teardown delay " + msg.arg1);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NetworkAgent.EVENT_LINGER_DURATION_CHANGED: {
|
||||||
|
nai.setLingerDuration((int) arg.second);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6597,7 +6602,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
final NetworkAgentInfo nai = new NetworkAgentInfo(na,
|
final NetworkAgentInfo nai = new NetworkAgentInfo(na,
|
||||||
new Network(mNetIdManager.reserveNetId()), new NetworkInfo(networkInfo), lp, nc,
|
new Network(mNetIdManager.reserveNetId()), new NetworkInfo(networkInfo), lp, nc,
|
||||||
currentScore, mContext, mTrackerHandler, new NetworkAgentConfig(networkAgentConfig),
|
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.
|
// Make sure the LinkProperties and NetworkCapabilities reflect what the agent info says.
|
||||||
processCapabilitiesFromAgent(nai, nc);
|
processCapabilitiesFromAgent(nai, nc);
|
||||||
@@ -7841,7 +7847,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
log(" accepting network in place of " + previousSatisfier.toShortString());
|
log(" accepting network in place of " + previousSatisfier.toShortString());
|
||||||
}
|
}
|
||||||
previousSatisfier.removeRequest(previousRequest.requestId);
|
previousSatisfier.removeRequest(previousRequest.requestId);
|
||||||
previousSatisfier.lingerRequest(previousRequest.requestId, now, mLingerDelayMs);
|
previousSatisfier.lingerRequest(previousRequest.requestId, now);
|
||||||
} else {
|
} else {
|
||||||
if (VDBG || DDBG) log(" accepting network in place of null");
|
if (VDBG || DDBG) log(" accepting network in place of null");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ import com.android.internal.util.WakeupMessage;
|
|||||||
import com.android.server.ConnectivityService;
|
import com.android.server.ConnectivityService;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
@@ -281,6 +282,9 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo>, NetworkRa
|
|||||||
*/
|
*/
|
||||||
public static final int ARG_AGENT_SUCCESS = 1;
|
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
|
// 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
|
// 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
|
// 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,
|
@NonNull NetworkScore score, Context context,
|
||||||
Handler handler, NetworkAgentConfig config, ConnectivityService connService, INetd netd,
|
Handler handler, NetworkAgentConfig config, ConnectivityService connService, INetd netd,
|
||||||
IDnsResolver dnsResolver, int factorySerialNumber, int creatorUid,
|
IDnsResolver dnsResolver, int factorySerialNumber, int creatorUid,
|
||||||
QosCallbackTracker qosCallbackTracker, ConnectivityService.Dependencies deps) {
|
int lingerDurationMs, QosCallbackTracker qosCallbackTracker,
|
||||||
|
ConnectivityService.Dependencies deps) {
|
||||||
Objects.requireNonNull(net);
|
Objects.requireNonNull(net);
|
||||||
Objects.requireNonNull(info);
|
Objects.requireNonNull(info);
|
||||||
Objects.requireNonNull(lp);
|
Objects.requireNonNull(lp);
|
||||||
@@ -370,6 +375,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo>, NetworkRa
|
|||||||
mHandler = handler;
|
mHandler = handler;
|
||||||
this.factorySerialNumber = factorySerialNumber;
|
this.factorySerialNumber = factorySerialNumber;
|
||||||
this.creatorUid = creatorUid;
|
this.creatorUid = creatorUid;
|
||||||
|
mLingerDurationMs = lingerDurationMs;
|
||||||
mQosCallbackTracker = qosCallbackTracker;
|
mQosCallbackTracker = qosCallbackTracker;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -685,6 +691,12 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo>, NetworkRa
|
|||||||
mHandler.obtainMessage(NetworkAgent.EVENT_TEARDOWN_DELAY_CHANGED,
|
mHandler.obtainMessage(NetworkAgent.EVENT_TEARDOWN_DELAY_CHANGED,
|
||||||
teardownDelayMs, 0, new Pair<>(NetworkAgentInfo.this, null)).sendToTarget();
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -974,13 +986,14 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo>, NetworkRa
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the specified requestId to linger on this network for the specified time. Called by
|
* 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.
|
* when a network is newly created.
|
||||||
*
|
*
|
||||||
* @param requestId The requestId of the request that no longer need to be served by this
|
* @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
|
* 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) {
|
public void lingerRequest(int requestId, long now, long duration) {
|
||||||
if (mInactivityTimerForRequest.get(requestId) != null) {
|
if (mInactivityTimerForRequest.get(requestId) != null) {
|
||||||
// Cannot happen. Once a request is lingering on a particular network, we cannot
|
// Cannot happen. Once a request is lingering on a particular network, we cannot
|
||||||
@@ -995,6 +1008,19 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo>, NetworkRa
|
|||||||
mInactivityTimerForRequest.put(requestId, timer);
|
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.
|
* 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.
|
* Returns true if the given requestId was lingering on this network, false otherwise.
|
||||||
@@ -1032,6 +1058,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo>, NetworkRa
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (newExpiry > 0) {
|
if (newExpiry > 0) {
|
||||||
|
// If the newExpiry timestamp is in the past, the wakeup message will fire immediately.
|
||||||
mInactivityMessage = new WakeupMessage(
|
mInactivityMessage = new WakeupMessage(
|
||||||
mContext, mHandler,
|
mContext, mHandler,
|
||||||
"NETWORK_LINGER_COMPLETE." + network.getNetId() /* cmdName */,
|
"NETWORK_LINGER_COMPLETE." + network.getNetId() /* cmdName */,
|
||||||
@@ -1061,8 +1088,33 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo>, NetworkRa
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return whether the network is just connected and about to be torn down because of not
|
* Set the linger duration for this NAI.
|
||||||
* satisfying any request.
|
* @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() {
|
public boolean isNascent() {
|
||||||
return mInactive && mInactivityTimers.size() == 1
|
return mInactive && mInactivityTimers.size() == 1
|
||||||
|
|||||||
@@ -9832,7 +9832,8 @@ public class ConnectivityServiceTest {
|
|||||||
return new NetworkAgentInfo(null, new Network(NET_ID), networkInfo, new LinkProperties(),
|
return new NetworkAgentInfo(null, new Network(NET_ID), networkInfo, new LinkProperties(),
|
||||||
nc, new NetworkScore.Builder().setLegacyInt(0).build(),
|
nc, new NetworkScore.Builder().setLegacyInt(0).build(),
|
||||||
mServiceContext, null, new NetworkAgentConfig(), mService, null, null, 0,
|
mServiceContext, null, new NetworkAgentConfig(), mService, null, null, 0,
|
||||||
INVALID_UID, mQosCallbackTracker, new ConnectivityService.Dependencies());
|
INVALID_UID, TEST_LINGER_DELAY_MS, mQosCallbackTracker,
|
||||||
|
new ConnectivityService.Dependencies());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -71,6 +71,8 @@ public class LingerMonitorTest {
|
|||||||
static final int LOW_DAILY_LIMIT = 2;
|
static final int LOW_DAILY_LIMIT = 2;
|
||||||
static final int HIGH_DAILY_LIMIT = 1000;
|
static final int HIGH_DAILY_LIMIT = 1000;
|
||||||
|
|
||||||
|
private static final int TEST_LINGER_DELAY_MS = 400;
|
||||||
|
|
||||||
LingerMonitor mMonitor;
|
LingerMonitor mMonitor;
|
||||||
|
|
||||||
@Mock ConnectivityService mConnService;
|
@Mock ConnectivityService mConnService;
|
||||||
@@ -366,7 +368,7 @@ public class LingerMonitorTest {
|
|||||||
NetworkAgentInfo nai = new NetworkAgentInfo(null, new Network(netId), info,
|
NetworkAgentInfo nai = new NetworkAgentInfo(null, new Network(netId), info,
|
||||||
new LinkProperties(), caps, new NetworkScore.Builder().setLegacyInt(50).build(),
|
new LinkProperties(), caps, new NetworkScore.Builder().setLegacyInt(50).build(),
|
||||||
mCtx, null, new NetworkAgentConfig.Builder().build(), mConnService, mNetd,
|
mCtx, null, new NetworkAgentConfig.Builder().build(), mConnService, mNetd,
|
||||||
mDnsResolver, NetworkProvider.ID_NONE, Binder.getCallingUid(),
|
mDnsResolver, NetworkProvider.ID_NONE, Binder.getCallingUid(), TEST_LINGER_DELAY_MS,
|
||||||
mQosCallbackTracker, new ConnectivityService.Dependencies());
|
mQosCallbackTracker, new ConnectivityService.Dependencies());
|
||||||
nai.everValidated = true;
|
nai.everValidated = true;
|
||||||
return nai;
|
return nai;
|
||||||
|
|||||||
Reference in New Issue
Block a user