Immediately create native networks when NetworkAgents register.
Currently, native networks for non-VPN networks are created only when the NetworkAgent goes into the CONNECTED state. This is not ideal, because until the network is connected: - Nothing routes to the network, so no IP packets can be sent on it (except via packet sockets). - Many network configuration changes (e.g., routes and DNS servers) fail to apply because the network does not exist yet. These cause ENONET errors in the logs. Fix this starting in U by creating the native network as soon as the agent registers. This should not impact apps because NetworkCallbacks are not sent until networks are connected. Bug: 143158421 Test: new coverage in NetworkAgentTest Change-Id: I26bfa8630c085422175558645c47a6c64be96ae6
This commit is contained in:
@@ -2597,7 +2597,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
final ArrayList<NetworkStateSnapshot> result = new ArrayList<>();
|
final ArrayList<NetworkStateSnapshot> result = new ArrayList<>();
|
||||||
for (Network network : getAllNetworks()) {
|
for (Network network : getAllNetworks()) {
|
||||||
final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
|
final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
|
||||||
if (nai != null && nai.everConnected()) {
|
final boolean includeNetwork = (nai != null) && nai.isCreated();
|
||||||
|
if (includeNetwork) {
|
||||||
// TODO (b/73321673) : NetworkStateSnapshot contains a copy of the
|
// TODO (b/73321673) : NetworkStateSnapshot contains a copy of the
|
||||||
// NetworkCapabilities, which may contain UIDs of apps to which the
|
// NetworkCapabilities, which may contain UIDs of apps to which the
|
||||||
// network applies. Should the UIDs be cleared so as not to leak or
|
// network applies. Should the UIDs be cleared so as not to leak or
|
||||||
@@ -3799,9 +3800,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NetworkAgent.EVENT_UNREGISTER_AFTER_REPLACEMENT: {
|
case NetworkAgent.EVENT_UNREGISTER_AFTER_REPLACEMENT: {
|
||||||
if (!nai.isCreated()) {
|
if (!nai.everConnected()) {
|
||||||
Log.d(TAG, "unregisterAfterReplacement on uncreated " + nai.toShortString()
|
Log.d(TAG, "unregisterAfterReplacement on never-connected "
|
||||||
+ ", tearing down instead");
|
+ nai.toShortString() + ", tearing down instead");
|
||||||
teardownUnneededNetwork(nai);
|
teardownUnneededNetwork(nai);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -4386,6 +4387,25 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
protected static boolean shouldCreateNetworksImmediately() {
|
||||||
|
// Before U, physical networks are only created when the agent advances to CONNECTED.
|
||||||
|
// In U and above, all networks are immediately created when the agent is registered.
|
||||||
|
return SdkLevel.isAtLeastU();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean shouldCreateNativeNetwork(@NonNull NetworkAgentInfo nai,
|
||||||
|
@NonNull NetworkInfo.State state) {
|
||||||
|
if (nai.isCreated()) return false;
|
||||||
|
if (state == NetworkInfo.State.CONNECTED) return true;
|
||||||
|
if (state != NetworkInfo.State.CONNECTING) {
|
||||||
|
// TODO: throw if no WTFs are observed in the field.
|
||||||
|
Log.wtf(TAG, "Uncreated network in invalid state: " + state);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return nai.isVPN() || shouldCreateNetworksImmediately();
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean shouldDestroyNativeNetwork(@NonNull NetworkAgentInfo nai) {
|
private static boolean shouldDestroyNativeNetwork(@NonNull NetworkAgentInfo nai) {
|
||||||
return nai.isCreated() && !nai.isDestroyed();
|
return nai.isCreated() && !nai.isDestroyed();
|
||||||
}
|
}
|
||||||
@@ -7823,7 +7843,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
|
|
||||||
if (isDefaultNetwork(networkAgent)) {
|
if (isDefaultNetwork(networkAgent)) {
|
||||||
handleApplyDefaultProxy(newLp.getHttpProxy());
|
handleApplyDefaultProxy(newLp.getHttpProxy());
|
||||||
} else {
|
} else if (networkAgent.everConnected()) {
|
||||||
updateProxy(newLp, oldLp);
|
updateProxy(newLp, oldLp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7857,6 +7877,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
mKeepaliveTracker.handleCheckKeepalivesStillValid(networkAgent);
|
mKeepaliveTracker.handleCheckKeepalivesStillValid(networkAgent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void applyInitialLinkProperties(@NonNull NetworkAgentInfo nai) {
|
||||||
|
updateLinkProperties(nai, new LinkProperties(nai.linkProperties), null);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param naData captive portal data from NetworkAgent
|
* @param naData captive portal data from NetworkAgent
|
||||||
* @param apiData captive portal data from capport API
|
* @param apiData captive portal data from capport API
|
||||||
@@ -9608,21 +9632,32 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
+ oldInfo.getState() + " to " + state);
|
+ oldInfo.getState() + " to " + state);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!networkAgent.isCreated()
|
if (shouldCreateNativeNetwork(networkAgent, state)) {
|
||||||
&& (state == NetworkInfo.State.CONNECTED
|
|
||||||
|| (state == NetworkInfo.State.CONNECTING && networkAgent.isVPN()))) {
|
|
||||||
|
|
||||||
// A network that has just connected has zero requests and is thus a foreground network.
|
// A network that has just connected has zero requests and is thus a foreground network.
|
||||||
networkAgent.networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND);
|
networkAgent.networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND);
|
||||||
|
|
||||||
if (!createNativeNetwork(networkAgent)) return;
|
if (!createNativeNetwork(networkAgent)) return;
|
||||||
|
|
||||||
|
networkAgent.setCreated();
|
||||||
|
|
||||||
|
// If the network is created immediately on register, then apply the LinkProperties now.
|
||||||
|
// Otherwise, this is done further down when the network goes into connected state.
|
||||||
|
// Applying the LinkProperties means that the network is ready to carry traffic -
|
||||||
|
// interfaces and routing rules have been added, DNS servers programmed, etc.
|
||||||
|
// For VPNs, this must be done before the capabilities are updated, because as soon as
|
||||||
|
// that happens, UIDs are routed to the network.
|
||||||
|
if (shouldCreateNetworksImmediately()) {
|
||||||
|
applyInitialLinkProperties(networkAgent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: should this move earlier? It doesn't seem to have anything to do with whether
|
||||||
|
// a network is created or not.
|
||||||
if (networkAgent.propagateUnderlyingCapabilities()) {
|
if (networkAgent.propagateUnderlyingCapabilities()) {
|
||||||
// Initialize the network's capabilities to their starting values according to the
|
// Initialize the network's capabilities to their starting values according to the
|
||||||
// underlying networks. This ensures that the capabilities are correct before
|
// underlying networks. This ensures that the capabilities are correct before
|
||||||
// anything happens to the network.
|
// anything happens to the network.
|
||||||
updateCapabilitiesForNetwork(networkAgent);
|
updateCapabilitiesForNetwork(networkAgent);
|
||||||
}
|
}
|
||||||
networkAgent.setCreated();
|
|
||||||
networkAgent.onNetworkCreated();
|
networkAgent.onNetworkCreated();
|
||||||
updateAllowedUids(networkAgent, null, networkAgent.networkCapabilities);
|
updateAllowedUids(networkAgent, null, networkAgent.networkCapabilities);
|
||||||
updateProfileAllowedNetworks();
|
updateProfileAllowedNetworks();
|
||||||
@@ -9636,8 +9671,19 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
networkAgent.getAndSetNetworkCapabilities(networkAgent.networkCapabilities);
|
networkAgent.getAndSetNetworkCapabilities(networkAgent.networkCapabilities);
|
||||||
|
|
||||||
handlePerNetworkPrivateDnsConfig(networkAgent, mDnsManager.getPrivateDnsConfig());
|
handlePerNetworkPrivateDnsConfig(networkAgent, mDnsManager.getPrivateDnsConfig());
|
||||||
updateLinkProperties(networkAgent, new LinkProperties(networkAgent.linkProperties),
|
if (!shouldCreateNetworksImmediately()) {
|
||||||
null);
|
applyInitialLinkProperties(networkAgent);
|
||||||
|
} else {
|
||||||
|
// The network was created when the agent registered, and the LinkProperties are
|
||||||
|
// already up-to-date. However, updateLinkProperties also makes some changes only
|
||||||
|
// when the network connects. Apply those changes here. On T and below these are
|
||||||
|
// handled by the applyInitialLinkProperties call just above.
|
||||||
|
// TODO: stop relying on updateLinkProperties(..., null) to do this.
|
||||||
|
// If something depends on both LinkProperties and connected state, it should be in
|
||||||
|
// this method as well.
|
||||||
|
networkAgent.clatd.update();
|
||||||
|
updateProxy(networkAgent.linkProperties, null);
|
||||||
|
}
|
||||||
|
|
||||||
// If a rate limit has been configured and is applicable to this network (network
|
// If a rate limit has been configured and is applicable to this network (network
|
||||||
// provides internet connectivity), apply it. The tc police filter cannot be attached
|
// provides internet connectivity), apply it. The tc police filter cannot be attached
|
||||||
|
|||||||
@@ -29,9 +29,9 @@ import android.net.LinkProperties
|
|||||||
import android.net.NattKeepalivePacketData
|
import android.net.NattKeepalivePacketData
|
||||||
import android.net.Network
|
import android.net.Network
|
||||||
import android.net.NetworkAgent
|
import android.net.NetworkAgent
|
||||||
import android.net.NetworkAgentConfig
|
|
||||||
import android.net.NetworkAgent.INVALID_NETWORK
|
import android.net.NetworkAgent.INVALID_NETWORK
|
||||||
import android.net.NetworkAgent.VALID_NETWORK
|
import android.net.NetworkAgent.VALID_NETWORK
|
||||||
|
import android.net.NetworkAgentConfig
|
||||||
import android.net.NetworkCapabilities
|
import android.net.NetworkCapabilities
|
||||||
import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET
|
import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET
|
||||||
import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED
|
import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED
|
||||||
@@ -46,21 +46,23 @@ import android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED
|
|||||||
import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED
|
import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED
|
||||||
import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
|
import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
|
||||||
import android.net.NetworkCapabilities.TRANSPORT_TEST
|
import android.net.NetworkCapabilities.TRANSPORT_TEST
|
||||||
import android.net.NetworkCapabilities.TRANSPORT_WIFI
|
|
||||||
import android.net.NetworkCapabilities.TRANSPORT_VPN
|
import android.net.NetworkCapabilities.TRANSPORT_VPN
|
||||||
|
import android.net.NetworkCapabilities.TRANSPORT_WIFI
|
||||||
import android.net.NetworkInfo
|
import android.net.NetworkInfo
|
||||||
import android.net.NetworkProvider
|
import android.net.NetworkProvider
|
||||||
import android.net.NetworkReleasedException
|
import android.net.NetworkReleasedException
|
||||||
import android.net.NetworkRequest
|
import android.net.NetworkRequest
|
||||||
import android.net.NetworkScore
|
import android.net.NetworkScore
|
||||||
import android.net.RouteInfo
|
|
||||||
import android.net.QosCallback
|
import android.net.QosCallback
|
||||||
import android.net.QosCallbackException
|
|
||||||
import android.net.QosCallback.QosCallbackRegistrationException
|
import android.net.QosCallback.QosCallbackRegistrationException
|
||||||
|
import android.net.QosCallbackException
|
||||||
import android.net.QosSession
|
import android.net.QosSession
|
||||||
import android.net.QosSessionAttributes
|
import android.net.QosSessionAttributes
|
||||||
import android.net.QosSocketInfo
|
import android.net.QosSocketInfo
|
||||||
|
import android.net.RouteInfo
|
||||||
import android.net.SocketKeepalive
|
import android.net.SocketKeepalive
|
||||||
|
import android.net.TestNetworkInterface
|
||||||
|
import android.net.TestNetworkManager
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.net.VpnManager
|
import android.net.VpnManager
|
||||||
import android.net.VpnTransportInfo
|
import android.net.VpnTransportInfo
|
||||||
@@ -71,6 +73,7 @@ import android.os.Build
|
|||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.HandlerThread
|
import android.os.HandlerThread
|
||||||
import android.os.Message
|
import android.os.Message
|
||||||
|
import android.os.Process
|
||||||
import android.os.SystemClock
|
import android.os.SystemClock
|
||||||
import android.platform.test.annotations.AppModeFull
|
import android.platform.test.annotations.AppModeFull
|
||||||
import android.system.OsConstants.IPPROTO_TCP
|
import android.system.OsConstants.IPPROTO_TCP
|
||||||
@@ -89,6 +92,7 @@ import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
|
|||||||
import com.android.testutils.DevSdkIgnoreRunner
|
import com.android.testutils.DevSdkIgnoreRunner
|
||||||
import com.android.testutils.RecorderCallback.CallbackEntry.Available
|
import com.android.testutils.RecorderCallback.CallbackEntry.Available
|
||||||
import com.android.testutils.RecorderCallback.CallbackEntry.BlockedStatus
|
import com.android.testutils.RecorderCallback.CallbackEntry.BlockedStatus
|
||||||
|
import com.android.testutils.RecorderCallback.CallbackEntry.CapabilitiesChanged
|
||||||
import com.android.testutils.RecorderCallback.CallbackEntry.LinkPropertiesChanged
|
import com.android.testutils.RecorderCallback.CallbackEntry.LinkPropertiesChanged
|
||||||
import com.android.testutils.RecorderCallback.CallbackEntry.Losing
|
import com.android.testutils.RecorderCallback.CallbackEntry.Losing
|
||||||
import com.android.testutils.RecorderCallback.CallbackEntry.Lost
|
import com.android.testutils.RecorderCallback.CallbackEntry.Lost
|
||||||
@@ -178,6 +182,7 @@ class NetworkAgentTest {
|
|||||||
private val agentsToCleanUp = mutableListOf<NetworkAgent>()
|
private val agentsToCleanUp = mutableListOf<NetworkAgent>()
|
||||||
private val callbacksToCleanUp = mutableListOf<TestableNetworkCallback>()
|
private val callbacksToCleanUp = mutableListOf<TestableNetworkCallback>()
|
||||||
private var qosTestSocket: Closeable? = null // either Socket or DatagramSocket
|
private var qosTestSocket: Closeable? = null // either Socket or DatagramSocket
|
||||||
|
private val ifacesToCleanUp = mutableListOf<TestNetworkInterface>()
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
@@ -189,6 +194,7 @@ class NetworkAgentTest {
|
|||||||
fun tearDown() {
|
fun tearDown() {
|
||||||
agentsToCleanUp.forEach { it.unregister() }
|
agentsToCleanUp.forEach { it.unregister() }
|
||||||
callbacksToCleanUp.forEach { mCM.unregisterNetworkCallback(it) }
|
callbacksToCleanUp.forEach { mCM.unregisterNetworkCallback(it) }
|
||||||
|
ifacesToCleanUp.forEach { it.fileDescriptor.close() }
|
||||||
qosTestSocket?.close()
|
qosTestSocket?.close()
|
||||||
mHandlerThread.quitSafely()
|
mHandlerThread.quitSafely()
|
||||||
mHandlerThread.join()
|
mHandlerThread.join()
|
||||||
@@ -269,7 +275,7 @@ class NetworkAgentTest {
|
|||||||
removeCapability(NET_CAPABILITY_INTERNET)
|
removeCapability(NET_CAPABILITY_INTERNET)
|
||||||
addCapability(NET_CAPABILITY_NOT_SUSPENDED)
|
addCapability(NET_CAPABILITY_NOT_SUSPENDED)
|
||||||
addCapability(NET_CAPABILITY_NOT_ROAMING)
|
addCapability(NET_CAPABILITY_NOT_ROAMING)
|
||||||
addCapability(NET_CAPABILITY_NOT_VPN)
|
if (!transports.contains(TRANSPORT_VPN)) addCapability(NET_CAPABILITY_NOT_VPN)
|
||||||
if (SdkLevel.isAtLeastS()) {
|
if (SdkLevel.isAtLeastS()) {
|
||||||
addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
|
addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
|
||||||
}
|
}
|
||||||
@@ -304,7 +310,7 @@ class NetworkAgentTest {
|
|||||||
context: Context = realContext,
|
context: Context = realContext,
|
||||||
specifier: String? = UUID.randomUUID().toString(),
|
specifier: String? = UUID.randomUUID().toString(),
|
||||||
initialConfig: NetworkAgentConfig? = null,
|
initialConfig: NetworkAgentConfig? = null,
|
||||||
expectedInitSignalStrengthThresholds: IntArray? = intArrayOf(),
|
expectedInitSignalStrengthThresholds: IntArray = intArrayOf(),
|
||||||
transports: IntArray = intArrayOf()
|
transports: IntArray = intArrayOf()
|
||||||
): Pair<TestableNetworkAgent, TestableNetworkCallback> {
|
): Pair<TestableNetworkAgent, TestableNetworkCallback> {
|
||||||
val callback = TestableNetworkCallback()
|
val callback = TestableNetworkCallback()
|
||||||
@@ -317,8 +323,7 @@ class NetworkAgentTest {
|
|||||||
agent.register()
|
agent.register()
|
||||||
agent.markConnected()
|
agent.markConnected()
|
||||||
agent.expectCallback<OnNetworkCreated>()
|
agent.expectCallback<OnNetworkCreated>()
|
||||||
agent.expectSignalStrengths(expectedInitSignalStrengthThresholds)
|
agent.expectPostConnectionCallbacks(expectedInitSignalStrengthThresholds)
|
||||||
agent.expectValidationBypassedStatus()
|
|
||||||
callback.expectAvailableThenValidatedCallbacks(agent.network!!)
|
callback.expectAvailableThenValidatedCallbacks(agent.network!!)
|
||||||
return agent to callback
|
return agent to callback
|
||||||
}
|
}
|
||||||
@@ -336,6 +341,19 @@ class NetworkAgentTest {
|
|||||||
mFakeConnectivityService.connect(it.registerForTest(Network(FAKE_NET_ID)))
|
mFakeConnectivityService.connect(it.registerForTest(Network(FAKE_NET_ID)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun TestableNetworkAgent.expectPostConnectionCallbacks(
|
||||||
|
thresholds: IntArray = intArrayOf()
|
||||||
|
) {
|
||||||
|
expectSignalStrengths(thresholds)
|
||||||
|
expectValidationBypassedStatus()
|
||||||
|
assertNoCallback()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createTunInterface(): TestNetworkInterface = realContext.getSystemService(
|
||||||
|
TestNetworkManager::class.java)!!.createTunInterface(emptyList()).also {
|
||||||
|
ifacesToCleanUp.add(it)
|
||||||
|
}
|
||||||
|
|
||||||
fun assertLinkPropertiesEventually(
|
fun assertLinkPropertiesEventually(
|
||||||
n: Network,
|
n: Network,
|
||||||
description: String,
|
description: String,
|
||||||
@@ -1291,8 +1309,12 @@ class NetworkAgentTest {
|
|||||||
requestNetwork(makeTestNetworkRequest(specifier = specifier6), callback)
|
requestNetwork(makeTestNetworkRequest(specifier = specifier6), callback)
|
||||||
val agent6 = createNetworkAgent(specifier = specifier6)
|
val agent6 = createNetworkAgent(specifier = specifier6)
|
||||||
val network6 = agent6.register()
|
val network6 = agent6.register()
|
||||||
// No callbacks are sent, so check the LinkProperties to see if the network has connected.
|
if (SdkLevel.isAtLeastU()) {
|
||||||
assertLinkPropertiesEventuallyNotNull(agent6.network!!)
|
agent6.expectCallback<OnNetworkCreated>()
|
||||||
|
} else {
|
||||||
|
// No callbacks are sent, so check LinkProperties to wait for the network to be created.
|
||||||
|
assertLinkPropertiesEventuallyNotNull(agent6.network!!)
|
||||||
|
}
|
||||||
|
|
||||||
// unregisterAfterReplacement tears down the network immediately.
|
// unregisterAfterReplacement tears down the network immediately.
|
||||||
// Approximately check that this is the case by picking an unregister timeout that's longer
|
// Approximately check that this is the case by picking an unregister timeout that's longer
|
||||||
@@ -1301,8 +1323,9 @@ class NetworkAgentTest {
|
|||||||
val timeoutMs = agent6.DEFAULT_TIMEOUT_MS.toInt() + 1_000
|
val timeoutMs = agent6.DEFAULT_TIMEOUT_MS.toInt() + 1_000
|
||||||
agent6.unregisterAfterReplacement(timeoutMs)
|
agent6.unregisterAfterReplacement(timeoutMs)
|
||||||
agent6.expectCallback<OnNetworkUnwanted>()
|
agent6.expectCallback<OnNetworkUnwanted>()
|
||||||
if (!SdkLevel.isAtLeastT()) {
|
if (!SdkLevel.isAtLeastT() || SdkLevel.isAtLeastU()) {
|
||||||
// Before T, onNetworkDestroyed is called even if the network was never created.
|
// Before T, onNetworkDestroyed is called even if the network was never created.
|
||||||
|
// On U+, the network was created by register(). Destroying it sends onNetworkDestroyed.
|
||||||
agent6.expectCallback<OnNetworkDestroyed>()
|
agent6.expectCallback<OnNetworkDestroyed>()
|
||||||
}
|
}
|
||||||
// Poll for LinkProperties becoming null, because when onNetworkUnwanted is called, the
|
// Poll for LinkProperties becoming null, because when onNetworkUnwanted is called, the
|
||||||
@@ -1375,4 +1398,101 @@ class NetworkAgentTest {
|
|||||||
callback.expect<Available>(agent.network!!)
|
callback.expect<Available>(agent.network!!)
|
||||||
callback.eventuallyExpect<Lost> { it.network == agent.network }
|
callback.eventuallyExpect<Lost> { it.network == agent.network }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun doTestNativeNetworkCreation(expectCreatedImmediately: Boolean, transports: IntArray) {
|
||||||
|
val iface = createTunInterface()
|
||||||
|
val ifName = iface.interfaceName
|
||||||
|
val nc = makeTestNetworkCapabilities(ifName, transports).also {
|
||||||
|
if (transports.contains(TRANSPORT_VPN)) {
|
||||||
|
val sessionId = "NetworkAgentTest-${Process.myPid()}"
|
||||||
|
it.transportInfo = VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM, sessionId,
|
||||||
|
/*bypassable=*/ false, /*longLivedTcpConnectionsExpensive=*/ false)
|
||||||
|
it.underlyingNetworks = listOf()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val lp = LinkProperties().apply {
|
||||||
|
interfaceName = ifName
|
||||||
|
addLinkAddress(LinkAddress("2001:db8::1/64"))
|
||||||
|
addRoute(RouteInfo(IpPrefix("2001:db8::/64"), null /* nextHop */, ifName))
|
||||||
|
addRoute(RouteInfo(IpPrefix("::/0"),
|
||||||
|
InetAddresses.parseNumericAddress("fe80::abcd"),
|
||||||
|
ifName))
|
||||||
|
}
|
||||||
|
|
||||||
|
// File a request containing the agent's specifier to receive callbacks and to ensure that
|
||||||
|
// the agent is not torn down due to being unneeded.
|
||||||
|
val request = makeTestNetworkRequest(specifier = ifName)
|
||||||
|
val requestCallback = TestableNetworkCallback()
|
||||||
|
requestNetwork(request, requestCallback)
|
||||||
|
|
||||||
|
val listenCallback = TestableNetworkCallback()
|
||||||
|
registerNetworkCallback(request, listenCallback)
|
||||||
|
|
||||||
|
// Register the NetworkAgent...
|
||||||
|
val agent = createNetworkAgent(realContext, initialNc = nc, initialLp = lp)
|
||||||
|
val network = agent.register()
|
||||||
|
|
||||||
|
// ... and then change the NetworkCapabilities and LinkProperties.
|
||||||
|
nc.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)
|
||||||
|
agent.sendNetworkCapabilities(nc)
|
||||||
|
lp.addLinkAddress(LinkAddress("192.0.2.2/25"))
|
||||||
|
lp.addRoute(RouteInfo(IpPrefix("192.0.2.0/25"), null /* nextHop */, ifName))
|
||||||
|
agent.sendLinkProperties(lp)
|
||||||
|
|
||||||
|
requestCallback.assertNoCallback()
|
||||||
|
listenCallback.assertNoCallback()
|
||||||
|
if (!expectCreatedImmediately) {
|
||||||
|
agent.assertNoCallback()
|
||||||
|
agent.markConnected()
|
||||||
|
agent.expectCallback<OnNetworkCreated>()
|
||||||
|
} else {
|
||||||
|
agent.expectCallback<OnNetworkCreated>()
|
||||||
|
agent.markConnected()
|
||||||
|
}
|
||||||
|
agent.expectPostConnectionCallbacks()
|
||||||
|
|
||||||
|
// onAvailable must be called only when the network connects, and no other callbacks may be
|
||||||
|
// called before that happens. The callbacks report the state of the network as it was when
|
||||||
|
// it connected, so they reflect the NC and LP changes made after registration.
|
||||||
|
requestCallback.expect<Available>(network)
|
||||||
|
listenCallback.expect<Available>(network)
|
||||||
|
|
||||||
|
requestCallback.expect<CapabilitiesChanged>(network) { it.caps.hasCapability(
|
||||||
|
NET_CAPABILITY_TEMPORARILY_NOT_METERED) }
|
||||||
|
listenCallback.expect<CapabilitiesChanged>(network) { it.caps.hasCapability(
|
||||||
|
NET_CAPABILITY_TEMPORARILY_NOT_METERED) }
|
||||||
|
|
||||||
|
requestCallback.expect<LinkPropertiesChanged>(network) { it.lp.equals(lp) }
|
||||||
|
listenCallback.expect<LinkPropertiesChanged>(network) { it.lp.equals(lp) }
|
||||||
|
|
||||||
|
requestCallback.expect<BlockedStatus>()
|
||||||
|
listenCallback.expect<BlockedStatus>()
|
||||||
|
|
||||||
|
// Except for network validation, ensure no more callbacks are sent.
|
||||||
|
requestCallback.expectCaps(network) {
|
||||||
|
it.hasCapability(NET_CAPABILITY_VALIDATED)
|
||||||
|
}
|
||||||
|
listenCallback.expectCaps(network) {
|
||||||
|
it.hasCapability(NET_CAPABILITY_VALIDATED)
|
||||||
|
}
|
||||||
|
unregister(agent)
|
||||||
|
// Lost implicitly checks that no further callbacks happened after connect.
|
||||||
|
requestCallback.expect<Lost>(network)
|
||||||
|
listenCallback.expect<Lost>(network)
|
||||||
|
assertNull(mCM.getLinkProperties(network))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testNativeNetworkCreation_PhysicalNetwork() {
|
||||||
|
// On T and below, the native network is only created when the agent connects.
|
||||||
|
// Starting in U, the native network is created as soon as the agent is registered.
|
||||||
|
doTestNativeNetworkCreation(expectCreatedImmediately = SdkLevel.isAtLeastU(),
|
||||||
|
intArrayOf(TRANSPORT_CELLULAR))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testNativeNetworkCreation_Vpn() {
|
||||||
|
// VPN networks are always created as soon as the agent is registered.
|
||||||
|
doTestNativeNetworkCreation(expectCreatedImmediately = true, intArrayOf(TRANSPORT_VPN))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3783,6 +3783,12 @@ public class ConnectivityServiceTest {
|
|||||||
|
|
||||||
mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, callbacks);
|
mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, callbacks);
|
||||||
|
|
||||||
|
if (mService.shouldCreateNetworksImmediately()) {
|
||||||
|
assertEquals("onNetworkCreated", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
|
||||||
|
} else {
|
||||||
|
assertNull(eventOrder.poll());
|
||||||
|
}
|
||||||
|
|
||||||
// Connect a network, and file a request for it after it has come up, to ensure the nascent
|
// Connect a network, and file a request for it after it has come up, to ensure the nascent
|
||||||
// timer is cleared and the test does not have to wait for it. Filing the request after the
|
// timer is cleared and the test does not have to wait for it. Filing the request after the
|
||||||
// network has come up is necessary because ConnectivityService does not appear to clear the
|
// network has come up is necessary because ConnectivityService does not appear to clear the
|
||||||
@@ -3790,7 +3796,12 @@ public class ConnectivityServiceTest {
|
|||||||
// connected.
|
// connected.
|
||||||
// TODO: fix this bug, file the request before connecting, and remove the waitForIdle.
|
// TODO: fix this bug, file the request before connecting, and remove the waitForIdle.
|
||||||
mWiFiAgent.connectWithoutInternet();
|
mWiFiAgent.connectWithoutInternet();
|
||||||
waitForIdle();
|
if (!mService.shouldCreateNetworksImmediately()) {
|
||||||
|
assertEquals("onNetworkCreated", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
|
||||||
|
} else {
|
||||||
|
waitForIdle();
|
||||||
|
assertNull(eventOrder.poll());
|
||||||
|
}
|
||||||
mCm.requestNetwork(request, callback);
|
mCm.requestNetwork(request, callback);
|
||||||
callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
|
callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
|
||||||
|
|
||||||
@@ -3807,7 +3818,6 @@ public class ConnectivityServiceTest {
|
|||||||
|
|
||||||
// Disconnect the network and check that events happened in the right order.
|
// Disconnect the network and check that events happened in the right order.
|
||||||
mCm.unregisterNetworkCallback(callback);
|
mCm.unregisterNetworkCallback(callback);
|
||||||
assertEquals("onNetworkCreated", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
|
|
||||||
assertEquals("onNetworkUnwanted", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
|
assertEquals("onNetworkUnwanted", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
|
||||||
assertEquals("timePasses", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
|
assertEquals("timePasses", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
|
||||||
assertEquals("onNetworkDisconnected", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
|
assertEquals("onNetworkDisconnected", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
|
||||||
@@ -7593,7 +7603,9 @@ public class ConnectivityServiceTest {
|
|||||||
// Simple connection with initial LP should have updated ifaces.
|
// Simple connection with initial LP should have updated ifaces.
|
||||||
mCellAgent.connect(false);
|
mCellAgent.connect(false);
|
||||||
waitForIdle();
|
waitForIdle();
|
||||||
expectNotifyNetworkStatus(onlyCell(), onlyCell(), MOBILE_IFNAME);
|
List<Network> allNetworks = mService.shouldCreateNetworksImmediately()
|
||||||
|
? cellAndWifi() : onlyCell();
|
||||||
|
expectNotifyNetworkStatus(allNetworks, onlyCell(), MOBILE_IFNAME);
|
||||||
reset(mStatsManager);
|
reset(mStatsManager);
|
||||||
|
|
||||||
// Verify change fields other than interfaces does not trigger a notification to NSS.
|
// Verify change fields other than interfaces does not trigger a notification to NSS.
|
||||||
@@ -7902,9 +7914,13 @@ public class ConnectivityServiceTest {
|
|||||||
setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
|
setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
|
||||||
|
|
||||||
mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
|
mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
|
||||||
|
final int netId = mCellAgent.getNetwork().netId;
|
||||||
waitForIdle();
|
waitForIdle();
|
||||||
verify(mMockDnsResolver, never()).setResolverConfiguration(any());
|
if (mService.shouldCreateNetworksImmediately()) {
|
||||||
verifyNoMoreInteractions(mMockDnsResolver);
|
verify(mMockDnsResolver, times(1)).createNetworkCache(netId);
|
||||||
|
} else {
|
||||||
|
verify(mMockDnsResolver, never()).setResolverConfiguration(any());
|
||||||
|
}
|
||||||
|
|
||||||
final LinkProperties cellLp = new LinkProperties();
|
final LinkProperties cellLp = new LinkProperties();
|
||||||
cellLp.setInterfaceName(MOBILE_IFNAME);
|
cellLp.setInterfaceName(MOBILE_IFNAME);
|
||||||
@@ -7920,10 +7936,13 @@ public class ConnectivityServiceTest {
|
|||||||
mCellAgent.sendLinkProperties(cellLp);
|
mCellAgent.sendLinkProperties(cellLp);
|
||||||
mCellAgent.connect(false);
|
mCellAgent.connect(false);
|
||||||
waitForIdle();
|
waitForIdle();
|
||||||
|
if (!mService.shouldCreateNetworksImmediately()) {
|
||||||
verify(mMockDnsResolver, times(1)).createNetworkCache(eq(mCellAgent.getNetwork().netId));
|
// CS tells dnsresolver about the empty DNS config for this network.
|
||||||
// CS tells dnsresolver about the empty DNS config for this network.
|
verify(mMockDnsResolver, times(1)).createNetworkCache(netId);
|
||||||
|
}
|
||||||
verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
|
verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
|
||||||
|
|
||||||
|
verifyNoMoreInteractions(mMockDnsResolver);
|
||||||
reset(mMockDnsResolver);
|
reset(mMockDnsResolver);
|
||||||
|
|
||||||
cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
|
cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
|
||||||
@@ -8038,10 +8057,13 @@ public class ConnectivityServiceTest {
|
|||||||
mCm.requestNetwork(cellRequest, cellNetworkCallback);
|
mCm.requestNetwork(cellRequest, cellNetworkCallback);
|
||||||
|
|
||||||
mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
|
mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
|
||||||
|
final int netId = mCellAgent.getNetwork().netId;
|
||||||
waitForIdle();
|
waitForIdle();
|
||||||
// CS tells netd about the empty DNS config for this network.
|
if (mService.shouldCreateNetworksImmediately()) {
|
||||||
verify(mMockDnsResolver, never()).setResolverConfiguration(any());
|
verify(mMockDnsResolver, times(1)).createNetworkCache(netId);
|
||||||
verifyNoMoreInteractions(mMockDnsResolver);
|
} else {
|
||||||
|
verify(mMockDnsResolver, never()).setResolverConfiguration(any());
|
||||||
|
}
|
||||||
|
|
||||||
final LinkProperties cellLp = new LinkProperties();
|
final LinkProperties cellLp = new LinkProperties();
|
||||||
cellLp.setInterfaceName(MOBILE_IFNAME);
|
cellLp.setInterfaceName(MOBILE_IFNAME);
|
||||||
@@ -8060,7 +8082,9 @@ public class ConnectivityServiceTest {
|
|||||||
mCellAgent.sendLinkProperties(cellLp);
|
mCellAgent.sendLinkProperties(cellLp);
|
||||||
mCellAgent.connect(false);
|
mCellAgent.connect(false);
|
||||||
waitForIdle();
|
waitForIdle();
|
||||||
verify(mMockDnsResolver, times(1)).createNetworkCache(eq(mCellAgent.getNetwork().netId));
|
if (!mService.shouldCreateNetworksImmediately()) {
|
||||||
|
verify(mMockDnsResolver, times(1)).createNetworkCache(netId);
|
||||||
|
}
|
||||||
verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
|
verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
|
||||||
mResolverParamsParcelCaptor.capture());
|
mResolverParamsParcelCaptor.capture());
|
||||||
ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
|
ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
|
||||||
@@ -8071,6 +8095,7 @@ public class ConnectivityServiceTest {
|
|||||||
assertEquals(2, resolvrParams.tlsServers.length);
|
assertEquals(2, resolvrParams.tlsServers.length);
|
||||||
assertTrue(new ArraySet<>(resolvrParams.tlsServers).containsAll(
|
assertTrue(new ArraySet<>(resolvrParams.tlsServers).containsAll(
|
||||||
asList("2001:db8::1", "192.0.2.1")));
|
asList("2001:db8::1", "192.0.2.1")));
|
||||||
|
verifyNoMoreInteractions(mMockDnsResolver);
|
||||||
reset(mMockDnsResolver);
|
reset(mMockDnsResolver);
|
||||||
cellNetworkCallback.expect(AVAILABLE, mCellAgent);
|
cellNetworkCallback.expect(AVAILABLE, mCellAgent);
|
||||||
cellNetworkCallback.expect(NETWORK_CAPS_UPDATED, mCellAgent);
|
cellNetworkCallback.expect(NETWORK_CAPS_UPDATED, mCellAgent);
|
||||||
@@ -10388,7 +10413,8 @@ public class ConnectivityServiceTest {
|
|||||||
if (inOrder != null) {
|
if (inOrder != null) {
|
||||||
return inOrder.verify(t);
|
return inOrder.verify(t);
|
||||||
} else {
|
} else {
|
||||||
return verify(t);
|
// times(1) for consistency with the above. InOrder#verify always implies times(1).
|
||||||
|
return verify(t, times(1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -10437,6 +10463,21 @@ public class ConnectivityServiceTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void expectNativeNetworkCreated(int netId, int permission, String iface,
|
||||||
|
InOrder inOrder) throws Exception {
|
||||||
|
verifyWithOrder(inOrder, mMockNetd).networkCreate(nativeNetworkConfigPhysical(netId,
|
||||||
|
permission));
|
||||||
|
verifyWithOrder(inOrder, mMockDnsResolver).createNetworkCache(eq(netId));
|
||||||
|
if (iface != null) {
|
||||||
|
verifyWithOrder(inOrder, mMockNetd).networkAddInterface(netId, iface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void expectNativeNetworkCreated(int netId, int permission, String iface)
|
||||||
|
throws Exception {
|
||||||
|
expectNativeNetworkCreated(netId, permission, iface, null /* inOrder */);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStackedLinkProperties() throws Exception {
|
public void testStackedLinkProperties() throws Exception {
|
||||||
final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24");
|
final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24");
|
||||||
@@ -10474,11 +10515,8 @@ public class ConnectivityServiceTest {
|
|||||||
int cellNetId = mCellAgent.getNetwork().netId;
|
int cellNetId = mCellAgent.getNetwork().netId;
|
||||||
waitForIdle();
|
waitForIdle();
|
||||||
|
|
||||||
verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(cellNetId,
|
expectNativeNetworkCreated(cellNetId, INetd.PERMISSION_NONE, MOBILE_IFNAME);
|
||||||
INetd.PERMISSION_NONE));
|
|
||||||
assertRoutesAdded(cellNetId, ipv6Subnet, ipv6Default);
|
assertRoutesAdded(cellNetId, ipv6Subnet, ipv6Default);
|
||||||
verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId));
|
|
||||||
verify(mMockNetd, times(1)).networkAddInterface(cellNetId, MOBILE_IFNAME);
|
|
||||||
final ArrayTrackRecord<ReportedInterfaces>.ReadHead readHead =
|
final ArrayTrackRecord<ReportedInterfaces>.ReadHead readHead =
|
||||||
mDeps.mReportedInterfaceHistory.newReadHead();
|
mDeps.mReportedInterfaceHistory.newReadHead();
|
||||||
assertNotNull(readHead.poll(TIMEOUT_MS, ri -> ri.contentEquals(mServiceContext,
|
assertNotNull(readHead.poll(TIMEOUT_MS, ri -> ri.contentEquals(mServiceContext,
|
||||||
@@ -14993,7 +15031,7 @@ public class ConnectivityServiceTest {
|
|||||||
UserHandle testHandle,
|
UserHandle testHandle,
|
||||||
TestNetworkCallback profileDefaultNetworkCallback,
|
TestNetworkCallback profileDefaultNetworkCallback,
|
||||||
TestNetworkCallback disAllowProfileDefaultNetworkCallback) throws Exception {
|
TestNetworkCallback disAllowProfileDefaultNetworkCallback) throws Exception {
|
||||||
final InOrder inOrder = inOrder(mMockNetd);
|
final InOrder inOrder = inOrder(mMockNetd, mMockDnsResolver);
|
||||||
|
|
||||||
mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
|
mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
|
||||||
mCellAgent.connect(true);
|
mCellAgent.connect(true);
|
||||||
@@ -15009,8 +15047,16 @@ public class ConnectivityServiceTest {
|
|||||||
|
|
||||||
final TestNetworkAgentWrapper workAgent =
|
final TestNetworkAgentWrapper workAgent =
|
||||||
makeEnterpriseNetworkAgent(profileNetworkPreference.getPreferenceEnterpriseId());
|
makeEnterpriseNetworkAgent(profileNetworkPreference.getPreferenceEnterpriseId());
|
||||||
|
if (mService.shouldCreateNetworksImmediately()) {
|
||||||
|
expectNativeNetworkCreated(workAgent.getNetwork().netId, INetd.PERMISSION_SYSTEM,
|
||||||
|
null /* iface */, inOrder);
|
||||||
|
}
|
||||||
if (connectWorkProfileAgentAhead) {
|
if (connectWorkProfileAgentAhead) {
|
||||||
workAgent.connect(false);
|
workAgent.connect(false);
|
||||||
|
if (!mService.shouldCreateNetworksImmediately()) {
|
||||||
|
expectNativeNetworkCreated(workAgent.getNetwork().netId, INetd.PERMISSION_SYSTEM,
|
||||||
|
null /* iface */, inOrder);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final TestOnCompleteListener listener = new TestOnCompleteListener();
|
final TestOnCompleteListener listener = new TestOnCompleteListener();
|
||||||
@@ -15050,6 +15096,11 @@ public class ConnectivityServiceTest {
|
|||||||
|
|
||||||
if (!connectWorkProfileAgentAhead) {
|
if (!connectWorkProfileAgentAhead) {
|
||||||
workAgent.connect(false);
|
workAgent.connect(false);
|
||||||
|
if (!mService.shouldCreateNetworksImmediately()) {
|
||||||
|
inOrder.verify(mMockNetd).networkCreate(
|
||||||
|
nativeNetworkConfigPhysical(workAgent.getNetwork().netId,
|
||||||
|
INetd.PERMISSION_SYSTEM));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
profileDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(workAgent);
|
profileDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(workAgent);
|
||||||
@@ -15058,8 +15109,6 @@ public class ConnectivityServiceTest {
|
|||||||
}
|
}
|
||||||
mSystemDefaultNetworkCallback.assertNoCallback();
|
mSystemDefaultNetworkCallback.assertNoCallback();
|
||||||
mDefaultNetworkCallback.assertNoCallback();
|
mDefaultNetworkCallback.assertNoCallback();
|
||||||
inOrder.verify(mMockNetd).networkCreate(
|
|
||||||
nativeNetworkConfigPhysical(workAgent.getNetwork().netId, INetd.PERMISSION_SYSTEM));
|
|
||||||
inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
|
inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
|
||||||
workAgent.getNetwork().netId,
|
workAgent.getNetwork().netId,
|
||||||
uidRangeFor(testHandle, profileNetworkPreference),
|
uidRangeFor(testHandle, profileNetworkPreference),
|
||||||
@@ -17578,6 +17627,22 @@ public class ConnectivityServiceTest {
|
|||||||
verify(mMockNetd, never()).interfaceSetMtu(eq(WIFI_IFNAME), anyInt());
|
verify(mMockNetd, never()).interfaceSetMtu(eq(WIFI_IFNAME), anyInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void verifyMtuSetOnWifiInterfaceOnlyUpToT(int mtu) throws Exception {
|
||||||
|
if (!mService.shouldCreateNetworksImmediately()) {
|
||||||
|
verify(mMockNetd, times(1)).interfaceSetMtu(WIFI_IFNAME, mtu);
|
||||||
|
} else {
|
||||||
|
verify(mMockNetd, never()).interfaceSetMtu(eq(WIFI_IFNAME), anyInt());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void verifyMtuSetOnWifiInterfaceOnlyStartingFromU(int mtu) throws Exception {
|
||||||
|
if (mService.shouldCreateNetworksImmediately()) {
|
||||||
|
verify(mMockNetd, times(1)).interfaceSetMtu(WIFI_IFNAME, mtu);
|
||||||
|
} else {
|
||||||
|
verify(mMockNetd, never()).interfaceSetMtu(eq(WIFI_IFNAME), anyInt());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSendLinkPropertiesSetInterfaceMtuBeforeConnect() throws Exception {
|
public void testSendLinkPropertiesSetInterfaceMtuBeforeConnect() throws Exception {
|
||||||
final int mtu = 1281;
|
final int mtu = 1281;
|
||||||
@@ -17592,8 +17657,8 @@ public class ConnectivityServiceTest {
|
|||||||
reset(mMockNetd);
|
reset(mMockNetd);
|
||||||
|
|
||||||
mWiFiAgent.connect(false /* validated */);
|
mWiFiAgent.connect(false /* validated */);
|
||||||
// The MTU is always (re-)applied when the network connects.
|
// Before U, the MTU is always (re-)applied when the network connects.
|
||||||
verifyMtuSetOnWifiInterface(mtu);
|
verifyMtuSetOnWifiInterfaceOnlyUpToT(mtu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -17603,13 +17668,13 @@ public class ConnectivityServiceTest {
|
|||||||
lp.setInterfaceName(WIFI_IFNAME);
|
lp.setInterfaceName(WIFI_IFNAME);
|
||||||
lp.setMtu(mtu);
|
lp.setMtu(mtu);
|
||||||
|
|
||||||
// Registering an agent with an MTU doesn't set the MTU...
|
// Registering an agent with an MTU only sets the MTU on U+.
|
||||||
mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
|
mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
|
||||||
waitForIdle();
|
waitForIdle();
|
||||||
verifyMtuNeverSetOnWifiInterface();
|
verifyMtuSetOnWifiInterfaceOnlyStartingFromU(mtu);
|
||||||
reset(mMockNetd);
|
reset(mMockNetd);
|
||||||
|
|
||||||
// ... but prevents future updates with the same MTU from setting the MTU.
|
// Future updates with the same MTU don't set the MTU even on T when it's not set initially.
|
||||||
mWiFiAgent.sendLinkProperties(lp);
|
mWiFiAgent.sendLinkProperties(lp);
|
||||||
waitForIdle();
|
waitForIdle();
|
||||||
verifyMtuNeverSetOnWifiInterface();
|
verifyMtuNeverSetOnWifiInterface();
|
||||||
@@ -17622,8 +17687,8 @@ public class ConnectivityServiceTest {
|
|||||||
reset(mMockNetd);
|
reset(mMockNetd);
|
||||||
|
|
||||||
mWiFiAgent.connect(false /* validated */);
|
mWiFiAgent.connect(false /* validated */);
|
||||||
// The MTU is always (re-)applied when the network connects.
|
// Before U, the MTU is always (re-)applied when the network connects.
|
||||||
verifyMtuSetOnWifiInterface(mtu + 1);
|
verifyMtuSetOnWifiInterfaceOnlyUpToT(mtu + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user