diff --git a/Tethering/src/android/net/ip/IpServer.java b/Tethering/src/android/net/ip/IpServer.java index a651b1b198..baaaef5092 100644 --- a/Tethering/src/android/net/ip/IpServer.java +++ b/Tethering/src/android/net/ip/IpServer.java @@ -43,6 +43,7 @@ import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH import static com.android.net.module.util.NetworkStackConstants.RFC7421_PREFIX_LENGTH; import static com.android.networkstack.tethering.TetheringConfiguration.TETHERING_LOCAL_NETWORK_AGENT; import static com.android.networkstack.tethering.TetheringConfiguration.USE_SYNC_SM; +import static com.android.networkstack.tethering.TetheringConfiguration.WIFIP2PGO_LOCAL_NETWORK_AGENT; import static com.android.networkstack.tethering.util.PrefixUtils.asIpPrefix; import static com.android.networkstack.tethering.util.TetheringMessageBase.BASE_IPSERVER; import static com.android.networkstack.tethering.util.TetheringUtils.getTransportTypeForTetherableType; @@ -334,7 +335,8 @@ public class IpServer extends StateMachineShim { private final Handler mHandler; private final Context mContext; - private final boolean mSupportLocalAgent; + private final boolean mSupportTetheringLocalAgent; + private final boolean mSupportWifiP2pGroupOwnerLocalAgent; // This will be null if the TetheredState is not entered or feature not supported. // This will be only accessed from the IpServer handler thread. @@ -380,8 +382,10 @@ public class IpServer extends StateMachineShim { mServingMode = STATE_AVAILABLE; // Tethering network agent is supported on V+, and will be rolled out gradually. - mSupportLocalAgent = SdkLevel.isAtLeastV() + mSupportTetheringLocalAgent = SdkLevel.isAtLeastV() && mDeps.isFeatureEnabled(mContext, TETHERING_LOCAL_NETWORK_AGENT); + mSupportWifiP2pGroupOwnerLocalAgent = mSupportTetheringLocalAgent + && mDeps.isFeatureEnabled(mContext, WIFIP2PGO_LOCAL_NETWORK_AGENT); mInitialState = new InitialState(); mLocalHotspotState = new LocalHotspotState(); @@ -1162,9 +1166,8 @@ public class IpServer extends StateMachineShim { @SuppressLint("NewApi") private void startServingInterface() { - // TODO: Enable Network Agent for Wifi P2P Group Owner mode when Network Agent - // for Group Client mode is supported. - if (mSupportLocalAgent && getScope() == CONNECTIVITY_SCOPE_GLOBAL) { + if (mSupportTetheringLocalAgent && (mSupportWifiP2pGroupOwnerLocalAgent + || getScope() != CONNECTIVITY_SCOPE_LOCAL)) { try { mTetheringAgent = mDeps.makeNetworkAgent(mContext, Looper.myLooper(), TAG, mInterfaceType, mLinkProperties); diff --git a/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java b/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java index e2609e7d2f..bac2a7dead 100644 --- a/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java +++ b/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java @@ -154,6 +154,13 @@ public class TetheringConfiguration { */ public static final String TETHERING_LOCAL_NETWORK_AGENT = "tethering_local_network_agent"; + /** + * A feature flag to control whether the Wifi P2P Group Owner local network agent + * should be enabled. Disabled by default. This depends on TETHERING_LOCAL_AGENT + * and will not be enabled if that flag is off. + */ + public static final String WIFIP2PGO_LOCAL_NETWORK_AGENT = "wifip2pgo_local_network_agent"; + public final String[] tetherableUsbRegexs; public final String[] tetherableWifiRegexs; public final String[] tetherableWigigRegexs; diff --git a/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java index d47f4b3294..a2bf3a6c99 100644 --- a/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java +++ b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java @@ -219,6 +219,7 @@ public class EthernetTetheringTest extends EthernetTetheringTestBase { // Shamelessly copied from TetheringConfiguration. private static final String TETHERING_LOCAL_NETWORK_AGENT = "tethering_local_network_agent"; + private static final String WIFIP2PGO_LOCAL_NETWORK_AGENT = "wifip2pgo_local_network_agent"; @After public void tearDown() throws Exception { @@ -1245,15 +1246,29 @@ public class EthernetTetheringTest extends EthernetTetheringTestBase { } } + private void assumeMatchNonThreadLocalNetworksEnabled() { + assumeTrue(runAsShell(READ_COMPAT_CHANGE_CONFIG, LOG_COMPAT_CHANGE, + () -> CompatChanges.isChangeEnabled(ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS))); + } + @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) @Test - public void testLocalAgent_networkCallbacks() throws Exception { - final boolean isMatchNonThreadLocalNetworksEnabled = runAsShell( - READ_COMPAT_CHANGE_CONFIG, LOG_COMPAT_CHANGE, - () -> CompatChanges.isChangeEnabled(ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS)); - assumeTrue(isMatchNonThreadLocalNetworksEnabled); - + public void testTetheringLocalAgent_networkCallbacks() throws Exception { + assumeMatchNonThreadLocalNetworksEnabled(); mDeviceConfigRule.setConfig(NAMESPACE_TETHERING, TETHERING_LOCAL_NETWORK_AGENT, "1"); + doTestLocalAgent_networkCallbacks(CONNECTIVITY_SCOPE_GLOBAL); + } + + @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) + @Test + public void testWifiP2pGroupOwnerLocalAgent_networkCallbacks() throws Exception { + assumeMatchNonThreadLocalNetworksEnabled(); + mDeviceConfigRule.setConfig(NAMESPACE_TETHERING, TETHERING_LOCAL_NETWORK_AGENT, "1"); + mDeviceConfigRule.setConfig(NAMESPACE_TETHERING, WIFIP2PGO_LOCAL_NETWORK_AGENT, "1"); + doTestLocalAgent_networkCallbacks(CONNECTIVITY_SCOPE_LOCAL); + } + + private void doTestLocalAgent_networkCallbacks(int scope) throws Exception { assumeFalse(isInterfaceForTetheringAvailable()); setIncludeTestInterfaces(true); @@ -1273,9 +1288,13 @@ public class EthernetTetheringTest extends EthernetTetheringTestBase { downstreamIface.getInterfaceName(), iface); final TetheringRequest request = new TetheringRequest.Builder(TETHERING_ETHERNET) - .setConnectivityScope(CONNECTIVITY_SCOPE_GLOBAL).build(); + .setConnectivityScope(scope).build(); tetheringEventCallback = enableTethering(iface, request, null /* any upstream */); - tetheringEventCallback.awaitInterfaceTethered(); + if (scope == CONNECTIVITY_SCOPE_GLOBAL) { + tetheringEventCallback.awaitInterfaceTethered(); + } else { + tetheringEventCallback.awaitInterfaceLocalOnly(); + } // Verify NetworkCallback works accordingly. final Network network = networkCallback.expect(CallbackEntry.AVAILABLE).getNetwork(); @@ -1284,6 +1303,15 @@ public class EthernetTetheringTest extends EthernetTetheringTestBase { assertEquals(network, capEvent.getNetwork()); assertTrue(capEvent.getCaps().hasTransport(TRANSPORT_ETHERNET)); assertTrue(capEvent.getCaps().hasCapability(NET_CAPABILITY_LOCAL_NETWORK)); + + // Verify details in the LinkPropertiesChanged event. + final CallbackEntry.LinkPropertiesChanged lpEvent = + networkCallback.eventuallyExpect(CallbackEntry.LINK_PROPERTIES_CHANGED); + assertEquals(network, lpEvent.getNetwork()); + assertEquals(iface, lpEvent.getLp().getInterfaceName()); + assertTrue(lpEvent.getLp().hasIPv4Address()); + // At least one Ipv4 route for the subnet is needed. + assertTrue(lpEvent.getLp().getRoutes().size() >= 1); } finally { stopEthernetTethering(tetheringEventCallback); maybeCloseTestInterface(downstreamIface); diff --git a/Tethering/tests/unit/src/android/net/ip/IpServerTest.java b/Tethering/tests/unit/src/android/net/ip/IpServerTest.java index dc90d686f0..89fa34c60c 100644 --- a/Tethering/tests/unit/src/android/net/ip/IpServerTest.java +++ b/Tethering/tests/unit/src/android/net/ip/IpServerTest.java @@ -41,6 +41,7 @@ import static com.android.modules.utils.build.SdkLevel.isAtLeastT; import static com.android.modules.utils.build.SdkLevel.isAtLeastV; import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH; import static com.android.networkstack.tethering.TetheringConfiguration.TETHERING_LOCAL_NETWORK_AGENT; +import static com.android.networkstack.tethering.TetheringConfiguration.WIFIP2PGO_LOCAL_NETWORK_AGENT; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -1123,20 +1124,33 @@ public class IpServerTest { @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) @SetFeatureFlagsRule.FeatureFlag(name = TETHERING_LOCAL_NETWORK_AGENT, enabled = false) + @SetFeatureFlagsRule.FeatureFlag(name = WIFIP2PGO_LOCAL_NETWORK_AGENT) @Test public void testTetheringNetworkAgent_tetheringAgentDisabled() throws Exception { doTestTetheringNetworkAgent(CONNECTIVITY_SCOPE_GLOBAL, false); + // Even if the flag is enabled, no wifip2p network agent if the tethering network + // agent feature is not supported. + doTestTetheringNetworkAgent(CONNECTIVITY_SCOPE_LOCAL, false); } // Verify Tethering Network Agent feature doesn't affect Wi-fi P2P Group Owner although // the code is mostly shared. @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) @SetFeatureFlagsRule.FeatureFlag(name = TETHERING_LOCAL_NETWORK_AGENT) + @SetFeatureFlagsRule.FeatureFlag(name = WIFIP2PGO_LOCAL_NETWORK_AGENT, enabled = false) @Test public void testTetheringNetworkAgent_p2pGroupOwnerAgentDisabled() throws Exception { doTestTetheringNetworkAgent(CONNECTIVITY_SCOPE_LOCAL, false); } + @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) + @SetFeatureFlagsRule.FeatureFlag(name = TETHERING_LOCAL_NETWORK_AGENT) + @SetFeatureFlagsRule.FeatureFlag(name = WIFIP2PGO_LOCAL_NETWORK_AGENT) + @Test + public void testTetheringNetworkAgent_p2pGroupOwnerAgentEnabled() throws Exception { + doTestTetheringNetworkAgent(CONNECTIVITY_SCOPE_LOCAL, true); + } + private void doTestTetheringNetworkAgent(int scope, boolean expectAgentEnabled) throws Exception { initStateMachine(TETHERING_USB);