Merge "Allow tethering pick prefix from all of private address range"
This commit is contained in:
@@ -20,6 +20,10 @@ import static android.net.TetheringManager.TETHERING_BLUETOOTH;
|
||||
import static android.net.TetheringManager.TETHERING_WIFI_P2P;
|
||||
import static android.net.util.PrefixUtils.asIpPrefix;
|
||||
|
||||
import static com.android.net.module.util.Inet4AddressUtils.inet4AddressToIntHTH;
|
||||
import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH;
|
||||
import static com.android.net.module.util.Inet4AddressUtils.prefixLengthToV4NetmaskIntHTH;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
import android.content.Context;
|
||||
@@ -37,9 +41,10 @@ import androidx.annotation.Nullable;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.util.IndentingPrintWriter;
|
||||
|
||||
import java.net.Inet4Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
@@ -58,10 +63,6 @@ import java.util.Set;
|
||||
public class PrivateAddressCoordinator {
|
||||
public static final int PREFIX_LENGTH = 24;
|
||||
|
||||
private static final int MAX_UBYTE = 256;
|
||||
private static final int BYTE_MASK = 0xff;
|
||||
private static final byte DEFAULT_ID = (byte) 42;
|
||||
|
||||
// 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
|
||||
@@ -69,22 +70,22 @@ public class PrivateAddressCoordinator {
|
||||
// mUpstreamPrefixMap when tethering is starting. See #maybeRemoveDeprecatedUpstreams().
|
||||
private final ArrayMap<Network, List<IpPrefix>> mUpstreamPrefixMap;
|
||||
private final ArraySet<IpServer> mDownstreams;
|
||||
// IANA has reserved the following three blocks of the IP address space for private intranets:
|
||||
// 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 static final String LEGACY_BLUETOOTH_IFACE_ADDRESS = "192.168.44.1/24";
|
||||
private final IpPrefix mTetheringPrefix;
|
||||
private final List<IpPrefix> mTetheringPrefixes;
|
||||
private final ConnectivityManager mConnectivityMgr;
|
||||
private final TetheringConfiguration mConfig;
|
||||
// keyed by downstream type(TetheringManager.TETHERING_*).
|
||||
private final SparseArray<LinkAddress> mCachedAddresses;
|
||||
|
||||
public PrivateAddressCoordinator(Context context, TetheringConfiguration config) {
|
||||
this(context, config, new ArrayList<>(Arrays.asList(new IpPrefix("192.168.0.0/16"))));
|
||||
}
|
||||
|
||||
public PrivateAddressCoordinator(Context context, TetheringConfiguration config,
|
||||
List<IpPrefix> prefixPools) {
|
||||
mDownstreams = new ArraySet<>();
|
||||
mUpstreamPrefixMap = new ArrayMap<>();
|
||||
mTetheringPrefix = new IpPrefix(DEFAULT_TETHERING_PREFIX);
|
||||
mConnectivityMgr = (ConnectivityManager) context.getSystemService(
|
||||
Context.CONNECTIVITY_SERVICE);
|
||||
mConfig = config;
|
||||
@@ -92,6 +93,8 @@ public class PrivateAddressCoordinator {
|
||||
// Reserved static addresses for bluetooth and wifi p2p.
|
||||
mCachedAddresses.put(TETHERING_BLUETOOTH, new LinkAddress(LEGACY_BLUETOOTH_IFACE_ADDRESS));
|
||||
mCachedAddresses.put(TETHERING_WIFI_P2P, new LinkAddress(LEGACY_WIFI_P2P_IFACE_ADDRESS));
|
||||
|
||||
mTetheringPrefixes = prefixPools;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -179,52 +182,148 @@ public class PrivateAddressCoordinator {
|
||||
return cachedAddress;
|
||||
}
|
||||
|
||||
// Address would be 192.168.[subAddress]/24.
|
||||
final byte[] bytes = mTetheringPrefix.getRawAddress();
|
||||
final int subAddress = getRandomSubAddr();
|
||||
final int subNet = (subAddress >> 8) & BYTE_MASK;
|
||||
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;
|
||||
bytes[2] = (byte) newSubNet;
|
||||
|
||||
final InetAddress addr;
|
||||
try {
|
||||
addr = InetAddress.getByAddress(bytes);
|
||||
} catch (UnknownHostException e) {
|
||||
throw new IllegalStateException("Invalid address, shouldn't happen.", e);
|
||||
for (IpPrefix prefixRange : mTetheringPrefixes) {
|
||||
final LinkAddress newAddress = chooseDownstreamAddress(prefixRange);
|
||||
if (newAddress != null) {
|
||||
mDownstreams.add(ipServer);
|
||||
mCachedAddresses.put(ipServer.interfaceType(), newAddress);
|
||||
return newAddress;
|
||||
}
|
||||
|
||||
if (isConflict(new IpPrefix(addr, PREFIX_LENGTH))) continue;
|
||||
|
||||
mDownstreams.add(ipServer);
|
||||
final LinkAddress newAddress = new LinkAddress(addr, PREFIX_LENGTH);
|
||||
mCachedAddresses.put(ipServer.interfaceType(), newAddress);
|
||||
return newAddress;
|
||||
}
|
||||
|
||||
// No available address.
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isConflict(final IpPrefix prefix) {
|
||||
// Check whether this prefix is in use or conflict with any current upstream network.
|
||||
return isDownstreamPrefixInUse(prefix) || isConflictWithUpstream(prefix);
|
||||
private int getPrefixBaseAddress(final IpPrefix prefix) {
|
||||
return inet4AddressToIntHTH((Inet4Address) prefix.getAddress());
|
||||
}
|
||||
|
||||
/** Get random sub address value. Return value is in 0 ~ 0xffff. */
|
||||
@VisibleForTesting
|
||||
public int getRandomSubAddr() {
|
||||
return ((new Random()).nextInt()) & 0xffff; // subNet is in 0 ~ 0xffff.
|
||||
/**
|
||||
* Check whether input prefix conflict with upstream prefixes or in-use downstream prefixes.
|
||||
* If yes, return one of them.
|
||||
*/
|
||||
private IpPrefix getConflictPrefix(final IpPrefix prefix) {
|
||||
final IpPrefix upstream = getConflictWithUpstream(prefix);
|
||||
if (upstream != null) return upstream;
|
||||
|
||||
return getInUseDownstreamPrefix(prefix);
|
||||
}
|
||||
|
||||
private byte getSanitizedAddressSuffix(final int source, byte... excluded) {
|
||||
final byte subId = (byte) (source & BYTE_MASK);
|
||||
for (byte value : excluded) {
|
||||
if (subId == value) return DEFAULT_ID;
|
||||
// Get the next non-conflict sub prefix. E.g: To get next sub prefix from 10.0.0.0/8, if the
|
||||
// previously selected prefix is 10.20.42.0/24(subPrefix: 0.20.42.0) and the conflicting prefix
|
||||
// is 10.16.0.0/20 (10.16.0.0 ~ 10.16.15.255), then the max address under subPrefix is
|
||||
// 0.16.15.255 and the next subPrefix is 0.16.16.255/24 (0.16.15.255 + 0.0.1.0).
|
||||
// Note: the sub address 0.0.0.255 here is fine to be any value that it will be replaced as
|
||||
// selected random sub address later.
|
||||
private int getNextSubPrefix(final IpPrefix conflictPrefix, final int prefixRangeMask) {
|
||||
final int suffixMask = ~prefixLengthToV4NetmaskIntHTH(conflictPrefix.getPrefixLength());
|
||||
// The largest offset within the prefix assignment block that still conflicts with
|
||||
// conflictPrefix.
|
||||
final int maxConflict =
|
||||
(getPrefixBaseAddress(conflictPrefix) | suffixMask) & ~prefixRangeMask;
|
||||
|
||||
final int prefixMask = prefixLengthToV4NetmaskIntHTH(PREFIX_LENGTH);
|
||||
// Pick a sub prefix a full prefix (1 << (32 - PREFIX_LENGTH) addresses) greater than
|
||||
// maxConflict. This ensures that the selected prefix never overlaps with conflictPrefix.
|
||||
// There is no need to mask the result with PREFIX_LENGTH bits because this is done by
|
||||
// findAvailablePrefixFromRange when it constructs the prefix.
|
||||
return maxConflict + (1 << (32 - PREFIX_LENGTH));
|
||||
}
|
||||
|
||||
private LinkAddress chooseDownstreamAddress(final IpPrefix prefixRange) {
|
||||
// The netmask of the prefix assignment block (e.g., 0xfff00000 for 172.16.0.0/12).
|
||||
final int prefixRangeMask = prefixLengthToV4NetmaskIntHTH(prefixRange.getPrefixLength());
|
||||
|
||||
// The zero address in the block (e.g., 0xac100000 for 172.16.0.0/12).
|
||||
final int baseAddress = getPrefixBaseAddress(prefixRange);
|
||||
|
||||
// The subnet mask corresponding to PREFIX_LENGTH.
|
||||
final int prefixMask = prefixLengthToV4NetmaskIntHTH(PREFIX_LENGTH);
|
||||
|
||||
// The offset within prefixRange of a randomly-selected prefix of length PREFIX_LENGTH.
|
||||
// This may not be the prefix of the address returned by this method:
|
||||
// - If it is already in use, the method will return an address in another prefix.
|
||||
// - If all prefixes within prefixRange are in use, the method will return null. For
|
||||
// example, for a /24 prefix within 172.26.0.0/12, this will be a multiple of 256 in
|
||||
// [0, 1048576). In other words, a random 32-bit number with mask 0x000fff00.
|
||||
//
|
||||
// prefixRangeMask is required to ensure no wrapping. For example, consider:
|
||||
// - prefixRange 127.0.0.0/8
|
||||
// - randomPrefixStart 127.255.255.0
|
||||
// - A conflicting prefix of 127.255.254.0/23
|
||||
// In this case without prefixRangeMask, getNextSubPrefix would return 128.0.0.0, which
|
||||
// means the "start < end" check in findAvailablePrefixFromRange would not reject the prefix
|
||||
// because Java doesn't have unsigned integers, so 128.0.0.0 = 0x80000000 = -2147483648
|
||||
// is less than 127.0.0.0 = 0x7f000000 = 2130706432.
|
||||
//
|
||||
// Additionally, it makes debug output easier to read by making the numbers smaller.
|
||||
final int randomPrefixStart = getRandomInt() & ~prefixRangeMask & prefixMask;
|
||||
|
||||
// A random offset within the prefix. Used to determine the local address once the prefix
|
||||
// is selected. It does not result in an IPv4 address ending in .0, .1, or .255
|
||||
// For a PREFIX_LENGTH of 255, this is a number between 2 and 254.
|
||||
final int subAddress = getSanitizedSubAddr(~prefixMask);
|
||||
|
||||
// Find a prefix length PREFIX_LENGTH between randomPrefixStart and the end of the block,
|
||||
// such that the prefix does not conflict with any upstream.
|
||||
IpPrefix downstreamPrefix = findAvailablePrefixFromRange(
|
||||
randomPrefixStart, (~prefixRangeMask) + 1, baseAddress, prefixRangeMask);
|
||||
if (downstreamPrefix != null) return getLinkAddress(downstreamPrefix, subAddress);
|
||||
|
||||
// If that failed, do the same, but between 0 and randomPrefixStart.
|
||||
downstreamPrefix = findAvailablePrefixFromRange(
|
||||
0, randomPrefixStart, baseAddress, prefixRangeMask);
|
||||
|
||||
return getLinkAddress(downstreamPrefix, subAddress);
|
||||
}
|
||||
|
||||
private LinkAddress getLinkAddress(final IpPrefix prefix, final int subAddress) {
|
||||
if (prefix == null) return null;
|
||||
|
||||
final InetAddress address = intToInet4AddressHTH(getPrefixBaseAddress(prefix) | subAddress);
|
||||
return new LinkAddress(address, PREFIX_LENGTH);
|
||||
}
|
||||
|
||||
private IpPrefix findAvailablePrefixFromRange(final int start, final int end,
|
||||
final int baseAddress, final int prefixRangeMask) {
|
||||
int newSubPrefix = start;
|
||||
while (newSubPrefix < end) {
|
||||
final InetAddress address = intToInet4AddressHTH(baseAddress | newSubPrefix);
|
||||
final IpPrefix prefix = new IpPrefix(address, PREFIX_LENGTH);
|
||||
|
||||
final IpPrefix conflictPrefix = getConflictPrefix(prefix);
|
||||
|
||||
if (conflictPrefix == null) return prefix;
|
||||
|
||||
newSubPrefix = getNextSubPrefix(conflictPrefix, prefixRangeMask);
|
||||
}
|
||||
|
||||
return subId;
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Get random int which could be used to generate random address. */
|
||||
@VisibleForTesting
|
||||
public int getRandomInt() {
|
||||
return (new Random()).nextInt();
|
||||
}
|
||||
|
||||
/** Get random subAddress and avoid selecting x.x.x.0, x.x.x.1 and x.x.x.255 address. */
|
||||
private int getSanitizedSubAddr(final int subAddrMask) {
|
||||
final int randomSubAddr = getRandomInt() & subAddrMask;
|
||||
// If prefix length > 30, the selecting speace would be less than 4 which may be hard to
|
||||
// avoid 3 consecutive address.
|
||||
if (PREFIX_LENGTH > 30) return randomSubAddr;
|
||||
|
||||
// TODO: maybe it is not necessary to avoid .0, .1 and .255 address because tethering
|
||||
// address would not be conflicted. This code only works because PREFIX_LENGTH is not longer
|
||||
// than 24
|
||||
final int candidate = randomSubAddr & 0xff;
|
||||
if (candidate == 0 || candidate == 1 || candidate == 255) {
|
||||
return (randomSubAddr & 0xfffffffc) + 2;
|
||||
}
|
||||
|
||||
return randomSubAddr;
|
||||
}
|
||||
|
||||
/** Release downstream record for IpServer. */
|
||||
@@ -237,14 +336,18 @@ public class PrivateAddressCoordinator {
|
||||
mUpstreamPrefixMap.clear();
|
||||
}
|
||||
|
||||
private boolean isConflictWithUpstream(final IpPrefix source) {
|
||||
private IpPrefix getConflictWithUpstream(final IpPrefix prefix) {
|
||||
for (int i = 0; i < mUpstreamPrefixMap.size(); i++) {
|
||||
final List<IpPrefix> list = mUpstreamPrefixMap.valueAt(i);
|
||||
for (IpPrefix target : list) {
|
||||
if (isConflictPrefix(source, target)) return true;
|
||||
for (IpPrefix upstream : list) {
|
||||
if (isConflictPrefix(prefix, upstream)) return upstream;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isConflictWithUpstream(final IpPrefix prefix) {
|
||||
return getConflictWithUpstream(prefix) != null;
|
||||
}
|
||||
|
||||
private boolean isConflictPrefix(final IpPrefix prefix1, final IpPrefix prefix2) {
|
||||
@@ -257,11 +360,10 @@ public class PrivateAddressCoordinator {
|
||||
|
||||
// InUse Prefixes are prefixes of mCachedAddresses which are active downstream addresses, last
|
||||
// downstream addresses(reserved for next time) and static addresses(e.g. bluetooth, wifi p2p).
|
||||
private boolean isDownstreamPrefixInUse(final IpPrefix prefix) {
|
||||
// This class always generates downstream prefixes with the same prefix length, so
|
||||
// prefixes cannot be contained in each other. They can only be equal to each other.
|
||||
private IpPrefix getInUseDownstreamPrefix(final IpPrefix prefix) {
|
||||
for (int i = 0; i < mCachedAddresses.size(); i++) {
|
||||
if (prefix.equals(asIpPrefix(mCachedAddresses.valueAt(i)))) return true;
|
||||
final IpPrefix downstream = asIpPrefix(mCachedAddresses.valueAt(i));
|
||||
if (isConflictPrefix(prefix, downstream)) return downstream;
|
||||
}
|
||||
|
||||
// IpServer may use manually-defined address (mStaticIpv4ServerAddr) which does not include
|
||||
@@ -270,10 +372,10 @@ public class PrivateAddressCoordinator {
|
||||
final IpPrefix target = getDownstreamPrefix(downstream);
|
||||
if (target == null) continue;
|
||||
|
||||
if (isConflictPrefix(prefix, target)) return true;
|
||||
if (isConflictPrefix(prefix, target)) return target;
|
||||
}
|
||||
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
private IpPrefix getDownstreamPrefix(final IpServer downstream) {
|
||||
@@ -284,6 +386,13 @@ public class PrivateAddressCoordinator {
|
||||
}
|
||||
|
||||
void dump(final IndentingPrintWriter pw) {
|
||||
pw.println("mTetheringPrefixes:");
|
||||
pw.increaseIndent();
|
||||
for (IpPrefix prefix : mTetheringPrefixes) {
|
||||
pw.println(prefix);
|
||||
}
|
||||
pw.decreaseIndent();
|
||||
|
||||
pw.println("mUpstreamPrefixMap:");
|
||||
pw.increaseIndent();
|
||||
for (int i = 0; i < mUpstreamPrefixMap.size(); i++) {
|
||||
|
||||
@@ -326,7 +326,7 @@ public class Tethering {
|
||||
// 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);
|
||||
mPrivateAddressCoordinator = mDeps.getPrivateAddressCoordinator(mContext, mConfig);
|
||||
|
||||
// Must be initialized after tethering configuration is loaded because BpfCoordinator
|
||||
// constructor needs to use the configuration.
|
||||
|
||||
@@ -156,4 +156,12 @@ public abstract class TetheringDependencies {
|
||||
public boolean isTetheringDenied() {
|
||||
return TextUtils.equals(SystemProperties.get("ro.tether.denied"), "true");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a reference to PrivateAddressCoordinator to be used by Tethering.
|
||||
*/
|
||||
public PrivateAddressCoordinator getPrivateAddressCoordinator(Context ctx,
|
||||
TetheringConfiguration cfg) {
|
||||
return new PrivateAddressCoordinator(ctx, cfg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,6 +51,9 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@SmallTest
|
||||
public final class PrivateAddressCoordinatorTest {
|
||||
@@ -70,7 +73,17 @@ public final class PrivateAddressCoordinatorTest {
|
||||
private final Network mWifiNetwork = new Network(1);
|
||||
private final Network mMobileNetwork = new Network(2);
|
||||
private final Network mVpnNetwork = new Network(3);
|
||||
private final Network[] mAllNetworks = {mMobileNetwork, mWifiNetwork, mVpnNetwork};
|
||||
private final Network mMobileNetwork2 = new Network(4);
|
||||
private final Network mMobileNetwork3 = new Network(5);
|
||||
private final Network mMobileNetwork4 = new Network(6);
|
||||
private final Network mMobileNetwork5 = new Network(7);
|
||||
private final Network mMobileNetwork6 = new Network(8);
|
||||
private final Network[] mAllNetworks = {mMobileNetwork, mWifiNetwork, mVpnNetwork,
|
||||
mMobileNetwork2, mMobileNetwork3, mMobileNetwork4, mMobileNetwork5, mMobileNetwork6};
|
||||
private final ArrayList<IpPrefix> mTetheringPrefixes = new ArrayList<>(Arrays.asList(
|
||||
new IpPrefix("192.168.0.0/16"),
|
||||
new IpPrefix("172.16.0.0/12"),
|
||||
new IpPrefix("10.0.0.0/8")));
|
||||
|
||||
private void setUpIpServers() throws Exception {
|
||||
when(mUsbIpServer.interfaceType()).thenReturn(TETHERING_USB);
|
||||
@@ -87,7 +100,8 @@ public final class PrivateAddressCoordinatorTest {
|
||||
when(mConnectivityMgr.getAllNetworks()).thenReturn(mAllNetworks);
|
||||
when(mConfig.shouldEnableWifiP2pDedicatedIp()).thenReturn(false);
|
||||
setUpIpServers();
|
||||
mPrivateAddressCoordinator = spy(new PrivateAddressCoordinator(mContext, mConfig));
|
||||
mPrivateAddressCoordinator = spy(new PrivateAddressCoordinator(mContext, mConfig,
|
||||
mTetheringPrefixes));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -117,28 +131,28 @@ public final class PrivateAddressCoordinatorTest {
|
||||
@Test
|
||||
public void testSanitizedAddress() throws Exception {
|
||||
int fakeSubAddr = 0x2b00; // 43.0.
|
||||
when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(fakeSubAddr);
|
||||
when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeSubAddr);
|
||||
LinkAddress actualAddress = mPrivateAddressCoordinator.requestDownstreamAddress(
|
||||
mHotspotIpServer, false /* useLastAddress */);
|
||||
assertEquals(new LinkAddress("192.168.43.42/24"), actualAddress);
|
||||
assertEquals(new LinkAddress("192.168.43.2/24"), actualAddress);
|
||||
mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer);
|
||||
|
||||
fakeSubAddr = 0x2d01; // 45.1.
|
||||
when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(fakeSubAddr);
|
||||
when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeSubAddr);
|
||||
actualAddress = mPrivateAddressCoordinator.requestDownstreamAddress(
|
||||
mHotspotIpServer, false /* useLastAddress */);
|
||||
assertEquals(new LinkAddress("192.168.45.42/24"), actualAddress);
|
||||
assertEquals(new LinkAddress("192.168.45.2/24"), actualAddress);
|
||||
mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer);
|
||||
|
||||
fakeSubAddr = 0x2eff; // 46.255.
|
||||
when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(fakeSubAddr);
|
||||
when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeSubAddr);
|
||||
actualAddress = mPrivateAddressCoordinator.requestDownstreamAddress(
|
||||
mHotspotIpServer, false /* useLastAddress */);
|
||||
assertEquals(new LinkAddress("192.168.46.42/24"), actualAddress);
|
||||
assertEquals(new LinkAddress("192.168.46.254/24"), actualAddress);
|
||||
mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer);
|
||||
|
||||
fakeSubAddr = 0x2f05; // 47.5.
|
||||
when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(fakeSubAddr);
|
||||
when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeSubAddr);
|
||||
actualAddress = mPrivateAddressCoordinator.requestDownstreamAddress(
|
||||
mHotspotIpServer, false /* useLastAddress */);
|
||||
assertEquals(new LinkAddress("192.168.47.5/24"), actualAddress);
|
||||
@@ -148,7 +162,7 @@ public final class PrivateAddressCoordinatorTest {
|
||||
@Test
|
||||
public void testReservedPrefix() throws Exception {
|
||||
// - Test bluetooth prefix is reserved.
|
||||
when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(
|
||||
when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(
|
||||
getSubAddress(mBluetoothAddress.getAddress().getAddress()));
|
||||
final LinkAddress hotspotAddress = mPrivateAddressCoordinator.requestDownstreamAddress(
|
||||
mHotspotIpServer, false /* useLastAddress */);
|
||||
@@ -157,7 +171,7 @@ public final class PrivateAddressCoordinatorTest {
|
||||
mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer);
|
||||
|
||||
// - Test previous enabled hotspot prefix(cached prefix) is reserved.
|
||||
when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(
|
||||
when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(
|
||||
getSubAddress(hotspotAddress.getAddress().getAddress()));
|
||||
final LinkAddress usbAddress = mPrivateAddressCoordinator.requestDownstreamAddress(
|
||||
mUsbIpServer, false /* useLastAddress */);
|
||||
@@ -167,7 +181,7 @@ public final class PrivateAddressCoordinatorTest {
|
||||
mPrivateAddressCoordinator.releaseDownstream(mUsbIpServer);
|
||||
|
||||
// - Test wifi p2p prefix is reserved.
|
||||
when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(
|
||||
when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(
|
||||
getSubAddress(mLegacyWifiP2pAddress.getAddress().getAddress()));
|
||||
final LinkAddress etherAddress = mPrivateAddressCoordinator.requestDownstreamAddress(
|
||||
mEthernetIpServer, false /* useLastAddress */);
|
||||
@@ -182,7 +196,7 @@ public final class PrivateAddressCoordinatorTest {
|
||||
public void testRequestLastDownstreamAddress() throws Exception {
|
||||
final int fakeHotspotSubAddr = 0x2b05;
|
||||
final IpPrefix predefinedPrefix = new IpPrefix("192.168.43.0/24");
|
||||
when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(fakeHotspotSubAddr);
|
||||
when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeHotspotSubAddr);
|
||||
final LinkAddress hotspotAddress = mPrivateAddressCoordinator.requestDownstreamAddress(
|
||||
mHotspotIpServer, true /* useLastAddress */);
|
||||
assertEquals("Wrong wifi prefix: ", predefinedPrefix, asIpPrefix(hotspotAddress));
|
||||
@@ -196,7 +210,7 @@ public final class PrivateAddressCoordinatorTest {
|
||||
mPrivateAddressCoordinator.releaseDownstream(mUsbIpServer);
|
||||
|
||||
final int newFakeSubAddr = 0x3c05;
|
||||
when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(fakeHotspotSubAddr);
|
||||
when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeHotspotSubAddr);
|
||||
|
||||
final LinkAddress newHotspotAddress = mPrivateAddressCoordinator.requestDownstreamAddress(
|
||||
mHotspotIpServer, true /* useLastAddress */);
|
||||
@@ -229,11 +243,10 @@ public final class PrivateAddressCoordinatorTest {
|
||||
|
||||
@Test
|
||||
public void testNoConflictUpstreamPrefix() throws Exception {
|
||||
final int fakeHotspotSubId = 43;
|
||||
final int fakeHotspotSubAddr = 0x2b05;
|
||||
final int fakeHotspotSubAddr = 0x2b05; // 43.5
|
||||
final IpPrefix predefinedPrefix = new IpPrefix("192.168.43.0/24");
|
||||
// Force always get subAddress "43.5" for conflict testing.
|
||||
when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(fakeHotspotSubAddr);
|
||||
when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeHotspotSubAddr);
|
||||
// - Enable hotspot with prefix 192.168.43.0/24
|
||||
final LinkAddress hotspotAddr = mPrivateAddressCoordinator.requestDownstreamAddress(
|
||||
mHotspotIpServer, true /* useLastAddress */);
|
||||
@@ -312,6 +325,209 @@ public final class PrivateAddressCoordinatorTest {
|
||||
assertEquals(predefinedPrefix, ethPrefix);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChooseAvailablePrefix() throws Exception {
|
||||
final int randomAddress = 0x8605; // 134.5
|
||||
when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(randomAddress);
|
||||
final LinkAddress addr0 = mPrivateAddressCoordinator.requestDownstreamAddress(
|
||||
mHotspotIpServer, true/* useLastAddress */);
|
||||
// Check whether return address is prefix 192.168.0.0/16 + subAddress 0.0.134.5.
|
||||
assertEquals("Wrong prefix: ", new LinkAddress("192.168.134.5/24"), addr0);
|
||||
when(mHotspotIpServer.getAddress()).thenReturn(addr0);
|
||||
final UpstreamNetworkState wifiUpstream = buildUpstreamNetworkState(mWifiNetwork,
|
||||
new LinkAddress("192.168.134.13/26"), null,
|
||||
makeNetworkCapabilities(TRANSPORT_WIFI));
|
||||
mPrivateAddressCoordinator.updateUpstreamPrefix(wifiUpstream);
|
||||
|
||||
// Check whether return address is next prefix of 192.168.134.0/24.
|
||||
final LinkAddress addr1 = mPrivateAddressCoordinator.requestDownstreamAddress(
|
||||
mHotspotIpServer, true/* useLastAddress */);
|
||||
assertEquals("Wrong prefix: ", new LinkAddress("192.168.135.5/24"), addr1);
|
||||
when(mHotspotIpServer.getAddress()).thenReturn(addr1);
|
||||
final UpstreamNetworkState wifiUpstream2 = buildUpstreamNetworkState(mWifiNetwork,
|
||||
new LinkAddress("192.168.149.16/19"), null,
|
||||
makeNetworkCapabilities(TRANSPORT_WIFI));
|
||||
mPrivateAddressCoordinator.updateUpstreamPrefix(wifiUpstream2);
|
||||
|
||||
|
||||
// The conflict range is 128 ~ 159, so the address is 192.168.160.5/24.
|
||||
final LinkAddress addr2 = mPrivateAddressCoordinator.requestDownstreamAddress(
|
||||
mHotspotIpServer, true/* useLastAddress */);
|
||||
assertEquals("Wrong prefix: ", new LinkAddress("192.168.160.5/24"), addr2);
|
||||
when(mHotspotIpServer.getAddress()).thenReturn(addr2);
|
||||
final UpstreamNetworkState mobileUpstream = buildUpstreamNetworkState(mMobileNetwork,
|
||||
new LinkAddress("192.168.129.53/18"), null,
|
||||
makeNetworkCapabilities(TRANSPORT_CELLULAR));
|
||||
// Update another conflict upstream which is covered by the previous one (but not the first
|
||||
// one) and verify whether this would affect the result.
|
||||
final UpstreamNetworkState mobileUpstream2 = buildUpstreamNetworkState(mMobileNetwork2,
|
||||
new LinkAddress("192.168.170.7/19"), null,
|
||||
makeNetworkCapabilities(TRANSPORT_CELLULAR));
|
||||
mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream);
|
||||
mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream2);
|
||||
|
||||
// The conflict range are 128 ~ 159 and 159 ~ 191, so the address is 192.168.192.5/24.
|
||||
final LinkAddress addr3 = mPrivateAddressCoordinator.requestDownstreamAddress(
|
||||
mHotspotIpServer, true/* useLastAddress */);
|
||||
assertEquals("Wrong prefix: ", new LinkAddress("192.168.192.5/24"), addr3);
|
||||
when(mHotspotIpServer.getAddress()).thenReturn(addr3);
|
||||
final UpstreamNetworkState mobileUpstream3 = buildUpstreamNetworkState(mMobileNetwork3,
|
||||
new LinkAddress("192.168.188.133/17"), null,
|
||||
makeNetworkCapabilities(TRANSPORT_CELLULAR));
|
||||
mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream3);
|
||||
|
||||
// Conflict range: 128 ~ 255. The next available address is 192.168.0.5 because
|
||||
// 192.168.134/24 ~ 192.168.255.255/24 is not available.
|
||||
final LinkAddress addr4 = mPrivateAddressCoordinator.requestDownstreamAddress(
|
||||
mHotspotIpServer, true/* useLastAddress */);
|
||||
assertEquals("Wrong prefix: ", new LinkAddress("192.168.0.5/24"), addr4);
|
||||
when(mHotspotIpServer.getAddress()).thenReturn(addr4);
|
||||
final UpstreamNetworkState mobileUpstream4 = buildUpstreamNetworkState(mMobileNetwork4,
|
||||
new LinkAddress("192.168.3.59/21"), null,
|
||||
makeNetworkCapabilities(TRANSPORT_CELLULAR));
|
||||
mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream4);
|
||||
|
||||
// Conflict ranges: 128 ~ 255 and 0 ~ 7, so the address is 192.168.8.5/24.
|
||||
final LinkAddress addr5 = mPrivateAddressCoordinator.requestDownstreamAddress(
|
||||
mHotspotIpServer, true/* useLastAddress */);
|
||||
assertEquals("Wrong prefix: ", new LinkAddress("192.168.8.5/24"), addr5);
|
||||
when(mHotspotIpServer.getAddress()).thenReturn(addr5);
|
||||
final UpstreamNetworkState mobileUpstream5 = buildUpstreamNetworkState(mMobileNetwork5,
|
||||
new LinkAddress("192.168.68.43/21"), null,
|
||||
makeNetworkCapabilities(TRANSPORT_CELLULAR));
|
||||
mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream5);
|
||||
|
||||
// Update an upstream that does *not* conflict, check whether return the same address
|
||||
// 192.168.5/24.
|
||||
final LinkAddress addr6 = mPrivateAddressCoordinator.requestDownstreamAddress(
|
||||
mHotspotIpServer, true/* useLastAddress */);
|
||||
assertEquals("Wrong prefix: ", new LinkAddress("192.168.8.5/24"), addr6);
|
||||
when(mHotspotIpServer.getAddress()).thenReturn(addr6);
|
||||
final UpstreamNetworkState mobileUpstream6 = buildUpstreamNetworkState(mMobileNetwork6,
|
||||
new LinkAddress("192.168.10.97/21"), null,
|
||||
makeNetworkCapabilities(TRANSPORT_CELLULAR));
|
||||
mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream6);
|
||||
|
||||
// Conflict ranges: 0 ~ 15 and 128 ~ 255, so the address is 192.168.16.5/24.
|
||||
final LinkAddress addr7 = mPrivateAddressCoordinator.requestDownstreamAddress(
|
||||
mHotspotIpServer, true/* useLastAddress */);
|
||||
assertEquals("Wrong prefix: ", new LinkAddress("192.168.16.5/24"), addr7);
|
||||
when(mHotspotIpServer.getAddress()).thenReturn(addr7);
|
||||
final UpstreamNetworkState mobileUpstream7 = buildUpstreamNetworkState(mMobileNetwork6,
|
||||
new LinkAddress("192.168.0.0/17"), null,
|
||||
makeNetworkCapabilities(TRANSPORT_CELLULAR));
|
||||
mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream7);
|
||||
|
||||
// Choose prefix from next range(172.16.0.0/12) when no available prefix in 192.168.0.0/16.
|
||||
final LinkAddress addr8 = mPrivateAddressCoordinator.requestDownstreamAddress(
|
||||
mHotspotIpServer, true/* useLastAddress */);
|
||||
assertEquals("Wrong prefix: ", new LinkAddress("172.16.134.5/24"), addr8);
|
||||
when(mHotspotIpServer.getAddress()).thenReturn(addr6);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChoosePrefixFromDifferentRanges() throws Exception {
|
||||
final int randomAddress = 0x1f2b2a; // 31.43.42
|
||||
when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(randomAddress);
|
||||
final LinkAddress classC1 = mPrivateAddressCoordinator.requestDownstreamAddress(
|
||||
mHotspotIpServer, true/* useLastAddress */);
|
||||
// Check whether return address is prefix 192.168.0.0/16 + subAddress 0.0.43.42.
|
||||
assertEquals("Wrong prefix: ", new LinkAddress("192.168.43.42/24"), classC1);
|
||||
when(mHotspotIpServer.getAddress()).thenReturn(classC1);
|
||||
final UpstreamNetworkState wifiUpstream = buildUpstreamNetworkState(mWifiNetwork,
|
||||
new LinkAddress("192.168.88.23/17"), null,
|
||||
makeNetworkCapabilities(TRANSPORT_WIFI));
|
||||
mPrivateAddressCoordinator.updateUpstreamPrefix(wifiUpstream);
|
||||
verifyNotifyConflictAndRelease(mHotspotIpServer);
|
||||
|
||||
// Check whether return address is next address of prefix 192.168.128.0/17.
|
||||
final LinkAddress classC2 = mPrivateAddressCoordinator.requestDownstreamAddress(
|
||||
mHotspotIpServer, true/* useLastAddress */);
|
||||
assertEquals("Wrong prefix: ", new LinkAddress("192.168.128.42/24"), classC2);
|
||||
when(mHotspotIpServer.getAddress()).thenReturn(classC2);
|
||||
final UpstreamNetworkState mobileUpstream = buildUpstreamNetworkState(mMobileNetwork,
|
||||
new LinkAddress("192.1.2.3/8"), null,
|
||||
makeNetworkCapabilities(TRANSPORT_CELLULAR));
|
||||
mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream);
|
||||
verifyNotifyConflictAndRelease(mHotspotIpServer);
|
||||
|
||||
// Check whether return address is under prefix 172.16.0.0/12.
|
||||
final LinkAddress classB1 = mPrivateAddressCoordinator.requestDownstreamAddress(
|
||||
mHotspotIpServer, true/* useLastAddress */);
|
||||
assertEquals("Wrong prefix: ", new LinkAddress("172.31.43.42/24"), classB1);
|
||||
when(mHotspotIpServer.getAddress()).thenReturn(classB1);
|
||||
final UpstreamNetworkState mobileUpstream2 = buildUpstreamNetworkState(mMobileNetwork2,
|
||||
new LinkAddress("172.28.123.100/14"), null,
|
||||
makeNetworkCapabilities(TRANSPORT_CELLULAR));
|
||||
mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream2);
|
||||
verifyNotifyConflictAndRelease(mHotspotIpServer);
|
||||
|
||||
// 172.28.0.0 ~ 172.31.255.255 is not available.
|
||||
// Check whether return address is next address of prefix 172.16.0.0/14.
|
||||
final LinkAddress classB2 = mPrivateAddressCoordinator.requestDownstreamAddress(
|
||||
mHotspotIpServer, true/* useLastAddress */);
|
||||
assertEquals("Wrong prefix: ", new LinkAddress("172.16.0.42/24"), classB2);
|
||||
when(mHotspotIpServer.getAddress()).thenReturn(classB2);
|
||||
|
||||
// Check whether new downstream is next address of address 172.16.0.42/24.
|
||||
final LinkAddress classB3 = mPrivateAddressCoordinator.requestDownstreamAddress(
|
||||
mUsbIpServer, true/* useLastAddress */);
|
||||
assertEquals("Wrong prefix: ", new LinkAddress("172.16.1.42/24"), classB3);
|
||||
when(mUsbIpServer.getAddress()).thenReturn(classB3);
|
||||
final UpstreamNetworkState mobileUpstream3 = buildUpstreamNetworkState(mMobileNetwork3,
|
||||
new LinkAddress("172.16.0.1/24"), null,
|
||||
makeNetworkCapabilities(TRANSPORT_CELLULAR));
|
||||
mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream3);
|
||||
verifyNotifyConflictAndRelease(mHotspotIpServer);
|
||||
verify(mUsbIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
|
||||
|
||||
// Check whether return address is next address of prefix 172.16.1.42/24.
|
||||
final LinkAddress classB4 = mPrivateAddressCoordinator.requestDownstreamAddress(
|
||||
mHotspotIpServer, true/* useLastAddress */);
|
||||
assertEquals("Wrong prefix: ", new LinkAddress("172.16.2.42/24"), classB4);
|
||||
when(mHotspotIpServer.getAddress()).thenReturn(classB4);
|
||||
final UpstreamNetworkState mobileUpstream4 = buildUpstreamNetworkState(mMobileNetwork4,
|
||||
new LinkAddress("172.16.0.1/13"), null,
|
||||
makeNetworkCapabilities(TRANSPORT_CELLULAR));
|
||||
mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream4);
|
||||
verifyNotifyConflictAndRelease(mHotspotIpServer);
|
||||
verifyNotifyConflictAndRelease(mUsbIpServer);
|
||||
|
||||
// Check whether return address is next address of prefix 172.16.0.1/13.
|
||||
final LinkAddress classB5 = mPrivateAddressCoordinator.requestDownstreamAddress(
|
||||
mHotspotIpServer, true/* useLastAddress */);
|
||||
assertEquals("Wrong prefix: ", new LinkAddress("172.24.0.42/24"), classB5);
|
||||
when(mHotspotIpServer.getAddress()).thenReturn(classB5);
|
||||
// Check whether return address is next address of prefix 172.24.0.42/24.
|
||||
final LinkAddress classB6 = mPrivateAddressCoordinator.requestDownstreamAddress(
|
||||
mUsbIpServer, true/* useLastAddress */);
|
||||
assertEquals("Wrong prefix: ", new LinkAddress("172.24.1.42/24"), classB6);
|
||||
when(mUsbIpServer.getAddress()).thenReturn(classB6);
|
||||
final UpstreamNetworkState mobileUpstream5 = buildUpstreamNetworkState(mMobileNetwork5,
|
||||
new LinkAddress("172.24.0.1/12"), null,
|
||||
makeNetworkCapabilities(TRANSPORT_CELLULAR));
|
||||
mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream5);
|
||||
verifyNotifyConflictAndRelease(mHotspotIpServer);
|
||||
verifyNotifyConflictAndRelease(mUsbIpServer);
|
||||
|
||||
// Check whether return address is prefix 10.0.0.0/8 + subAddress 0.31.43.42.
|
||||
final LinkAddress classA1 = mPrivateAddressCoordinator.requestDownstreamAddress(
|
||||
mHotspotIpServer, true/* useLastAddress */);
|
||||
assertEquals("Wrong prefix: ", new LinkAddress("10.31.43.42/24"), classA1);
|
||||
when(mHotspotIpServer.getAddress()).thenReturn(classA1);
|
||||
// Check whether new downstream is next address of address 10.31.43.42/24.
|
||||
final LinkAddress classA2 = mPrivateAddressCoordinator.requestDownstreamAddress(
|
||||
mUsbIpServer, true/* useLastAddress */);
|
||||
assertEquals("Wrong prefix: ", new LinkAddress("10.31.44.42/24"), classA2);
|
||||
}
|
||||
|
||||
private void verifyNotifyConflictAndRelease(final IpServer ipServer) throws Exception {
|
||||
verify(ipServer).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
|
||||
mPrivateAddressCoordinator.releaseDownstream(ipServer);
|
||||
reset(ipServer);
|
||||
setUpIpServers();
|
||||
}
|
||||
|
||||
private int getSubAddress(final byte... ipv4Address) {
|
||||
assertEquals(4, ipv4Address.length);
|
||||
|
||||
@@ -330,7 +546,7 @@ public final class PrivateAddressCoordinatorTest {
|
||||
|
||||
@Test
|
||||
public void testEnableLegacyWifiP2PAddress() throws Exception {
|
||||
when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(
|
||||
when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(
|
||||
getSubAddress(mLegacyWifiP2pAddress.getAddress().getAddress()));
|
||||
// No matter #shouldEnableWifiP2pDedicatedIp() is enabled or not, legacy wifi p2p prefix
|
||||
// is resevered.
|
||||
|
||||
@@ -24,6 +24,9 @@ import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
|
||||
import static android.net.ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED;
|
||||
import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED;
|
||||
import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED;
|
||||
import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH;
|
||||
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
|
||||
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
|
||||
import static android.net.RouteInfo.RTN_UNICAST;
|
||||
import static android.net.TetheringManager.ACTION_TETHER_STATE_CHANGED;
|
||||
import static android.net.TetheringManager.EXTRA_ACTIVE_LOCAL_ONLY;
|
||||
@@ -179,6 +182,7 @@ public class TetheringTest {
|
||||
private static final String TEST_P2P_IFNAME = "test_p2p-p2p0-0";
|
||||
private static final String TEST_NCM_IFNAME = "test_ncm0";
|
||||
private static final String TEST_ETH_IFNAME = "test_eth0";
|
||||
private static final String TEST_BT_IFNAME = "test_pan0";
|
||||
private static final String TETHERING_NAME = "Tethering";
|
||||
private static final String[] PROVISIONING_APP_NAME = {"some", "app"};
|
||||
private static final String PROVISIONING_NO_UI_APP_NAME = "no_ui_app";
|
||||
@@ -230,6 +234,7 @@ public class TetheringTest {
|
||||
private TetheringConfiguration mConfig;
|
||||
private EntitlementManager mEntitleMgr;
|
||||
private OffloadController mOffloadCtrl;
|
||||
private PrivateAddressCoordinator mPrivateAddressCoordinator;
|
||||
|
||||
private class TestContext extends BroadcastInterceptingContext {
|
||||
TestContext(Context base) {
|
||||
@@ -446,6 +451,18 @@ public class TetheringTest {
|
||||
public boolean isTetheringDenied() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public PrivateAddressCoordinator getPrivateAddressCoordinator(Context ctx,
|
||||
TetheringConfiguration cfg) {
|
||||
final ArrayList<IpPrefix> prefixPool = new ArrayList<>(Arrays.asList(
|
||||
new IpPrefix("192.168.0.0/16"),
|
||||
new IpPrefix("172.16.0.0/12"),
|
||||
new IpPrefix("10.0.0.0/8")));
|
||||
mPrivateAddressCoordinator = spy(new PrivateAddressCoordinator(ctx, cfg, prefixPool));
|
||||
return mPrivateAddressCoordinator;
|
||||
}
|
||||
}
|
||||
|
||||
private static UpstreamNetworkState buildMobileUpstreamState(boolean withIPv4,
|
||||
@@ -1875,27 +1892,36 @@ public class TetheringTest {
|
||||
sendConfigurationChanged();
|
||||
}
|
||||
|
||||
private static UpstreamNetworkState buildV4WifiUpstreamState(final String ipv4Address,
|
||||
final int prefixLength, final Network network) {
|
||||
private static UpstreamNetworkState buildV4UpstreamState(final LinkAddress address,
|
||||
final Network network, final String iface, final int transportType) {
|
||||
final LinkProperties prop = new LinkProperties();
|
||||
prop.setInterfaceName(TEST_WIFI_IFNAME);
|
||||
prop.setInterfaceName(iface);
|
||||
|
||||
prop.addLinkAddress(
|
||||
new LinkAddress(InetAddresses.parseNumericAddress(ipv4Address),
|
||||
prefixLength));
|
||||
prop.addLinkAddress(address);
|
||||
|
||||
final NetworkCapabilities capabilities = new NetworkCapabilities()
|
||||
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
|
||||
.addTransportType(transportType);
|
||||
return new UpstreamNetworkState(prop, capabilities, network);
|
||||
}
|
||||
|
||||
private void updateV4Upstream(final LinkAddress ipv4Address, final Network network,
|
||||
final String iface, final int transportType) {
|
||||
final UpstreamNetworkState upstream = buildV4UpstreamState(ipv4Address, network, iface,
|
||||
transportType);
|
||||
mTetheringDependencies.mUpstreamNetworkMonitorSM.sendMessage(
|
||||
Tethering.TetherMainSM.EVENT_UPSTREAM_CALLBACK,
|
||||
UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES,
|
||||
0,
|
||||
upstream);
|
||||
mLooper.dispatchAll();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleIpConflict() throws Exception {
|
||||
final Network wifiNetwork = new Network(200);
|
||||
final Network[] allNetworks = { wifiNetwork };
|
||||
when(mCm.getAllNetworks()).thenReturn(allNetworks);
|
||||
UpstreamNetworkState upstreamNetwork = null;
|
||||
runUsbTethering(upstreamNetwork);
|
||||
runUsbTethering(null);
|
||||
final ArgumentCaptor<InterfaceConfigurationParcel> ifaceConfigCaptor =
|
||||
ArgumentCaptor.forClass(InterfaceConfigurationParcel.class);
|
||||
verify(mNetd).interfaceSetCfg(ifaceConfigCaptor.capture());
|
||||
@@ -1903,13 +1929,10 @@ public class TetheringTest {
|
||||
verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).startWithCallbacks(
|
||||
any(), any());
|
||||
reset(mNetd, mUsbManager);
|
||||
upstreamNetwork = buildV4WifiUpstreamState(ipv4Address, 30, wifiNetwork);
|
||||
mTetheringDependencies.mUpstreamNetworkMonitorSM.sendMessage(
|
||||
Tethering.TetherMainSM.EVENT_UPSTREAM_CALLBACK,
|
||||
UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES,
|
||||
0,
|
||||
upstreamNetwork);
|
||||
mLooper.dispatchAll();
|
||||
|
||||
// Cause a prefix conflict by assigning a /30 out of the downstream's /24 to the upstream.
|
||||
updateV4Upstream(new LinkAddress(InetAddresses.parseNumericAddress(ipv4Address), 30),
|
||||
wifiNetwork, TEST_WIFI_IFNAME, TRANSPORT_WIFI);
|
||||
// verify turn off usb tethering
|
||||
verify(mUsbManager).setCurrentFunctions(UsbManager.FUNCTION_NONE);
|
||||
mTethering.interfaceRemoved(TEST_USB_IFNAME);
|
||||
@@ -1921,9 +1944,10 @@ public class TetheringTest {
|
||||
@Test
|
||||
public void testNoAddressAvailable() throws Exception {
|
||||
final Network wifiNetwork = new Network(200);
|
||||
final Network[] allNetworks = { wifiNetwork };
|
||||
final Network btNetwork = new Network(201);
|
||||
final Network mobileNetwork = new Network(202);
|
||||
final Network[] allNetworks = { wifiNetwork, btNetwork, mobileNetwork };
|
||||
when(mCm.getAllNetworks()).thenReturn(allNetworks);
|
||||
final String upstreamAddress = "192.168.0.100";
|
||||
runUsbTethering(null);
|
||||
verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).startWithCallbacks(
|
||||
any(), any());
|
||||
@@ -1940,13 +1964,13 @@ public class TetheringTest {
|
||||
mLooper.dispatchAll();
|
||||
reset(mUsbManager, mEm);
|
||||
|
||||
final UpstreamNetworkState upstreamNetwork = buildV4WifiUpstreamState(
|
||||
upstreamAddress, 16, wifiNetwork);
|
||||
mTetheringDependencies.mUpstreamNetworkMonitorSM.sendMessage(
|
||||
Tethering.TetherMainSM.EVENT_UPSTREAM_CALLBACK,
|
||||
UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES,
|
||||
0,
|
||||
upstreamNetwork);
|
||||
updateV4Upstream(new LinkAddress("192.168.0.100/16"), wifiNetwork, TEST_WIFI_IFNAME,
|
||||
TRANSPORT_WIFI);
|
||||
updateV4Upstream(new LinkAddress("172.16.0.0/12"), btNetwork, TEST_BT_IFNAME,
|
||||
TRANSPORT_BLUETOOTH);
|
||||
updateV4Upstream(new LinkAddress("10.0.0.0/8"), mobileNetwork, TEST_MOBILE_IFNAME,
|
||||
TRANSPORT_CELLULAR);
|
||||
|
||||
mLooper.dispatchAll();
|
||||
// verify turn off usb tethering
|
||||
verify(mUsbManager).setCurrentFunctions(UsbManager.FUNCTION_NONE);
|
||||
|
||||
Reference in New Issue
Block a user