Make sure tests know to handle both early creation true and false

This is necessary to pass tests whatever the values of the features are.

NetworkAgentTest was updated assuming the feature was true, so
this patch revives the old code for when it's false.

TestableNetworkAgent reads the feature directly from
ConnectivityManager when it's not mocked.

Test: CtsNetTestCases
Change-Id: Ia556fbb1d1b6a38a4995b021981e2693d778bfff
diff --git a/staticlibs/testutils/devicetests/com/android/testutils/TestableNetworkAgent.kt b/staticlibs/testutils/devicetests/com/android/testutils/TestableNetworkAgent.kt
index 0413ed4..f5f2e69 100644
--- a/staticlibs/testutils/devicetests/com/android/testutils/TestableNetworkAgent.kt
+++ b/staticlibs/testutils/devicetests/com/android/testutils/TestableNetworkAgent.kt
@@ -17,6 +17,7 @@
 package com.android.testutils
 
 import android.content.Context
+import android.net.ConnectivityManager
 import android.net.ConnectivityManager.FEATURE_QUEUE_NETWORK_AGENT_EVENTS_IN_SYSTEM_SERVER
 import android.net.InetAddresses.parseNumericAddress
 import android.net.KeepalivePacketData
@@ -77,9 +78,7 @@
 private class Provider(context: Context, looper: Looper) :
             NetworkProvider(context, looper, "NetworkAgentTest NetworkProvider")
 
-private val enabledFeatures = mutableMapOf(
-    FEATURE_QUEUE_NETWORK_AGENT_EVENTS_IN_SYSTEM_SERVER to true
-)
+private val enabledFeatures = mutableMapOf<Long, Boolean>()
 
 public open class TestableNetworkAgent(
     context: Context,
@@ -92,7 +91,12 @@
 
     override fun isFeatureEnabled(context: Context, feature: Long): Boolean {
         when (val it = enabledFeatures.get(feature)) {
-            null -> fail("Unmocked feature $feature, see TestableNetworkAgent.enabledFeatures")
+            null -> {
+                val cm = context.getSystemService(ConnectivityManager::class.java)
+                val res = cm.isFeatureEnabled(feature)
+                enabledFeatures[feature] = res
+                return res
+            }
             else -> return it
         }
     }
diff --git a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
index 4c3bce0..8f2ac7f 100644
--- a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
+++ b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
@@ -1015,6 +1015,12 @@
             mock(Network::class.java),
             mock(INetworkAgentRegistry::class.java)
         )
+        doReturn(SHOULD_CREATE_NETWORKS_IMMEDIATELY).`when`(mockCm)
+            .isFeatureEnabled(
+                eq(ConnectivityManager.FEATURE_QUEUE_NETWORK_AGENT_EVENTS_IN_SYSTEM_SERVER)
+            )
+        doReturn(Context.CONNECTIVITY_SERVICE).`when`(mockContext)
+            .getSystemServiceName(ConnectivityManager::class.java)
         doReturn(mockCm).`when`(mockContext).getSystemService(Context.CONNECTIVITY_SERVICE)
         doReturn(mockedResult).`when`(mockCm).registerNetworkAgent(
             any(),
@@ -1673,14 +1679,22 @@
         // The fact that the first event seen by matchAllCallback is the connection of network3
         // implicitly ensures that no callbacks are sent since network1 was lost.
         val (agent3, network3) = connectNetwork(lp = lp)
-
-        // As soon as the replacement arrives, network1 is disconnected.
-        // Check that this happens before the replacement timeout (5 seconds) fires.
-        matchAllCallback.expectAvailableCallbacks(network3, validated = false)
-        matchAllCallback.expect<Lost>(network1, 2_000 /* timeoutMs */)
-        matchAllCallback.expectCaps(network3) { it.hasCapability(NET_CAPABILITY_VALIDATED) }
-        sendAndExpectUdpPacket(network3, reader, iface)
-        testCallback.expectAvailableDoubleValidatedCallbacks(network3)
+        if (SHOULD_CREATE_NETWORKS_IMMEDIATELY) {
+            // This is the correct sequence of events.
+            matchAllCallback.expectAvailableCallbacks(network3, validated = false)
+            matchAllCallback.expect<Lost>(network1, 2_000 /* timeoutMs */)
+            matchAllCallback.expectCaps(network3) { it.hasCapability(NET_CAPABILITY_VALIDATED) }
+            sendAndExpectUdpPacket(network3, reader, iface)
+            testCallback.expectAvailableDoubleValidatedCallbacks(network3)
+        } else {
+            // This is incorrect and fixed by the "create networks immediately" feature
+            matchAllCallback.expectAvailableThenValidatedCallbacks(network3)
+            testCallback.expectAvailableDoubleValidatedCallbacks(network3)
+            sendAndExpectUdpPacket(network3, reader, iface)
+            // As soon as the replacement arrives, network1 is disconnected.
+            // Check that this happens before the replacement timeout (5 seconds) fires.
+            matchAllCallback.expect<Lost>(network1, 2_000 /* timeoutMs */)
+        }
         agent1.expectCallback<OnNetworkUnwanted>()
 
         // Test lingering:
@@ -1798,9 +1812,19 @@
 
         val (newWifiAgent, newWifiNetwork) = connectNetwork(TRANSPORT_WIFI)
         testCallback.expectAvailableCallbacks(newWifiNetwork, validated = true)
-        matchAllCallback.expectAvailableCallbacks(newWifiNetwork, validated = false)
-        matchAllCallback.expect<Lost>(wifiNetwork)
-        matchAllCallback.expectCaps(newWifiNetwork) { it.hasCapability(NET_CAPABILITY_VALIDATED) }
+        if (SHOULD_CREATE_NETWORKS_IMMEDIATELY) {
+            // This is the correct sequence of events
+            matchAllCallback.expectAvailableCallbacks(newWifiNetwork, validated = false)
+            matchAllCallback.expect<Lost>(wifiNetwork)
+            matchAllCallback.expectCaps(newWifiNetwork) {
+                it.hasCapability(NET_CAPABILITY_VALIDATED)
+            }
+        } else {
+            // When networks are not created immediately, the sequence is slightly incorrect
+            // and instead is as follows
+            matchAllCallback.expectAvailableThenValidatedCallbacks(newWifiNetwork)
+            matchAllCallback.expect<Lost>(wifiNetwork)
+        }
         wifiAgent.expectCallback<OnNetworkUnwanted>()
         testCallback.expect<CapabilitiesChanged>(newWifiNetwork)
 
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index 35a7fbd..67cb1a4 100755
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -586,6 +586,10 @@
             "https://android.com/user/api/capport/";
     private static final String TEST_FRIENDLY_NAME = "Network friendly name";
     private static final String TEST_REDIRECT_URL = "http://example.com/firstPath";
+    private static final String QUEUE_NETWORK_AGENT_EVENTS_IN_SYSTEM_SERVER =
+            "queue_network_agent_events_in_system_server";
+
+    private boolean mShouldCreateNetworksImmediately;
 
     private MockContext mServiceContext;
     private HandlerThread mCsHandlerThread;
@@ -1935,6 +1939,9 @@
         mService.mLingerDelayMs = TEST_LINGER_DELAY_MS;
         mService.mNascentDelayMs = TEST_NASCENT_DELAY_MS;
 
+        mShouldCreateNetworksImmediately = mService.isConnectivityServiceFeatureEnabledForTesting(
+                QUEUE_NETWORK_AGENT_EVENTS_IN_SYSTEM_SERVER);
+
         if (mDeps.isAtLeastV()) {
             verify(mNetworkPolicyManager, never()).registerNetworkPolicyCallback(any(), any());
             mPolicyCallback = null;
@@ -3092,23 +3099,43 @@
         generalCb.expectAvailableCallbacksUnvalidated(net2);
         if (expectLingering) {
             generalCb.expectLosing(net1);
+        }
+        if (mShouldCreateNetworksImmediately) {
+            if (expectLingering) {
+                // Make sure cell 1 is unwanted immediately if the radio can't time share, but only
+                // after some delay if it can.
+                generalCb.expectCaps(net2, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
+                defaultCb.expectAvailableDoubleValidatedCallbacks(net2);
+                net1.assertNotDisconnected(TEST_CALLBACK_TIMEOUT_MS); // always incurs the timeout
+                generalCb.assertNoCallback();
+                // assertNotDisconnected waited for TEST_CALLBACK_TIMEOUT_MS, so waiting for the
+                // linger period gives TEST_CALLBACK_TIMEOUT_MS time for the event to process.
+                net1.expectDisconnected(UNREASONABLY_LONG_ALARM_WAIT_MS);
+                generalCb.expect(LOST, net1);
+            } else {
+                net1.expectDisconnected(TEST_CALLBACK_TIMEOUT_MS);
+                net1.disconnect();
+                generalCb.expect(LOST, net1);
+                generalCb.expectCaps(net2, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
+                defaultCb.expectAvailableDoubleValidatedCallbacks(net2);
+            }
+        } else {
+            generalCb.expectCaps(net2, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
+            defaultCb.expectAvailableDoubleValidatedCallbacks(net2);
 
             // Make sure cell 1 is unwanted immediately if the radio can't time share, but only
             // after some delay if it can.
-            generalCb.expectCaps(net2, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
-            defaultCb.expectAvailableDoubleValidatedCallbacks(net2);
-            net1.assertNotDisconnected(TEST_CALLBACK_TIMEOUT_MS); // always incurs the timeout
-            generalCb.assertNoCallback();
-            // assertNotDisconnected waited for TEST_CALLBACK_TIMEOUT_MS, so waiting for the
-            // linger period gives TEST_CALLBACK_TIMEOUT_MS time for the event to process.
-            net1.expectDisconnected(UNREASONABLY_LONG_ALARM_WAIT_MS);
-            generalCb.expect(LOST, net1);
-        } else {
-            net1.expectDisconnected(TEST_CALLBACK_TIMEOUT_MS);
+            if (expectLingering) {
+                net1.assertNotDisconnected(TEST_CALLBACK_TIMEOUT_MS); // always incurs the timeout
+                generalCb.assertNoCallback();
+                // assertNotDisconnected waited for TEST_CALLBACK_TIMEOUT_MS, so waiting for the
+                // linger period gives TEST_CALLBACK_TIMEOUT_MS time for the event to process.
+                net1.expectDisconnected(UNREASONABLY_LONG_ALARM_WAIT_MS);
+            } else {
+                net1.expectDisconnected(TEST_CALLBACK_TIMEOUT_MS);
+            }
             net1.disconnect();
             generalCb.expect(LOST, net1);
-            generalCb.expectCaps(net2, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
-            defaultCb.expectAvailableDoubleValidatedCallbacks(net2);
         }
 
         // Remove primary from net 2