Merge "Allow wifi p2p to use legacy dedicated address" am: d2af4d9e2a am: b537c25685
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1382398
Change-Id: Ica17499f82135bc96b87ca4071b603bb8cc23053
diff --git a/Tethering/res/values/config.xml b/Tethering/res/values/config.xml
index 9b9dcde..5f8d299 100644
--- a/Tethering/res/values/config.xml
+++ b/Tethering/res/values/config.xml
@@ -73,6 +73,9 @@
<!-- Use the old dnsmasq DHCP server for tethering instead of the framework implementation. -->
<bool translatable="false" name="config_tether_enable_legacy_dhcp_server">false</bool>
+ <!-- Use legacy wifi p2p dedicated address instead of randomize address. -->
+ <bool translatable="false" name="config_tether_enable_legacy_wifi_p2p_dedicated_ip">false</bool>
+
<!-- Dhcp range (min, max) to use for tethering purposes -->
<string-array translatable="false" name="config_tether_dhcp_range">
</string-array>
diff --git a/Tethering/res/values/overlayable.xml b/Tethering/res/values/overlayable.xml
index 6a33d55..0ee7a99 100644
--- a/Tethering/res/values/overlayable.xml
+++ b/Tethering/res/values/overlayable.xml
@@ -30,6 +30,7 @@
-->
<item type="bool" name="config_tether_enable_bpf_offload"/>
<item type="bool" name="config_tether_enable_legacy_dhcp_server"/>
+ <item type="bool" name="config_tether_enable_legacy_wifi_p2p_dedicated_ip"/>
<item type="integer" name="config_tether_offload_poll_interval"/>
<item type="array" name="config_tether_upstream_types"/>
<item type="bool" name="config_tether_upstream_automatic"/>
diff --git a/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java b/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java
index aa58a4b..fd9e360 100644
--- a/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java
+++ b/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java
@@ -15,6 +15,8 @@
*/
package com.android.networkstack.tethering;
+import static android.net.TetheringManager.TETHERING_WIFI_P2P;
+
import static java.util.Arrays.asList;
import android.content.Context;
@@ -58,6 +60,7 @@
private static final int BYTE_MASK = 0xff;
// reserved for bluetooth tethering.
private static final int BLUETOOTH_RESERVED = 44;
+ private static final int WIFI_P2P_RESERVED = 49;
private static final byte DEFAULT_ID = (byte) 42;
// Upstream monitor would be stopped when tethering is down. When tethering restart, downstream
@@ -71,15 +74,18 @@
// 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16
// Tethering use 192.168.0.0/16 that has 256 contiguous class C network numbers.
private static final String DEFAULT_TETHERING_PREFIX = "192.168.0.0/16";
+ private static final String LEGACY_WIFI_P2P_IFACE_ADDRESS = "192.168.49.1/24";
private final IpPrefix mTetheringPrefix;
private final ConnectivityManager mConnectivityMgr;
+ private final TetheringConfiguration mConfig;
- public PrivateAddressCoordinator(Context context) {
+ public PrivateAddressCoordinator(Context context, TetheringConfiguration config) {
mDownstreams = new ArraySet<>();
mUpstreamPrefixMap = new ArrayMap<>();
mTetheringPrefix = new IpPrefix(DEFAULT_TETHERING_PREFIX);
mConnectivityMgr = (ConnectivityManager) context.getSystemService(
Context.CONNECTIVITY_SERVICE);
+ mConfig = config;
}
/**
@@ -141,12 +147,21 @@
mUpstreamPrefixMap.removeAll(toBeRemoved);
}
+ private boolean isReservedSubnet(final int subnet) {
+ return subnet == BLUETOOTH_RESERVED || subnet == WIFI_P2P_RESERVED;
+ }
+
/**
* Pick a random available address and mark its prefix as in use for the provided IpServer,
* returns null if there is no available address.
*/
@Nullable
public LinkAddress requestDownstreamAddress(final IpServer ipServer) {
+ if (mConfig.shouldEnableWifiP2pDedicatedIp()
+ && ipServer.interfaceType() == TETHERING_WIFI_P2P) {
+ return new LinkAddress(LEGACY_WIFI_P2P_IFACE_ADDRESS);
+ }
+
// Address would be 192.168.[subAddress]/24.
final byte[] bytes = mTetheringPrefix.getRawAddress();
final int subAddress = getRandomSubAddr();
@@ -154,7 +169,7 @@
bytes[3] = getSanitizedAddressSuffix(subAddress, (byte) 0, (byte) 1, (byte) 0xff);
for (int i = 0; i < MAX_UBYTE; i++) {
final int newSubNet = (subNet + i) & BYTE_MASK;
- if (newSubNet == BLUETOOTH_RESERVED) continue;
+ if (isReservedSubnet(newSubNet)) continue;
bytes[2] = (byte) newSubNet;
final InetAddress addr;
diff --git a/Tethering/src/com/android/networkstack/tethering/Tethering.java b/Tethering/src/com/android/networkstack/tethering/Tethering.java
index cfc6575..7dd5290 100644
--- a/Tethering/src/com/android/networkstack/tethering/Tethering.java
+++ b/Tethering/src/com/android/networkstack/tethering/Tethering.java
@@ -320,10 +320,13 @@
mExecutor = new TetheringThreadExecutor(mHandler);
mActiveDataSubIdListener = new ActiveDataSubIdListener(mExecutor);
mNetdCallback = new NetdCallback();
- mPrivateAddressCoordinator = new PrivateAddressCoordinator(mContext);
// Load tethering configuration.
updateConfiguration();
+ // 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 = new PrivateAddressCoordinator(mContext, mConfig);
// 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 e1771a5..5783805 100644
--- a/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
+++ b/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
@@ -84,6 +84,9 @@
public static final String TETHER_ENABLE_LEGACY_DHCP_SERVER =
"tether_enable_legacy_dhcp_server";
+ public static final String USE_LEGACY_WIFI_P2P_DEDICATED_IP =
+ "use_legacy_wifi_p2p_dedicated_ip";
+
/**
* Default value that used to periodic polls tether offload stats from tethering offload HAL
* to make the data warnings work.
@@ -113,6 +116,7 @@
private final int mOffloadPollInterval;
// TODO: Add to TetheringConfigurationParcel if required.
private final boolean mEnableBpfOffload;
+ private final boolean mEnableWifiP2pDedicatedIp;
public TetheringConfiguration(Context ctx, SharedLog log, int id) {
final SharedLog configLog = log.forSubComponent("config");
@@ -156,6 +160,10 @@
R.integer.config_tether_offload_poll_interval,
DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS);
+ mEnableWifiP2pDedicatedIp = getResourceBoolean(res,
+ R.bool.config_tether_enable_legacy_wifi_p2p_dedicated_ip,
+ false /* defaultValue */);
+
configLog.log(toString());
}
@@ -199,6 +207,11 @@
return !TextUtils.isEmpty(provisioningAppNoUi);
}
+ /** Check whether dedicated wifi p2p address is enabled. */
+ public boolean shouldEnableWifiP2pDedicatedIp() {
+ return mEnableWifiP2pDedicatedIp;
+ }
+
/** Does the dumping.*/
public void dump(PrintWriter pw) {
pw.print("activeDataSubId: ");
@@ -233,6 +246,9 @@
pw.print("enableLegacyDhcpServer: ");
pw.println(enableLegacyDhcpServer);
+
+ pw.print("enableWifiP2pDedicatedIp: ");
+ pw.println(mEnableWifiP2pDedicatedIp);
}
/** Returns the string representation of this object.*/
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 2c0df6f..8e93c2e 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java
@@ -15,6 +15,11 @@
*/
package com.android.networkstack.tethering;
+import static android.net.TetheringManager.TETHERING_ETHERNET;
+import static android.net.TetheringManager.TETHERING_USB;
+import static android.net.TetheringManager.TETHERING_WIFI;
+import static android.net.TetheringManager.TETHERING_WIFI_P2P;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.mockito.Mockito.never;
@@ -54,22 +59,34 @@
@Mock private IpServer mHotspotIpServer;
@Mock private IpServer mUsbIpServer;
@Mock private IpServer mEthernetIpServer;
+ @Mock private IpServer mWifiP2pIpServer;
@Mock private Context mContext;
@Mock private ConnectivityManager mConnectivityMgr;
+ @Mock private TetheringConfiguration mConfig;
private PrivateAddressCoordinator mPrivateAddressCoordinator;
private final IpPrefix mBluetoothPrefix = new IpPrefix("192.168.44.0/24");
+ private final LinkAddress mLegacyWifiP2pAddress = new LinkAddress("192.168.49.1/24");
private final Network mWifiNetwork = new Network(1);
private final Network mMobileNetwork = new Network(2);
private final Network[] mAllNetworks = {mMobileNetwork, mWifiNetwork};
+ private void setUpIpServers() throws Exception {
+ when(mUsbIpServer.interfaceType()).thenReturn(TETHERING_USB);
+ when(mEthernetIpServer.interfaceType()).thenReturn(TETHERING_ETHERNET);
+ when(mHotspotIpServer.interfaceType()).thenReturn(TETHERING_WIFI);
+ when(mWifiP2pIpServer.interfaceType()).thenReturn(TETHERING_WIFI_P2P);
+ }
+
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(mConnectivityMgr);
when(mConnectivityMgr.getAllNetworks()).thenReturn(mAllNetworks);
- mPrivateAddressCoordinator = spy(new PrivateAddressCoordinator(mContext));
+ when(mConfig.shouldEnableWifiP2pDedicatedIp()).thenReturn(false);
+ setUpIpServers();
+ mPrivateAddressCoordinator = spy(new PrivateAddressCoordinator(mContext, mConfig));
}
@Test
@@ -256,4 +273,38 @@
final IpPrefix ethPrefix = PrefixUtils.asIpPrefix(ethAddr);
assertEquals(predefinedPrefix, ethPrefix);
}
+
+ private int getSubAddress(final byte... ipv4Address) {
+ assertEquals(4, ipv4Address.length);
+
+ int subnet = Byte.toUnsignedInt(ipv4Address[2]);
+ return (subnet << 8) + ipv4Address[3];
+ }
+
+ private void assertReseveredWifiP2pPrefix() throws Exception {
+ LinkAddress address = mPrivateAddressCoordinator.requestDownstreamAddress(
+ mHotspotIpServer);
+ final IpPrefix hotspotPrefix = PrefixUtils.asIpPrefix(address);
+ final IpPrefix legacyWifiP2pPrefix = PrefixUtils.asIpPrefix(mLegacyWifiP2pAddress);
+ assertNotEquals(legacyWifiP2pPrefix, hotspotPrefix);
+ mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer);
+ }
+
+ @Test
+ public void testEnableLegacyWifiP2PAddress() throws Exception {
+ when(mPrivateAddressCoordinator.getRandomSubAddr()).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 = mPrivateAddressCoordinator.requestDownstreamAddress(
+ mWifiP2pIpServer);
+ assertEquals(mLegacyWifiP2pAddress, address);
+ mPrivateAddressCoordinator.releaseDownstream(mWifiP2pIpServer);
+ }
}
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java
index a9ac4e2..dc0940c 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java
@@ -128,6 +128,8 @@
.thenReturn(new String[0]);
when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn(
false);
+ when(mResources.getBoolean(R.bool.config_tether_enable_legacy_wifi_p2p_dedicated_ip))
+ .thenReturn(false);
initializeBpfOffloadConfiguration(true, null /* unset */);
mHasTelephonyManager = true;
@@ -413,4 +415,17 @@
R.string.config_mobile_hotspot_provision_response)).thenReturn(
PROVISIONING_APP_RESPONSE);
}
+
+ @Test
+ public void testEnableLegacyWifiP2PAddress() throws Exception {
+ final TetheringConfiguration defaultCfg = new TetheringConfiguration(
+ mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
+ assertFalse(defaultCfg.shouldEnableWifiP2pDedicatedIp());
+
+ when(mResources.getBoolean(R.bool.config_tether_enable_legacy_wifi_p2p_dedicated_ip))
+ .thenReturn(true);
+ final TetheringConfiguration testCfg = new TetheringConfiguration(
+ mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
+ assertTrue(testCfg.shouldEnableWifiP2pDedicatedIp());
+ }
}