Merge "Immediately create native networks when NetworkAgents register."

This commit is contained in:
Lorenzo Colitti
2023-05-11 03:35:21 +00:00
committed by Gerrit Code Review
3 changed files with 281 additions and 50 deletions

View File

@@ -2653,7 +2653,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
final ArrayList<NetworkStateSnapshot> result = new ArrayList<>();
for (Network network : getAllNetworks()) {
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
// NetworkCapabilities, which may contain UIDs of apps to which the
// network applies. Should the UIDs be cleared so as not to leak or
@@ -3879,9 +3880,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
break;
}
case NetworkAgent.EVENT_UNREGISTER_AFTER_REPLACEMENT: {
if (!nai.isCreated()) {
Log.d(TAG, "unregisterAfterReplacement on uncreated " + nai.toShortString()
+ ", tearing down instead");
if (!nai.everConnected()) {
Log.d(TAG, "unregisterAfterReplacement on never-connected "
+ nai.toShortString() + ", tearing down instead");
teardownUnneededNetwork(nai);
break;
}
@@ -4466,6 +4467,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) {
return nai.isCreated() && !nai.isDestroyed();
}
@@ -7908,7 +7928,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (isDefaultNetwork(networkAgent)) {
handleApplyDefaultProxy(newLp.getHttpProxy());
} else {
} else if (networkAgent.everConnected()) {
updateProxy(newLp, oldLp);
}
@@ -7942,6 +7962,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
mKeepaliveTracker.handleCheckKeepalivesStillValid(networkAgent);
}
private void applyInitialLinkProperties(@NonNull NetworkAgentInfo nai) {
updateLinkProperties(nai, new LinkProperties(nai.linkProperties), null);
}
/**
* @param naData captive portal data from NetworkAgent
* @param apiData captive portal data from capport API
@@ -9704,21 +9728,32 @@ public class ConnectivityService extends IConnectivityManager.Stub
+ oldInfo.getState() + " to " + state);
}
if (!networkAgent.isCreated()
&& (state == NetworkInfo.State.CONNECTED
|| (state == NetworkInfo.State.CONNECTING && networkAgent.isVPN()))) {
if (shouldCreateNativeNetwork(networkAgent, state)) {
// A network that has just connected has zero requests and is thus a foreground network.
networkAgent.networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND);
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()) {
// Initialize the network's capabilities to their starting values according to the
// underlying networks. This ensures that the capabilities are correct before
// anything happens to the network.
updateCapabilitiesForNetwork(networkAgent);
}
networkAgent.setCreated();
networkAgent.onNetworkCreated();
updateAllowedUids(networkAgent, null, networkAgent.networkCapabilities);
updateProfileAllowedNetworks();
@@ -9732,8 +9767,19 @@ public class ConnectivityService extends IConnectivityManager.Stub
networkAgent.getAndSetNetworkCapabilities(networkAgent.networkCapabilities);
handlePerNetworkPrivateDnsConfig(networkAgent, mDnsManager.getPrivateDnsConfig());
updateLinkProperties(networkAgent, new LinkProperties(networkAgent.linkProperties),
null);
if (!shouldCreateNetworksImmediately()) {
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
// provides internet connectivity), apply it. The tc police filter cannot be attached

View File

@@ -29,9 +29,9 @@ import android.net.LinkProperties
import android.net.NattKeepalivePacketData
import android.net.Network
import android.net.NetworkAgent
import android.net.NetworkAgentConfig
import android.net.NetworkAgent.INVALID_NETWORK
import android.net.NetworkAgent.VALID_NETWORK
import android.net.NetworkAgentConfig
import android.net.NetworkCapabilities
import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET
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.TRANSPORT_CELLULAR
import android.net.NetworkCapabilities.TRANSPORT_TEST
import android.net.NetworkCapabilities.TRANSPORT_WIFI
import android.net.NetworkCapabilities.TRANSPORT_VPN
import android.net.NetworkCapabilities.TRANSPORT_WIFI
import android.net.NetworkInfo
import android.net.NetworkProvider
import android.net.NetworkReleasedException
import android.net.NetworkRequest
import android.net.NetworkScore
import android.net.RouteInfo
import android.net.QosCallback
import android.net.QosCallbackException
import android.net.QosCallback.QosCallbackRegistrationException
import android.net.QosCallbackException
import android.net.QosSession
import android.net.QosSessionAttributes
import android.net.QosSocketInfo
import android.net.RouteInfo
import android.net.SocketKeepalive
import android.net.TestNetworkInterface
import android.net.TestNetworkManager
import android.net.Uri
import android.net.VpnManager
import android.net.VpnTransportInfo
@@ -71,6 +73,7 @@ import android.os.Build
import android.os.Handler
import android.os.HandlerThread
import android.os.Message
import android.os.Process
import android.os.SystemClock
import android.platform.test.annotations.AppModeFull
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.RecorderCallback.CallbackEntry.Available
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.Losing
import com.android.testutils.RecorderCallback.CallbackEntry.Lost
@@ -178,6 +182,7 @@ class NetworkAgentTest {
private val agentsToCleanUp = mutableListOf<NetworkAgent>()
private val callbacksToCleanUp = mutableListOf<TestableNetworkCallback>()
private var qosTestSocket: Closeable? = null // either Socket or DatagramSocket
private val ifacesToCleanUp = mutableListOf<TestNetworkInterface>()
@Before
fun setUp() {
@@ -189,6 +194,7 @@ class NetworkAgentTest {
fun tearDown() {
agentsToCleanUp.forEach { it.unregister() }
callbacksToCleanUp.forEach { mCM.unregisterNetworkCallback(it) }
ifacesToCleanUp.forEach { it.fileDescriptor.close() }
qosTestSocket?.close()
mHandlerThread.quitSafely()
mHandlerThread.join()
@@ -269,7 +275,7 @@ class NetworkAgentTest {
removeCapability(NET_CAPABILITY_INTERNET)
addCapability(NET_CAPABILITY_NOT_SUSPENDED)
addCapability(NET_CAPABILITY_NOT_ROAMING)
addCapability(NET_CAPABILITY_NOT_VPN)
if (!transports.contains(TRANSPORT_VPN)) addCapability(NET_CAPABILITY_NOT_VPN)
if (SdkLevel.isAtLeastS()) {
addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
}
@@ -304,7 +310,7 @@ class NetworkAgentTest {
context: Context = realContext,
specifier: String? = UUID.randomUUID().toString(),
initialConfig: NetworkAgentConfig? = null,
expectedInitSignalStrengthThresholds: IntArray? = intArrayOf(),
expectedInitSignalStrengthThresholds: IntArray = intArrayOf(),
transports: IntArray = intArrayOf()
): Pair<TestableNetworkAgent, TestableNetworkCallback> {
val callback = TestableNetworkCallback()
@@ -317,8 +323,7 @@ class NetworkAgentTest {
agent.register()
agent.markConnected()
agent.expectCallback<OnNetworkCreated>()
agent.expectSignalStrengths(expectedInitSignalStrengthThresholds)
agent.expectValidationBypassedStatus()
agent.expectPostConnectionCallbacks(expectedInitSignalStrengthThresholds)
callback.expectAvailableThenValidatedCallbacks(agent.network!!)
return agent to callback
}
@@ -336,6 +341,19 @@ class NetworkAgentTest {
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(
n: Network,
description: String,
@@ -1291,8 +1309,12 @@ class NetworkAgentTest {
requestNetwork(makeTestNetworkRequest(specifier = specifier6), callback)
val agent6 = createNetworkAgent(specifier = specifier6)
val network6 = agent6.register()
// No callbacks are sent, so check the LinkProperties to see if the network has connected.
assertLinkPropertiesEventuallyNotNull(agent6.network!!)
if (SdkLevel.isAtLeastU()) {
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.
// 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
agent6.unregisterAfterReplacement(timeoutMs)
agent6.expectCallback<OnNetworkUnwanted>()
if (!SdkLevel.isAtLeastT()) {
if (!SdkLevel.isAtLeastT() || SdkLevel.isAtLeastU()) {
// 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>()
}
// Poll for LinkProperties becoming null, because when onNetworkUnwanted is called, the
@@ -1375,4 +1398,101 @@ class NetworkAgentTest {
callback.expect<Available>(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))
}
}

View File

@@ -3810,6 +3810,12 @@ public class ConnectivityServiceTest {
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
// 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
@@ -3817,7 +3823,12 @@ public class ConnectivityServiceTest {
// connected.
// TODO: fix this bug, file the request before connecting, and remove the waitForIdle.
mWiFiAgent.connectWithoutInternet();
waitForIdle();
if (!mService.shouldCreateNetworksImmediately()) {
assertEquals("onNetworkCreated", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
} else {
waitForIdle();
assertNull(eventOrder.poll());
}
mCm.requestNetwork(request, callback);
callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
@@ -3834,7 +3845,6 @@ public class ConnectivityServiceTest {
// Disconnect the network and check that events happened in the right order.
mCm.unregisterNetworkCallback(callback);
assertEquals("onNetworkCreated", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
assertEquals("onNetworkUnwanted", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
assertEquals("timePasses", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
assertEquals("onNetworkDisconnected", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
@@ -7620,7 +7630,9 @@ public class ConnectivityServiceTest {
// Simple connection with initial LP should have updated ifaces.
mCellAgent.connect(false);
waitForIdle();
expectNotifyNetworkStatus(onlyCell(), onlyCell(), MOBILE_IFNAME);
List<Network> allNetworks = mService.shouldCreateNetworksImmediately()
? cellAndWifi() : onlyCell();
expectNotifyNetworkStatus(allNetworks, onlyCell(), MOBILE_IFNAME);
reset(mStatsManager);
// Verify change fields other than interfaces does not trigger a notification to NSS.
@@ -7929,9 +7941,13 @@ public class ConnectivityServiceTest {
setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
final int netId = mCellAgent.getNetwork().netId;
waitForIdle();
verify(mMockDnsResolver, never()).setResolverConfiguration(any());
verifyNoMoreInteractions(mMockDnsResolver);
if (mService.shouldCreateNetworksImmediately()) {
verify(mMockDnsResolver, times(1)).createNetworkCache(netId);
} else {
verify(mMockDnsResolver, never()).setResolverConfiguration(any());
}
final LinkProperties cellLp = new LinkProperties();
cellLp.setInterfaceName(MOBILE_IFNAME);
@@ -7947,10 +7963,13 @@ public class ConnectivityServiceTest {
mCellAgent.sendLinkProperties(cellLp);
mCellAgent.connect(false);
waitForIdle();
verify(mMockDnsResolver, times(1)).createNetworkCache(eq(mCellAgent.getNetwork().netId));
// CS tells dnsresolver about the empty DNS config for this network.
if (!mService.shouldCreateNetworksImmediately()) {
// CS tells dnsresolver about the empty DNS config for this network.
verify(mMockDnsResolver, times(1)).createNetworkCache(netId);
}
verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
verifyNoMoreInteractions(mMockDnsResolver);
reset(mMockDnsResolver);
cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
@@ -8065,10 +8084,13 @@ public class ConnectivityServiceTest {
mCm.requestNetwork(cellRequest, cellNetworkCallback);
mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
final int netId = mCellAgent.getNetwork().netId;
waitForIdle();
// CS tells netd about the empty DNS config for this network.
verify(mMockDnsResolver, never()).setResolverConfiguration(any());
verifyNoMoreInteractions(mMockDnsResolver);
if (mService.shouldCreateNetworksImmediately()) {
verify(mMockDnsResolver, times(1)).createNetworkCache(netId);
} else {
verify(mMockDnsResolver, never()).setResolverConfiguration(any());
}
final LinkProperties cellLp = new LinkProperties();
cellLp.setInterfaceName(MOBILE_IFNAME);
@@ -8087,7 +8109,9 @@ public class ConnectivityServiceTest {
mCellAgent.sendLinkProperties(cellLp);
mCellAgent.connect(false);
waitForIdle();
verify(mMockDnsResolver, times(1)).createNetworkCache(eq(mCellAgent.getNetwork().netId));
if (!mService.shouldCreateNetworksImmediately()) {
verify(mMockDnsResolver, times(1)).createNetworkCache(netId);
}
verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
mResolverParamsParcelCaptor.capture());
ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
@@ -8098,6 +8122,7 @@ public class ConnectivityServiceTest {
assertEquals(2, resolvrParams.tlsServers.length);
assertTrue(new ArraySet<>(resolvrParams.tlsServers).containsAll(
asList("2001:db8::1", "192.0.2.1")));
verifyNoMoreInteractions(mMockDnsResolver);
reset(mMockDnsResolver);
cellNetworkCallback.expect(AVAILABLE, mCellAgent);
cellNetworkCallback.expect(NETWORK_CAPS_UPDATED, mCellAgent);
@@ -10425,7 +10450,8 @@ public class ConnectivityServiceTest {
if (inOrder != null) {
return inOrder.verify(t);
} else {
return verify(t);
// times(1) for consistency with the above. InOrder#verify always implies times(1).
return verify(t, times(1));
}
}
@@ -10474,6 +10500,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
public void testStackedLinkProperties() throws Exception {
final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24");
@@ -10511,11 +10552,8 @@ public class ConnectivityServiceTest {
int cellNetId = mCellAgent.getNetwork().netId;
waitForIdle();
verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(cellNetId,
INetd.PERMISSION_NONE));
expectNativeNetworkCreated(cellNetId, INetd.PERMISSION_NONE, MOBILE_IFNAME);
assertRoutesAdded(cellNetId, ipv6Subnet, ipv6Default);
verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId));
verify(mMockNetd, times(1)).networkAddInterface(cellNetId, MOBILE_IFNAME);
final ArrayTrackRecord<ReportedInterfaces>.ReadHead readHead =
mDeps.mReportedInterfaceHistory.newReadHead();
assertNotNull(readHead.poll(TIMEOUT_MS, ri -> ri.contentEquals(mServiceContext,
@@ -15062,7 +15100,7 @@ public class ConnectivityServiceTest {
UserHandle testHandle,
TestNetworkCallback profileDefaultNetworkCallback,
TestNetworkCallback disAllowProfileDefaultNetworkCallback) throws Exception {
final InOrder inOrder = inOrder(mMockNetd);
final InOrder inOrder = inOrder(mMockNetd, mMockDnsResolver);
mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellAgent.connect(true);
@@ -15078,8 +15116,16 @@ public class ConnectivityServiceTest {
final TestNetworkAgentWrapper workAgent =
makeEnterpriseNetworkAgent(profileNetworkPreference.getPreferenceEnterpriseId());
if (mService.shouldCreateNetworksImmediately()) {
expectNativeNetworkCreated(workAgent.getNetwork().netId, INetd.PERMISSION_SYSTEM,
null /* iface */, inOrder);
}
if (connectWorkProfileAgentAhead) {
workAgent.connect(false);
if (!mService.shouldCreateNetworksImmediately()) {
expectNativeNetworkCreated(workAgent.getNetwork().netId, INetd.PERMISSION_SYSTEM,
null /* iface */, inOrder);
}
}
final TestOnCompleteListener listener = new TestOnCompleteListener();
@@ -15119,6 +15165,11 @@ public class ConnectivityServiceTest {
if (!connectWorkProfileAgentAhead) {
workAgent.connect(false);
if (!mService.shouldCreateNetworksImmediately()) {
inOrder.verify(mMockNetd).networkCreate(
nativeNetworkConfigPhysical(workAgent.getNetwork().netId,
INetd.PERMISSION_SYSTEM));
}
}
profileDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(workAgent);
@@ -15127,8 +15178,6 @@ public class ConnectivityServiceTest {
}
mSystemDefaultNetworkCallback.assertNoCallback();
mDefaultNetworkCallback.assertNoCallback();
inOrder.verify(mMockNetd).networkCreate(
nativeNetworkConfigPhysical(workAgent.getNetwork().netId, INetd.PERMISSION_SYSTEM));
inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
workAgent.getNetwork().netId,
uidRangeFor(testHandle, profileNetworkPreference),
@@ -17647,6 +17696,22 @@ public class ConnectivityServiceTest {
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
public void testSendLinkPropertiesSetInterfaceMtuBeforeConnect() throws Exception {
final int mtu = 1281;
@@ -17661,8 +17726,8 @@ public class ConnectivityServiceTest {
reset(mMockNetd);
mWiFiAgent.connect(false /* validated */);
// The MTU is always (re-)applied when the network connects.
verifyMtuSetOnWifiInterface(mtu);
// Before U, the MTU is always (re-)applied when the network connects.
verifyMtuSetOnWifiInterfaceOnlyUpToT(mtu);
}
@Test
@@ -17672,13 +17737,13 @@ public class ConnectivityServiceTest {
lp.setInterfaceName(WIFI_IFNAME);
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);
waitForIdle();
verifyMtuNeverSetOnWifiInterface();
verifyMtuSetOnWifiInterfaceOnlyStartingFromU(mtu);
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);
waitForIdle();
verifyMtuNeverSetOnWifiInterface();
@@ -17691,8 +17756,8 @@ public class ConnectivityServiceTest {
reset(mMockNetd);
mWiFiAgent.connect(false /* validated */);
// The MTU is always (re-)applied when the network connects.
verifyMtuSetOnWifiInterface(mtu + 1);
// Before U, the MTU is always (re-)applied when the network connects.
verifyMtuSetOnWifiInterfaceOnlyUpToT(mtu + 1);
}
@Test