From dc420ccccbd01e9d0ed5a1bc89866c6c76ab539c Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Tue, 12 Aug 2025 16:34:56 +0800 Subject: [PATCH 1/2] Adopt mainline beta program for local network agent Unifies the `TETHERING_LOCAL_NETWORK_AGENT` and `WIFIP2PGO_LOCAL_NETWORK_AGENT` legacy feature flags into a single mainline beta aconfig flag: `tethering_and_p2p_go_local_network_agent`. This change simplifies the logic for enabling the `NetworkAgent` for both standard tethering (global scope) and Wi-Fi P2P Group Owner mode (local scope). The agent is now enabled for both use cases when the new flag is on. The implementation in `IpServer` and associated tests have been updated to use the new unified flag. Flag: com.android.tethering.mainline.beta.tethering_and_p2p_go_local_agent Bug: 420590461 Test: atest TetheringTests Test: adb root adb shell device_config put com_android_tethering com.android.tethering.mainline.beta.tethering_and_p2p_go_local_agent true adb reboot atest CtsTetheringTest --test-filter '.*Agent.*' Test: atest ConnectivityCoverageTests:android.net.ip.IpServerTest --update-device Change-Id: I55817132c57a04b4f7b7bac61b5741f45ba16182 --- Tethering/Android.bp | 1 + Tethering/src/android/net/ip/IpServer.java | 27 +++++------- .../tethering/TetheringFeatureFlags.java | 13 ------ Tethering/tests/integration/Android.bp | 1 + .../android/net/EthernetTetheringTest.java | 18 +++----- .../unit/src/android/net/ip/IpServerTest.java | 44 +++++-------------- .../networkstack/tethering/TetheringTest.java | 9 ++-- common/mainline_beta.aconfig | 7 +++ .../tethering/cts/TetheringWifiP2pTest.kt | 22 +++------- 9 files changed, 49 insertions(+), 93 deletions(-) diff --git a/Tethering/Android.bp b/Tethering/Android.bp index 2a39028318..ad6b28c36a 100644 --- a/Tethering/Android.bp +++ b/Tethering/Android.bp @@ -66,6 +66,7 @@ java_defaults { "connectivity-net-module-utils-bpf", "com.android.net.flags-aconfig-java", "com.android.tethering.beta.test.flags-aconfig-java", + "com.android.tethering.mainline.beta.flags-aconfig-java", "modules-utils-build", "modules-utils-statemachine", "networkstack-client", diff --git a/Tethering/src/android/net/ip/IpServer.java b/Tethering/src/android/net/ip/IpServer.java index f51610344c..efb1017c16 100644 --- a/Tethering/src/android/net/ip/IpServer.java +++ b/Tethering/src/android/net/ip/IpServer.java @@ -42,8 +42,6 @@ import static android.system.OsConstants.RT_SCOPE_UNIVERSE; 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.USE_SYNC_SM; -import static com.android.networkstack.tethering.TetheringFeatureFlags.TETHERING_LOCAL_NETWORK_AGENT; -import static com.android.networkstack.tethering.TetheringFeatureFlags.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; @@ -86,7 +84,6 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.MessageUtils; import com.android.internal.util.State; import com.android.modules.utils.build.SdkLevel; -import com.android.net.module.util.DeviceConfigUtils; import com.android.net.module.util.IIpv4PrefixRequest; import com.android.net.module.util.InterfaceParams; import com.android.net.module.util.NetdUtils; @@ -100,6 +97,7 @@ import com.android.networkstack.tethering.metrics.TetheringMetrics; import com.android.networkstack.tethering.util.InterfaceSet; import com.android.networkstack.tethering.util.PrefixUtils; import com.android.networkstack.tethering.util.StateMachineShim; +import com.android.tethering.mainline.beta.Flags; import java.net.Inet4Address; import java.net.Inet6Address; @@ -217,11 +215,9 @@ public class IpServer extends StateMachineShim { public abstract void makeDhcpServer(String ifName, DhcpServingParamsParcel params, DhcpServerCallbacks cb); - /** - * @see DeviceConfigUtils#isTetheringFeatureEnabled - */ - public boolean isFeatureEnabled(Context context, String name) { - return DeviceConfigUtils.isTetheringFeatureEnabled(context, name); + /** Get whether TETHERING_AND_P2P_GO_LOCAL_AGENT feature is enabled. */ + public boolean isTetheringAndP2pGoLocalAgentEnabled() { + return Flags.tetheringAndP2pGoLocalAgent(); } /** Create a NetworkAgent instance to be used by IpServer. */ @@ -335,8 +331,8 @@ public class IpServer extends StateMachineShim { private final Handler mHandler; private final Context mContext; - private final boolean mSupportTetheringLocalAgent; - private final boolean mSupportWifiP2pGroupOwnerLocalAgent; + // Whether to enable tethering and Wi-Fi P2p Group Owner mode local network agent. + private final boolean mSupportTetheringAndP2pGoLocalAgent; // This will be null if the TetheredState is not entered or feature not supported. // This will be only accessed from the IpServer handler thread. @@ -381,11 +377,9 @@ public class IpServer extends StateMachineShim { mLastError = TETHER_ERROR_NO_ERROR; mServingMode = STATE_AVAILABLE; - // Tethering network agent is supported on V+, and will be rolled out gradually. - mSupportTetheringLocalAgent = SdkLevel.isAtLeastV() - && mDeps.isFeatureEnabled(mContext, TETHERING_LOCAL_NETWORK_AGENT); - mSupportWifiP2pGroupOwnerLocalAgent = mSupportTetheringLocalAgent - && mDeps.isFeatureEnabled(mContext, WIFIP2PGO_LOCAL_NETWORK_AGENT); + // Tethering network agent is supported on V+, and will be adopting mainline beta program. + mSupportTetheringAndP2pGoLocalAgent = SdkLevel.isAtLeastV() + && mDeps.isTetheringAndP2pGoLocalAgentEnabled(); mInitialState = new InitialState(); mLocalHotspotState = new LocalHotspotState(); @@ -1176,8 +1170,7 @@ public class IpServer extends StateMachineShim { @SuppressLint("NewApi") private void startServingInterface() { - if (mSupportTetheringLocalAgent && (mSupportWifiP2pGroupOwnerLocalAgent - || getScope() != CONNECTIVITY_SCOPE_LOCAL)) { + if (mSupportTetheringAndP2pGoLocalAgent) { try { mTetheringAgent = mDeps.makeNetworkAgent(mContext, Looper.myLooper(), TAG, mInterfaceType, mLinkProperties); diff --git a/Tethering/src/com/android/networkstack/tethering/TetheringFeatureFlags.java b/Tethering/src/com/android/networkstack/tethering/TetheringFeatureFlags.java index fd4aa510ea..9f450ca973 100644 --- a/Tethering/src/com/android/networkstack/tethering/TetheringFeatureFlags.java +++ b/Tethering/src/com/android/networkstack/tethering/TetheringFeatureFlags.java @@ -59,17 +59,4 @@ public class TetheringFeatureFlags { * Disabled by default. */ public static final String TETHER_ACTIVE_SESSIONS_METRICS = "tether_active_sessions_metrics"; - - /** - * A feature flag to control whether the tethering local network agent should be enabled. - * Disabled by default. - */ - 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"; } diff --git a/Tethering/tests/integration/Android.bp b/Tethering/tests/integration/Android.bp index 221154638b..51377bb792 100644 --- a/Tethering/tests/integration/Android.bp +++ b/Tethering/tests/integration/Android.bp @@ -28,6 +28,7 @@ java_defaults { static_libs: [ "DhcpPacketLib", "androidx.test.rules", + "com.android.tethering.mainline.beta.flags-aconfig-java", "cts-net-utils", "mockito-target-minus-junit4", "net-tests-utils", diff --git a/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java index 29f9376009..3dd9a212dc 100644 --- a/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java +++ b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java @@ -32,7 +32,6 @@ import static android.net.TetheringTester.buildUdpPacket; import static android.net.TetheringTester.isExpectedIcmpPacket; import static android.net.TetheringTester.isExpectedUdpDnsPacket; import static android.net.connectivity.ConnectivityCompatChanges.ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS; -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; @@ -63,6 +62,9 @@ import android.os.Build; import android.os.SystemClock; import android.os.SystemProperties; import android.os.VintfRuntimeInfo; +import android.platform.test.annotations.RequiresFlagsEnabled; +import android.platform.test.flag.junit.CheckFlagsRule; +import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.util.Log; import android.util.Pair; @@ -88,13 +90,13 @@ 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.TestableNetworkCallback; import com.android.testutils.TestableNetworkCallback.Event; +import com.android.tethering.mainline.beta.Flags; import org.junit.After; import org.junit.Rule; @@ -122,9 +124,8 @@ import java.util.concurrent.TimeoutException; 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(); + public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); @Rule public final AutoReleaseNetworkCallbackRule mNetworkCallbackRule = new AutoReleaseNetworkCallbackRule(); @@ -217,10 +218,6 @@ public class EthernetTetheringTest extends EthernetTetheringTestBase { (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"; - private static final String WIFIP2PGO_LOCAL_NETWORK_AGENT = "wifip2pgo_local_network_agent"; - @After public void tearDown() throws Exception { super.tearDown(); @@ -1252,19 +1249,18 @@ public class EthernetTetheringTest extends EthernetTetheringTestBase { } @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) + @RequiresFlagsEnabled(Flags.FLAG_TETHERING_AND_P2P_GO_LOCAL_AGENT) @Test 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) + @RequiresFlagsEnabled(Flags.FLAG_TETHERING_AND_P2P_GO_LOCAL_AGENT) @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); } diff --git a/Tethering/tests/unit/src/android/net/ip/IpServerTest.java b/Tethering/tests/unit/src/android/net/ip/IpServerTest.java index 370bc56e93..3a0a60ebfa 100644 --- a/Tethering/tests/unit/src/android/net/ip/IpServerTest.java +++ b/Tethering/tests/unit/src/android/net/ip/IpServerTest.java @@ -40,8 +40,6 @@ import static android.net.ip.IpServer.getTetherableIpv6Prefixes; 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.TetheringFeatureFlags.TETHERING_LOCAL_NETWORK_AGENT; -import static com.android.networkstack.tethering.TetheringFeatureFlags.WIFIP2PGO_LOCAL_NETWORK_AGENT; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -110,6 +108,8 @@ import com.android.testutils.DevSdkIgnoreRule; import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter; import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; import com.android.testutils.com.android.testutils.SetFeatureFlagsRule; +import com.android.testutils.com.android.testutils.SetFeatureFlagsRule.FeatureFlag; +import com.android.tethering.mainline.beta.Flags; import org.junit.Before; import org.junit.Rule; @@ -227,9 +227,8 @@ public class IpServerTest { when(mDependencies.getInterfaceParams(UPSTREAM_IFACE)).thenReturn(UPSTREAM_IFACE_PARAMS); when(mDependencies.getInterfaceParams(UPSTREAM_IFACE2)).thenReturn(UPSTREAM_IFACE_PARAMS2); when(mDependencies.getInterfaceParams(IPSEC_IFACE)).thenReturn(IPSEC_IFACE_PARAMS); - doAnswer( - invocation -> mFeatureFlags.getOrDefault((String) invocation.getArgument(1), false) - ).when(mDependencies).isFeatureEnabled(any(), anyString()); + doReturn(mFeatureFlags.getOrDefault(Flags.FLAG_TETHERING_AND_P2P_GO_LOCAL_AGENT, false)) + .when(mDependencies).isTetheringAndP2pGoLocalAgentEnabled(); if (isAtLeastV()) { when(mDependencies.makeNetworkAgent(any(), any(), anyString(), anyInt(), any())) .thenReturn(mNetworkAgent); @@ -376,7 +375,8 @@ public class IpServerTest { } private boolean isTetheringNetworkAgentFeatureEnabled() { - return isAtLeastV() && mFeatureFlags.getOrDefault(TETHERING_LOCAL_NETWORK_AGENT, false); + return isAtLeastV() && mFeatureFlags.getOrDefault( + Flags.FLAG_TETHERING_AND_P2P_GO_LOCAL_AGENT, false); } @Test @@ -1115,42 +1115,22 @@ public class IpServerTest { return true; } + @FeatureFlag(name = Flags.FLAG_TETHERING_AND_P2P_GO_LOCAL_AGENT) @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) - @SetFeatureFlagsRule.FeatureFlag(name = TETHERING_LOCAL_NETWORK_AGENT) @Test public void testTetheringNetworkAgent_tetheringAgentEnabled() throws Exception { doTestTetheringNetworkAgent(CONNECTIVITY_SCOPE_GLOBAL, true); + doTestTetheringNetworkAgent(CONNECTIVITY_SCOPE_LOCAL, true); } + @FeatureFlag(name = Flags.FLAG_TETHERING_AND_P2P_GO_LOCAL_AGENT, enabled = false) @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); @@ -1184,8 +1164,8 @@ public class IpServerTest { } // Verify if the registration failed, tethering can be gracefully shutdown. + @FeatureFlag(name = Flags.FLAG_TETHERING_AND_P2P_GO_LOCAL_AGENT) @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) - @SetFeatureFlagsRule.FeatureFlag(name = TETHERING_LOCAL_NETWORK_AGENT) @Test public void testTetheringNetworkAgent_registerThrows() throws Exception { initStateMachine(TETHERING_USB); @@ -1207,8 +1187,8 @@ public class IpServerTest { } // Verify if the network creation failed, tethering can be gracefully shutdown. + @FeatureFlag(name = Flags.FLAG_TETHERING_AND_P2P_GO_LOCAL_AGENT) @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) - @SetFeatureFlagsRule.FeatureFlag(name = TETHERING_LOCAL_NETWORK_AGENT) @Test public void testTetheringNetworkAgent_netdThrows() throws Exception { initStateMachine(TETHERING_USB); @@ -1229,8 +1209,8 @@ public class IpServerTest { } // Verify when IPv6 address update, set routes accordingly. + @FeatureFlag(name = Flags.FLAG_TETHERING_AND_P2P_GO_LOCAL_AGENT) @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) - @SetFeatureFlagsRule.FeatureFlag(name = TETHERING_LOCAL_NETWORK_AGENT) @Test public void testTetheringNetworkAgent_ipv6AddressUpdate() throws Exception { initStateMachine(TETHERING_USB); diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java index 224c66ab2b..504d626d70 100644 --- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java +++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java @@ -88,7 +88,6 @@ import static com.android.networkstack.tethering.Tethering.UserRestrictionAction import static com.android.networkstack.tethering.TetheringConfiguration.TETHER_FORCE_USB_FUNCTIONS; import static com.android.networkstack.tethering.TetheringConfiguration.TETHER_USB_NCM_FUNCTION; import static com.android.networkstack.tethering.TetheringConfiguration.TETHER_USB_RNDIS_FUNCTION; -import static com.android.networkstack.tethering.TetheringFeatureFlags.TETHERING_LOCAL_NETWORK_AGENT; import static com.android.networkstack.tethering.TetheringNotificationUpdater.DOWNSTREAM_NONE; import static com.android.networkstack.tethering.UpstreamNetworkMonitor.EVENT_ON_CAPABILITIES; import static com.android.testutils.TestPermissionUtil.runAsShell; @@ -224,6 +223,7 @@ import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter; import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; import com.android.testutils.MiscAsserts; import com.android.testutils.com.android.testutils.SetFeatureFlagsRule; +import com.android.tethering.mainline.beta.Flags; import org.junit.After; import org.junit.Before; @@ -479,8 +479,8 @@ public class TetheringTest { } @Override - public boolean isFeatureEnabled(Context context, String name) { - return mFeatureFlags.getOrDefault(name, false); + public boolean isTetheringAndP2pGoLocalAgentEnabled() { + return mFeatureFlags.getOrDefault(Flags.FLAG_TETHERING_AND_P2P_GO_LOCAL_AGENT, false); } } @@ -1078,7 +1078,8 @@ public class TetheringTest { } private boolean isTetheringNetworkAgentFeatureEnabled() { - return isAtLeastV() && mFeatureFlags.getOrDefault(TETHERING_LOCAL_NETWORK_AGENT, false); + return isAtLeastV() && mFeatureFlags.getOrDefault( + Flags.FLAG_TETHERING_AND_P2P_GO_LOCAL_AGENT, false); } private void verifyStopHotpot(boolean isLocalOnly) throws Exception { diff --git a/common/mainline_beta.aconfig b/common/mainline_beta.aconfig index d88a373ccb..4d493a5398 100644 --- a/common/mainline_beta.aconfig +++ b/common/mainline_beta.aconfig @@ -21,3 +21,10 @@ flag { description: "The flag enables the developer opt-in for LNP." bug: "421952907" } + +flag { + name: "tethering_and_p2p_go_local_agent" + namespace: "com_android_tethering" + description: "The flag enables the Tethering and WI-Fi P2p Group Owner mode local network agent." + bug: "420590461" +} diff --git a/tests/cts/tethering/src/android/tethering/cts/TetheringWifiP2pTest.kt b/tests/cts/tethering/src/android/tethering/cts/TetheringWifiP2pTest.kt index ac05a56f00..504db40707 100644 --- a/tests/cts/tethering/src/android/tethering/cts/TetheringWifiP2pTest.kt +++ b/tests/cts/tethering/src/android/tethering/cts/TetheringWifiP2pTest.kt @@ -27,7 +27,8 @@ import android.net.NetworkRequest import android.net.TetheringManager import android.net.connectivity.ConnectivityCompatChanges import android.os.Build -import android.provider.DeviceConfig +import android.platform.test.annotations.RequiresFlagsEnabled +import android.platform.test.flag.junit.DeviceFlagsValueProvider import android.text.TextUtils import androidx.test.platform.app.InstrumentationRegistry import com.android.testutils.AutoReleaseNetworkCallbackRule @@ -39,6 +40,7 @@ import com.android.testutils.TestableNetworkCallback.Event.Available import com.android.testutils.TestableNetworkCallback.Event.CapabilitiesChanged import com.android.testutils.TestableNetworkCallback.Event.LinkPropertiesChanged import com.android.testutils.runAsShell +import com.android.tethering.mainline.beta.Flags import com.google.snippet.connectivity.Wifip2pMultiDevicesSnippet import java.util.Random import org.junit.Assert.assertEquals @@ -59,11 +61,8 @@ class TetheringWifiP2pTest { @get:Rule val networkCallbackRule = AutoReleaseNetworkCallbackRule() - companion object { - // Shamelessly copied from TetheringConfiguration. - private const val TETHERING_LOCAL_NETWORK_AGENT = "tethering_local_network_agent" - private const val WIFIP2PGO_LOCAL_NETWORK_AGENT = "wifip2pgo_local_network_agent" - } + @get:Rule + val checkFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule() private val context = InstrumentationRegistry.getInstrumentation().getTargetContext() private val pm = context.packageManager!! @@ -81,6 +80,7 @@ class TetheringWifiP2pTest { return "%09d".format(Random().nextInt(1_000_000_000)) } + @RequiresFlagsEnabled(Flags.FLAG_TETHERING_AND_P2P_GO_LOCAL_AGENT) @Test fun testWifiP2pGoNetworkAgent_networkCallbacks() { // Check preconditions. @@ -90,16 +90,6 @@ class TetheringWifiP2pTest { // Wifi P2p Group Owner mode still need tethering support in order to get // onLocalOnlyInterfacesChanged callbacks. assumeTrue(runAsShell(TETHER_PRIVILEGED) { tm.isTetheringSupported() }) - deviceConfigRule.setConfig( - DeviceConfig.NAMESPACE_TETHERING, - TETHERING_LOCAL_NETWORK_AGENT, - "1" - ) - deviceConfigRule.setConfig( - DeviceConfig.NAMESPACE_TETHERING, - WIFIP2PGO_LOCAL_NETWORK_AGENT, - "1" - ) val cb = TestableNetworkCallback() val request = NetworkRequest.Builder().addCapability(NET_CAPABILITY_LOCAL_NETWORK) From 1c513a6a6fef58f5702ef755e9ba3599fdb7ac86 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Thu, 14 Aug 2025 22:38:33 +0800 Subject: [PATCH 2/2] Update ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS flag to target sdk 37 The ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS compatibility flag is now enabled for apps targeting SDK 37 or higher. Previously, this flag was configured to enable for Baklava (SDK 36) or higher. This is no-op because there is no tethering network agent presents. While the tethering network agents planned to be enabled in 25Q4, this adjustment allows developers sufficient time to adapt to the behavior change where NetworkRequests will match non-Thread local networks. Flag: com.android.tethering.mainline.beta.tethering_and_p2p_go_local_agent Test: atest ConnectivityCoverageTests --update-device \ --test-filter '.*Connectivity.*' Bug: 420590461 Change-Id: I105ee1d677c6beb12b4dccd109c01ef5ff2717d3 --- .../net/connectivity/ConnectivityCompatChanges.java | 4 ++-- service/src/com/android/server/ConnectivityService.java | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/framework/src/android/net/connectivity/ConnectivityCompatChanges.java b/framework/src/android/net/connectivity/ConnectivityCompatChanges.java index c3279306f9..8c8c36f5de 100644 --- a/framework/src/android/net/connectivity/ConnectivityCompatChanges.java +++ b/framework/src/android/net/connectivity/ConnectivityCompatChanges.java @@ -154,12 +154,12 @@ public final class ConnectivityCompatChanges { /** * Enable match non-threads local networks. * - * Apps targeting a release after V can have NetworkRequests matches non-thread local networks. + * Apps targeting a release after B can have NetworkRequests matches non-thread local networks. * * @hide */ @ChangeId - @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) + @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.BAKLAVA) public static final long ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS = 349487600L; private ConnectivityCompatChanges() { diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java index 35efabdaef..25fbcd5789 100644 --- a/service/src/com/android/server/ConnectivityService.java +++ b/service/src/com/android/server/ConnectivityService.java @@ -3409,8 +3409,12 @@ public class ConnectivityService extends IConnectivityManager.Stub private void maybeDisableLocalNetworkMatching(NetworkCapabilities nc, int callingUid) { // If disabled, NetworkRequest cannot match non-thread local networks even if - // specified explicitly. Compat change is enabled by default on apps targeting B+. - // Agent should not be visible on U- even if it's rolled out. + // specified explicitly. Compat change is enabled by default on apps targeting sdk + // level 37. Agent should not be visible on platform sdk level 36- even if it's rolled out. + // Note that on V+, isChangeEnabled returns false for + // ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS even if the app is targeting higher SDK + // due to b/401088586. + // TODO: Update the gating logic once SDK int APIs are ready. nc.setMatchNonThreadLocalNetworks(mDeps.isAtLeastV() && mDeps.isChangeEnabled( ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS, callingUid)); if (mDeps.isChangeEnabled(ENABLE_MATCH_LOCAL_NETWORK, callingUid)) {