Support Wifi P2P Group Owner local network agent

Flag: EXEMPT Flagged by DeviceCongfig wifip2pgo_local_network_agent
Test: atest ConnectivityCoverageTests:android.net.ip.IpServerTest \
      --update-device
Test: atest TetheringIntegrationTests:android.net.EthernetTetheringTest \
      --update-device
Bug: 406172997
Change-Id: I709082c05b576c17fd2823e687d63028b9b8a309
This commit is contained in:
Junyu Lai 2025-03-25 18:08:19 +08:00
commit 6c6128081f
4 changed files with 64 additions and 12 deletions

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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);