Merge changes I2e556cf5,I5e42005f,I7b766ef6 into main
* changes:
Remove unused method TetheringConfiguration#isRandomPrefixBaseEnabled()
PrivateAddressCoordinator: introduce Dependencies class
PrivateAddressCoordinator: move the special handling of WiFi P2P dedicated IP to IpServer
diff --git a/Tethering/src/android/net/ip/IpServer.java b/Tethering/src/android/net/ip/IpServer.java
index 506fa56..7a6df88 100644
--- a/Tethering/src/android/net/ip/IpServer.java
+++ b/Tethering/src/android/net/ip/IpServer.java
@@ -124,6 +124,8 @@
// TODO: have PanService use some visible version of this constant
private static final String BLUETOOTH_IFACE_ADDR = "192.168.44.1/24";
+ private static final String LEGACY_WIFI_P2P_IFACE_ADDRESS = "192.168.49.1/24";
+
// TODO: have this configurable
private static final int DHCP_LEASE_TIME_SECS = 3600;
@@ -249,6 +251,7 @@
private final LinkProperties mLinkProperties;
private final boolean mUsingLegacyDhcp;
private final int mP2pLeasesSubnetPrefixLength;
+ private final boolean mIsWifiP2pDedicatedIpEnabled;
private final Dependencies mDeps;
@@ -313,6 +316,7 @@
mLinkProperties = new LinkProperties();
mUsingLegacyDhcp = config.useLegacyDhcpServer();
mP2pLeasesSubnetPrefixLength = config.getP2pLeasesSubnetPrefixLength();
+ mIsWifiP2pDedicatedIpEnabled = config.shouldEnableWifiP2pDedicatedIp();
mPrivateAddressCoordinator = addressCoordinator;
mDeps = deps;
mTetheringMetrics = tetheringMetrics;
@@ -698,11 +702,18 @@
return (mInterfaceType == TetheringManager.TETHERING_BLUETOOTH) && !SdkLevel.isAtLeastT();
}
+ private boolean shouldUseWifiP2pDedicatedIp() {
+ return mIsWifiP2pDedicatedIpEnabled
+ && mInterfaceType == TetheringManager.TETHERING_WIFI_P2P;
+ }
+
private LinkAddress requestIpv4Address(final int scope, final boolean useLastAddress) {
if (mStaticIpv4ServerAddr != null) return mStaticIpv4ServerAddr;
if (shouldNotConfigureBluetoothInterface()) return new LinkAddress(BLUETOOTH_IFACE_ADDR);
+ if (shouldUseWifiP2pDedicatedIp()) return new LinkAddress(LEGACY_WIFI_P2P_IFACE_ADDRESS);
+
return mPrivateAddressCoordinator.requestDownstreamAddress(this, scope, useLastAddress);
}
diff --git a/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java b/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java
index 1d5df61..50f82cf 100644
--- a/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java
+++ b/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java
@@ -28,6 +28,7 @@
import static java.util.Arrays.asList;
+import android.content.Context;
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
@@ -42,6 +43,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.net.module.util.DeviceConfigUtils;
import java.net.Inet4Address;
import java.net.InetAddress;
@@ -67,6 +69,9 @@
// WARNING: Keep in sync with chooseDownstreamAddress
public static final int PREFIX_LENGTH = 24;
+ public static final String TETHER_FORCE_RANDOM_PREFIX_BASE_SELECTION =
+ "tether_force_random_prefix_base_selection";
+
// Upstream monitor would be stopped when tethering is down. When tethering restart, downstream
// address may be requested before coordinator get current upstream notification. To ensure
// coordinator do not select conflict downstream prefix, mUpstreamPrefixMap would not be cleared
@@ -79,20 +84,42 @@
private final List<IpPrefix> mTetheringPrefixes;
// A supplier that returns ConnectivityManager#getAllNetworks.
private final Supplier<Network[]> mGetAllNetworksSupplier;
- private final boolean mIsRandomPrefixBaseEnabled;
- private final boolean mShouldEnableWifiP2pDedicatedIp;
+ private final Dependencies mDeps;
// keyed by downstream type(TetheringManager.TETHERING_*).
private final ArrayMap<AddressKey, LinkAddress> mCachedAddresses;
private final Random mRandom;
+ /** Capture PrivateAddressCoordinator dependencies for injection. */
+ public static class Dependencies {
+ private final Context mContext;
+
+ Dependencies(Context context) {
+ mContext = context;
+ }
+
+ /**
+ * Check whether or not one specific experimental feature is enabled according to {@link
+ * DeviceConfigUtils}.
+ *
+ * @param featureName The feature's name to look up.
+ * @return true if this feature is enabled, or false if disabled.
+ */
+ public boolean isFeatureEnabled(String featureName) {
+ return DeviceConfigUtils.isTetheringFeatureEnabled(mContext, featureName);
+ }
+ }
+
+ public PrivateAddressCoordinator(Supplier<Network[]> getAllNetworksSupplier, Context context) {
+ this(getAllNetworksSupplier, new Dependencies(context));
+ }
+
+ @VisibleForTesting
public PrivateAddressCoordinator(Supplier<Network[]> getAllNetworksSupplier,
- boolean isRandomPrefixBase,
- boolean shouldEnableWifiP2pDedicatedIp) {
+ Dependencies deps) {
mDownstreams = new ArraySet<>();
mUpstreamPrefixMap = new ArrayMap<>();
mGetAllNetworksSupplier = getAllNetworksSupplier;
- mIsRandomPrefixBaseEnabled = isRandomPrefixBase;
- mShouldEnableWifiP2pDedicatedIp = shouldEnableWifiP2pDedicatedIp;
+ mDeps = deps;
mCachedAddresses = new ArrayMap<AddressKey, LinkAddress>();
// Reserved static addresses for bluetooth and wifi p2p.
mCachedAddresses.put(new AddressKey(TETHERING_BLUETOOTH, CONNECTIVITY_SCOPE_GLOBAL),
@@ -179,11 +206,6 @@
@Nullable
public LinkAddress requestDownstreamAddress(final IpServer ipServer, final int scope,
boolean useLastAddress) {
- if (mShouldEnableWifiP2pDedicatedIp
- && ipServer.interfaceType() == TETHERING_WIFI_P2P) {
- return new LinkAddress(LEGACY_WIFI_P2P_IFACE_ADDRESS);
- }
-
final AddressKey addrKey = new AddressKey(ipServer.interfaceType(), scope);
// This ensures that tethering isn't started on 2 different interfaces with the same type.
// Once tethering could support multiple interface with the same type,
@@ -212,7 +234,7 @@
}
private int getRandomPrefixIndex() {
- if (!mIsRandomPrefixBaseEnabled) return 0;
+ if (!mDeps.isFeatureEnabled(TETHER_FORCE_RANDOM_PREFIX_BASE_SELECTION)) return 0;
final int random = getRandomInt() & 0xffffff;
// This is to select the starting prefix range (/8, /12, or /16) instead of the actual
diff --git a/Tethering/src/com/android/networkstack/tethering/Tethering.java b/Tethering/src/com/android/networkstack/tethering/Tethering.java
index 49bc86e..13b8004 100644
--- a/Tethering/src/com/android/networkstack/tethering/Tethering.java
+++ b/Tethering/src/com/android/networkstack/tethering/Tethering.java
@@ -359,10 +359,7 @@
// Load tethering configuration.
updateConfiguration();
mConfig.readEnableSyncSM(mContext);
- // It is OK for the configuration to be passed to the PrivateAddressCoordinator at
- // construction time because the only part of the configuration it uses is
- // shouldEnableWifiP2pDedicatedIp(), and currently do not support changing that.
- mPrivateAddressCoordinator = mDeps.makePrivateAddressCoordinator(mContext, mConfig);
+ mPrivateAddressCoordinator = mDeps.makePrivateAddressCoordinator(mContext);
// Must be initialized after tethering configuration is loaded because BpfCoordinator
// constructor needs to use the configuration.
diff --git a/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java b/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
index c9817c9..b3e9c1b 100644
--- a/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
+++ b/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
@@ -182,7 +182,6 @@
private final int mP2pLeasesSubnetPrefixLength;
private final boolean mEnableWearTethering;
- private final boolean mRandomPrefixBase;
private final int mUsbTetheringFunction;
protected final ContentResolver mContentResolver;
@@ -300,8 +299,6 @@
mEnableWearTethering = shouldEnableWearTethering(ctx);
- mRandomPrefixBase = mDeps.isFeatureEnabled(ctx, TETHER_FORCE_RANDOM_PREFIX_BASE_SELECTION);
-
configLog.log(toString());
}
@@ -390,10 +387,6 @@
return mEnableWearTethering;
}
- public boolean isRandomPrefixBaseEnabled() {
- return mRandomPrefixBase;
- }
-
/**
* Check whether sync SM is enabled then set it to USE_SYNC_SM. This should be called once
* when tethering is created. Otherwise if the flag is pushed while tethering is enabled,
@@ -455,9 +448,6 @@
pw.print("mUsbTetheringFunction: ");
pw.println(isUsingNcm() ? "NCM" : "RNDIS");
- pw.print("mRandomPrefixBase: ");
- pw.println(mRandomPrefixBase);
-
pw.print("USE_SYNC_SM: ");
pw.println(USE_SYNC_SM);
}
diff --git a/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java b/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java
index 81f057c..cc878d5 100644
--- a/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java
+++ b/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java
@@ -177,13 +177,9 @@
/**
* Make PrivateAddressCoordinator to be used by Tethering.
*/
- public PrivateAddressCoordinator makePrivateAddressCoordinator(
- Context ctx, TetheringConfiguration cfg) {
+ public PrivateAddressCoordinator makePrivateAddressCoordinator(Context ctx) {
final ConnectivityManager cm = ctx.getSystemService(ConnectivityManager.class);
- return new PrivateAddressCoordinator(
- cm::getAllNetworks,
- cfg.isRandomPrefixBaseEnabled(),
- cfg.shouldEnableWifiP2pDedicatedIp());
+ return new PrivateAddressCoordinator(cm::getAllNetworks, ctx);
}
/**
diff --git a/Tethering/tests/unit/src/android/net/ip/IpServerTest.java b/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
index 177296a..f7834a3 100644
--- a/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
+++ b/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
@@ -139,6 +139,7 @@
private static final boolean DEFAULT_USING_BPF_OFFLOAD = true;
private static final int DEFAULT_SUBNET_PREFIX_LENGTH = 0;
private static final int P2P_SUBNET_PREFIX_LENGTH = 25;
+ private static final String LEGACY_WIFI_P2P_IFACE_ADDRESS = "192.168.49.1/24";
private static final InterfaceParams TEST_IFACE_PARAMS = new InterfaceParams(
IFACE_NAME, 42 /* index */, MacAddress.ALL_ZEROS_ADDRESS, 1500 /* defaultMtu */);
@@ -196,6 +197,12 @@
private void initStateMachine(int interfaceType, boolean usingLegacyDhcp,
boolean usingBpfOffload) throws Exception {
+ initStateMachine(interfaceType, usingLegacyDhcp, usingBpfOffload,
+ false /* shouldEnableWifiP2pDedicatedIp */);
+ }
+
+ private void initStateMachine(int interfaceType, boolean usingLegacyDhcp,
+ boolean usingBpfOffload, boolean shouldEnableWifiP2pDedicatedIp) throws Exception {
when(mDependencies.getDadProxy(any(), any())).thenReturn(mDadProxy);
when(mDependencies.getRouterAdvertisementDaemon(any())).thenReturn(mRaDaemon);
when(mDependencies.getInterfaceParams(IFACE_NAME)).thenReturn(TEST_IFACE_PARAMS);
@@ -213,6 +220,8 @@
when(mTetherConfig.isBpfOffloadEnabled()).thenReturn(usingBpfOffload);
when(mTetherConfig.useLegacyDhcpServer()).thenReturn(usingLegacyDhcp);
when(mTetherConfig.getP2pLeasesSubnetPrefixLength()).thenReturn(P2P_SUBNET_PREFIX_LENGTH);
+ when(mTetherConfig.shouldEnableWifiP2pDedicatedIp())
+ .thenReturn(shouldEnableWifiP2pDedicatedIp);
when(mBpfCoordinator.isUsingBpfOffload()).thenReturn(usingBpfOffload);
mIpServer = createIpServer(interfaceType);
mIpServer.start();
@@ -409,7 +418,7 @@
}
@Test
- public void canBeTetheredAsWifiP2p() throws Exception {
+ public void canBeTetheredAsWifiP2p_NotUsingDedicatedIp() throws Exception {
initStateMachine(TETHERING_WIFI_P2P);
dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_LOCAL_ONLY);
@@ -431,6 +440,33 @@
}
@Test
+ public void canBeTetheredAsWifiP2p_UsingDedicatedIp() throws Exception {
+ initStateMachine(TETHERING_WIFI_P2P, false /* usingLegacyDhcp */, DEFAULT_USING_BPF_OFFLOAD,
+ true /* shouldEnableWifiP2pDedicatedIp */);
+
+ dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_LOCAL_ONLY);
+ InOrder inOrder = inOrder(mCallback, mNetd, mAddressCoordinator);
+ // When using WiFi P2p dedicated IP, the IpServer just picks the IP address without
+ // requesting for it at PrivateAddressCoordinator.
+ inOrder.verify(mAddressCoordinator, never()).requestDownstreamAddress(any(), anyInt(),
+ anyBoolean());
+ inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg ->
+ IFACE_NAME.equals(cfg.ifName) && assertNotContainsFlag(cfg.flags, IF_STATE_UP)));
+ inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
+ inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
+ inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME),
+ any(), any());
+ inOrder.verify(mCallback).updateInterfaceState(
+ mIpServer, STATE_LOCAL_ONLY, TETHER_ERROR_NO_ERROR);
+ inOrder.verify(mCallback).updateLinkProperties(
+ eq(mIpServer), mLinkPropertiesCaptor.capture());
+ assertIPv4AddressAndDirectlyConnectedRoute(mLinkPropertiesCaptor.getValue());
+ assertEquals(List.of(new LinkAddress(LEGACY_WIFI_P2P_IFACE_ADDRESS)),
+ mLinkPropertiesCaptor.getValue().getLinkAddresses());
+ verifyNoMoreInteractions(mNetd, mCallback, mAddressCoordinator);
+ }
+
+ @Test
public void handlesFirstUpstreamChange() throws Exception {
initTetheredStateMachine(TETHERING_BLUETOOTH, null);
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java
index a5c06f3..bff1fda 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java
@@ -25,6 +25,7 @@
import static android.net.TetheringManager.TETHERING_WIFI;
import static android.net.TetheringManager.TETHERING_WIFI_P2P;
+import static com.android.networkstack.tethering.PrivateAddressCoordinator.TETHER_FORCE_RANDOM_PREFIX_BASE_SELECTION;
import static com.android.networkstack.tethering.util.PrefixUtils.asIpPrefix;
import static org.junit.Assert.assertEquals;
@@ -71,7 +72,7 @@
@Mock private IpServer mWifiP2pIpServer;
@Mock private Context mContext;
@Mock private ConnectivityManager mConnectivityMgr;
- @Mock private TetheringConfiguration mConfig;
+ @Mock private PrivateAddressCoordinator.Dependencies mDeps;
private PrivateAddressCoordinator mPrivateAddressCoordinator;
private final LinkAddress mBluetoothAddress = new LinkAddress("192.168.44.1/24");
@@ -106,15 +107,9 @@
when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(mConnectivityMgr);
when(mContext.getSystemService(ConnectivityManager.class)).thenReturn(mConnectivityMgr);
when(mConnectivityMgr.getAllNetworks()).thenReturn(mAllNetworks);
- when(mConfig.shouldEnableWifiP2pDedicatedIp()).thenReturn(false);
- when(mConfig.isRandomPrefixBaseEnabled()).thenReturn(false);
setUpIpServers();
mPrivateAddressCoordinator =
- spy(
- new PrivateAddressCoordinator(
- mConnectivityMgr::getAllNetworks,
- mConfig.isRandomPrefixBaseEnabled(),
- mConfig.shouldEnableWifiP2pDedicatedIp()));
+ spy(new PrivateAddressCoordinator(mConnectivityMgr::getAllNetworks, mDeps));
}
private LinkAddress requestDownstreamAddress(final IpServer ipServer, int scope,
@@ -282,24 +277,6 @@
}
@Test
- public void testEnableLegacyWifiP2PAddress() throws Exception {
- when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(
- getSubAddress(mLegacyWifiP2pAddress.getAddress().getAddress()));
- // No matter #shouldEnableWifiP2pDedicatedIp() is enabled or not, legacy wifi p2p prefix
- // is resevered.
- assertReseveredWifiP2pPrefix();
-
- when(mConfig.shouldEnableWifiP2pDedicatedIp()).thenReturn(true);
- assertReseveredWifiP2pPrefix();
-
- // If #shouldEnableWifiP2pDedicatedIp() is enabled, wifi P2P gets the configured address.
- LinkAddress address = requestDownstreamAddress(mWifiP2pIpServer,
- CONNECTIVITY_SCOPE_LOCAL, true /* useLastAddress */);
- assertEquals(mLegacyWifiP2pAddress, address);
- mPrivateAddressCoordinator.releaseDownstream(mWifiP2pIpServer);
- }
-
- @Test
public void testEnableSapAndLohsConcurrently() throws Exception {
final LinkAddress hotspotAddress = requestDownstreamAddress(mHotspotIpServer,
CONNECTIVITY_SCOPE_GLOBAL, true /* useLastAddress */);
@@ -317,7 +294,7 @@
@Test
public void testStartedPrefixRange() throws Exception {
- when(mConfig.isRandomPrefixBaseEnabled()).thenReturn(true);
+ when(mDeps.isFeatureEnabled(TETHER_FORCE_RANDOM_PREFIX_BASE_SELECTION)).thenReturn(true);
startedPrefixBaseTest("192.168.0.0/16", 0);
@@ -343,11 +320,7 @@
private void startedPrefixBaseTest(final String expected, final int randomIntForPrefixBase)
throws Exception {
mPrivateAddressCoordinator =
- spy(
- new PrivateAddressCoordinator(
- mConnectivityMgr::getAllNetworks,
- mConfig.isRandomPrefixBaseEnabled(),
- mConfig.shouldEnableWifiP2pDedicatedIp()));
+ spy(new PrivateAddressCoordinator(mConnectivityMgr::getAllNetworks, mDeps));
when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(randomIntForPrefixBase);
final LinkAddress address = requestDownstreamAddress(mHotspotIpServer,
CONNECTIVITY_SCOPE_GLOBAL, false /* useLastAddress */);
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 9a4945e..66fe957 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
@@ -71,6 +71,7 @@
import static com.android.net.module.util.NetworkStackConstants.RFC7421_PREFIX_LENGTH;
import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_HIDL_1_0;
import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_NONE;
+import static com.android.networkstack.tethering.PrivateAddressCoordinator.TETHER_FORCE_RANDOM_PREFIX_BASE_SELECTION;
import static com.android.networkstack.tethering.TestConnectivityManager.BROADCAST_FIRST;
import static com.android.networkstack.tethering.TestConnectivityManager.CALLBACKS_FIRST;
import static com.android.networkstack.tethering.Tethering.UserRestrictionActionListener;
@@ -293,6 +294,7 @@
@Mock private TetheredInterfaceRequestShim mTetheredInterfaceRequestShim;
@Mock private TetheringMetrics mTetheringMetrics;
@Mock private RoutingCoordinatorManager mRoutingCoordinatorManager;
+ @Mock private PrivateAddressCoordinator.Dependencies mPrivateAddressCoordinatorDependencies;
private final MockIpServerDependencies mIpServerDependencies =
spy(new MockIpServerDependencies());
@@ -535,9 +537,11 @@
}
@Override
- public PrivateAddressCoordinator makePrivateAddressCoordinator(Context ctx,
- TetheringConfiguration cfg) {
- mPrivateAddressCoordinator = super.makePrivateAddressCoordinator(ctx, cfg);
+ public PrivateAddressCoordinator makePrivateAddressCoordinator(Context ctx) {
+ ConnectivityManager cm = ctx.getSystemService(ConnectivityManager.class);
+ mPrivateAddressCoordinator =
+ new PrivateAddressCoordinator(
+ cm::getAllNetworks, mPrivateAddressCoordinatorDependencies);
return mPrivateAddressCoordinator;
}
@@ -664,6 +668,8 @@
.thenReturn(true);
initOffloadConfiguration(OFFLOAD_HAL_VERSION_HIDL_1_0, 0 /* defaultDisabled */);
when(mOffloadHardwareInterface.getForwardedStats(any())).thenReturn(mForwardedStats);
+ when(mPrivateAddressCoordinatorDependencies.isFeatureEnabled(anyString()))
+ .thenReturn(false);
mServiceContext = new TestContext(mContext);
mServiceContext.setUseRegisteredHandlers(true);