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