Add integration test of tethering local network agent feature

Test: atest TetheringIntegrationTests:android.net.EthernetTetheringTest#testLocalAgent_networkCallbacks \
      --update-device
Bug: 349487600
Change-Id: I3a173f7441a766c33844f89c13ef3cc7930167f1
diff --git a/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
index 3a5728e..11442ed 100644
--- a/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
+++ b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
@@ -18,6 +18,8 @@
 
 import static android.Manifest.permission.DUMP;
 import static android.net.InetAddresses.parseNumericAddress;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK;
+import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
 import static android.net.TetheringManager.CONNECTIVITY_SCOPE_LOCAL;
 import static android.net.TetheringManager.CONNECTIVITY_SCOPE_GLOBAL;
 import static android.net.TetheringManager.TETHERING_ETHERNET;
@@ -27,6 +29,7 @@
 import static android.net.TetheringTester.buildUdpPacket;
 import static android.net.TetheringTester.isExpectedIcmpPacket;
 import static android.net.TetheringTester.isExpectedUdpDnsPacket;
+import static android.provider.DeviceConfig.NAMESPACE_TETHERING;
 import static android.system.OsConstants.ICMP_ECHO;
 import static android.system.OsConstants.ICMP_ECHOREPLY;
 import static android.system.OsConstants.IPPROTO_UDP;
@@ -78,12 +81,16 @@
 import com.android.net.module.util.bpf.TetherStatsValue;
 import com.android.net.module.util.structs.Ipv4Header;
 import com.android.net.module.util.structs.UdpHeader;
+import com.android.testutils.AutoReleaseNetworkCallbackRule;
 import com.android.testutils.DevSdkIgnoreRule;
 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
+import com.android.testutils.DeviceConfigRule;
 import com.android.testutils.DeviceInfoUtils;
 import com.android.testutils.DumpTestUtils;
 import com.android.testutils.NetworkStackModuleTest;
 import com.android.testutils.PollPacketReader;
+import com.android.testutils.RecorderCallback.CallbackEntry;
+import com.android.testutils.TestableNetworkCallback;
 
 import org.junit.After;
 import org.junit.Rule;
@@ -111,6 +118,12 @@
 public class EthernetTetheringTest extends EthernetTetheringTestBase {
     @Rule
     public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule();
+    // For manipulating feature flag before and after testing.
+    @Rule
+    public final DeviceConfigRule mDeviceConfigRule = new DeviceConfigRule();
+    @Rule
+    public final AutoReleaseNetworkCallbackRule
+            mNetworkCallbackRule = new AutoReleaseNetworkCallbackRule();
 
     private static final String TAG = EthernetTetheringTest.class.getSimpleName();
 
@@ -200,6 +213,9 @@
             (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04  /* Address: 1.2.3.4 */
     };
 
+    // Shamelessly copied from TetheringConfiguration.
+    private static final String TETHERING_LOCAL_NETWORK_AGENT = "tethering_local_network_agent";
+
     @After
     public void tearDown() throws Exception {
         super.tearDown();
@@ -1224,4 +1240,44 @@
             maybeUnregisterTetheringEventCallback(tetheringEventCallback);
         }
     }
+
+    @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+    @Test
+    public void testLocalAgent_networkCallbacks() throws Exception {
+        mDeviceConfigRule.setConfig(NAMESPACE_TETHERING, TETHERING_LOCAL_NETWORK_AGENT, "1");
+        assumeFalse(isInterfaceForTetheringAvailable());
+        setIncludeTestInterfaces(true);
+
+        TestNetworkInterface downstreamIface = null;
+        MyTetheringEventCallback tetheringEventCallback = null;
+
+        final TestableNetworkCallback networkCallback = new TestableNetworkCallback();
+        final NetworkRequest networkRequest = new NetworkRequest.Builder()
+                .addCapability(NET_CAPABILITY_LOCAL_NETWORK).build();
+        mNetworkCallbackRule.registerNetworkCallback(networkRequest, networkCallback);
+
+        try {
+            downstreamIface = createTestInterface();
+
+            final String iface = mTetheredInterfaceRequester.getInterface();
+            assertEquals("TetheredInterfaceCallback for unexpected interface",
+                    downstreamIface.getInterfaceName(), iface);
+
+            final TetheringRequest request = new TetheringRequest.Builder(TETHERING_ETHERNET)
+                    .setConnectivityScope(CONNECTIVITY_SCOPE_GLOBAL).build();
+            tetheringEventCallback = enableTethering(iface, request, null /* any upstream */);
+            tetheringEventCallback.awaitInterfaceTethered();
+
+            // Verify NetworkCallback works accordingly.
+            final Network network = networkCallback.expect(CallbackEntry.AVAILABLE).getNetwork();
+            final CallbackEntry.CapabilitiesChanged capEvent =
+                    networkCallback.eventuallyExpect(CallbackEntry.NETWORK_CAPS_UPDATED);
+            assertEquals(network, capEvent.getNetwork());
+            assertTrue(capEvent.getCaps().hasTransport(TRANSPORT_ETHERNET));
+            assertTrue(capEvent.getCaps().hasCapability(NET_CAPABILITY_LOCAL_NETWORK));
+        } finally {
+            stopEthernetTethering(tetheringEventCallback);
+            maybeCloseTestInterface(downstreamIface);
+        }
+    }
 }