Merge "Make PrivateAddressCoordinator ignore vpn network"
This commit is contained in:
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.networkstack.tethering;
|
package com.android.networkstack.tethering;
|
||||||
|
|
||||||
|
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
|
||||||
import static android.net.TetheringManager.TETHERING_WIFI_P2P;
|
import static android.net.TetheringManager.TETHERING_WIFI_P2P;
|
||||||
|
|
||||||
import static java.util.Arrays.asList;
|
import static java.util.Arrays.asList;
|
||||||
@@ -23,7 +24,6 @@ import android.content.Context;
|
|||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.net.IpPrefix;
|
import android.net.IpPrefix;
|
||||||
import android.net.LinkAddress;
|
import android.net.LinkAddress;
|
||||||
import android.net.LinkProperties;
|
|
||||||
import android.net.Network;
|
import android.net.Network;
|
||||||
import android.net.ip.IpServer;
|
import android.net.ip.IpServer;
|
||||||
import android.net.util.PrefixUtils;
|
import android.net.util.PrefixUtils;
|
||||||
@@ -90,16 +90,24 @@ public class PrivateAddressCoordinator {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Record a new upstream IpPrefix which may conflict with tethering downstreams.
|
* Record a new upstream IpPrefix which may conflict with tethering downstreams.
|
||||||
* The downstreams will be notified if a conflict is found.
|
* The downstreams will be notified if a conflict is found. When updateUpstreamPrefix is called,
|
||||||
|
* UpstreamNetworkState must have an already populated LinkProperties.
|
||||||
*/
|
*/
|
||||||
public void updateUpstreamPrefix(final Network network, final LinkProperties lp) {
|
public void updateUpstreamPrefix(final UpstreamNetworkState ns) {
|
||||||
final ArrayList<IpPrefix> ipv4Prefixes = getIpv4Prefixes(lp.getAllLinkAddresses());
|
// Do not support VPN as upstream
|
||||||
if (ipv4Prefixes.isEmpty()) {
|
if (ns.networkCapabilities != null && ns.networkCapabilities.hasTransport(TRANSPORT_VPN)) {
|
||||||
removeUpstreamPrefix(network);
|
removeUpstreamPrefix(ns.network);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mUpstreamPrefixMap.put(network, ipv4Prefixes);
|
final ArrayList<IpPrefix> ipv4Prefixes = getIpv4Prefixes(
|
||||||
|
ns.linkProperties.getAllLinkAddresses());
|
||||||
|
if (ipv4Prefixes.isEmpty()) {
|
||||||
|
removeUpstreamPrefix(ns.network);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mUpstreamPrefixMap.put(ns.network, ipv4Prefixes);
|
||||||
handleMaybePrefixConflict(ipv4Prefixes);
|
handleMaybePrefixConflict(ipv4Prefixes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1678,14 +1678,6 @@ public class Tethering {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addUpstreamPrefixes(final UpstreamNetworkState ns) {
|
|
||||||
mPrivateAddressCoordinator.updateUpstreamPrefix(ns.network, ns.linkProperties);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeUpstreamPrefixes(final UpstreamNetworkState ns) {
|
|
||||||
mPrivateAddressCoordinator.removeUpstreamPrefix(ns.network);
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
void handleUpstreamNetworkMonitorCallback(int arg1, Object o) {
|
void handleUpstreamNetworkMonitorCallback(int arg1, Object o) {
|
||||||
if (arg1 == UpstreamNetworkMonitor.NOTIFY_LOCAL_PREFIXES) {
|
if (arg1 == UpstreamNetworkMonitor.NOTIFY_LOCAL_PREFIXES) {
|
||||||
@@ -1696,10 +1688,10 @@ public class Tethering {
|
|||||||
final UpstreamNetworkState ns = (UpstreamNetworkState) o;
|
final UpstreamNetworkState ns = (UpstreamNetworkState) o;
|
||||||
switch (arg1) {
|
switch (arg1) {
|
||||||
case UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES:
|
case UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES:
|
||||||
addUpstreamPrefixes(ns);
|
mPrivateAddressCoordinator.updateUpstreamPrefix(ns);
|
||||||
break;
|
break;
|
||||||
case UpstreamNetworkMonitor.EVENT_ON_LOST:
|
case UpstreamNetworkMonitor.EVENT_ON_LOST:
|
||||||
removeUpstreamPrefixes(ns);
|
mPrivateAddressCoordinator.removeUpstreamPrefix(ns.network);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,10 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.networkstack.tethering;
|
package com.android.networkstack.tethering;
|
||||||
|
|
||||||
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
|
||||||
|
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
|
||||||
|
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
|
||||||
|
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
|
||||||
import static android.net.TetheringManager.TETHERING_ETHERNET;
|
import static android.net.TetheringManager.TETHERING_ETHERNET;
|
||||||
import static android.net.TetheringManager.TETHERING_USB;
|
import static android.net.TetheringManager.TETHERING_USB;
|
||||||
import static android.net.TetheringManager.TETHERING_WIFI;
|
import static android.net.TetheringManager.TETHERING_WIFI;
|
||||||
@@ -30,13 +34,12 @@ import static org.mockito.Mockito.when;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.net.InetAddresses;
|
|
||||||
import android.net.IpPrefix;
|
import android.net.IpPrefix;
|
||||||
import android.net.LinkAddress;
|
import android.net.LinkAddress;
|
||||||
import android.net.LinkProperties;
|
import android.net.LinkProperties;
|
||||||
import android.net.Network;
|
import android.net.Network;
|
||||||
|
import android.net.NetworkCapabilities;
|
||||||
import android.net.ip.IpServer;
|
import android.net.ip.IpServer;
|
||||||
import android.net.util.NetworkConstants;
|
|
||||||
import android.net.util.PrefixUtils;
|
import android.net.util.PrefixUtils;
|
||||||
|
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
@@ -48,13 +51,10 @@ import org.junit.runner.RunWith;
|
|||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
@SmallTest
|
@SmallTest
|
||||||
public final class PrivateAddressCoordinatorTest {
|
public final class PrivateAddressCoordinatorTest {
|
||||||
private static final String TEST_MOBILE_IFNAME = "test_rmnet_data0";
|
private static final String TEST_IFNAME = "test0";
|
||||||
private static final String TEST_WIFI_IFNAME = "test_wlan0";
|
|
||||||
|
|
||||||
@Mock private IpServer mHotspotIpServer;
|
@Mock private IpServer mHotspotIpServer;
|
||||||
@Mock private IpServer mUsbIpServer;
|
@Mock private IpServer mUsbIpServer;
|
||||||
@@ -69,7 +69,8 @@ public final class PrivateAddressCoordinatorTest {
|
|||||||
private final LinkAddress mLegacyWifiP2pAddress = new LinkAddress("192.168.49.1/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 mVpnNetwork = new Network(3);
|
||||||
|
private final Network[] mAllNetworks = {mMobileNetwork, mWifiNetwork, mVpnNetwork};
|
||||||
|
|
||||||
private void setUpIpServers() throws Exception {
|
private void setUpIpServers() throws Exception {
|
||||||
when(mUsbIpServer.interfaceType()).thenReturn(TETHERING_USB);
|
when(mUsbIpServer.interfaceType()).thenReturn(TETHERING_USB);
|
||||||
@@ -184,33 +185,25 @@ public final class PrivateAddressCoordinatorTest {
|
|||||||
assertEquals("Fail to reselect available prefix: ", predefinedPrefix, allowUseFreePrefix);
|
assertEquals("Fail to reselect available prefix: ", predefinedPrefix, allowUseFreePrefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
private LinkProperties buildUpstreamLinkProperties(boolean withIPv4, boolean withIPv6,
|
private UpstreamNetworkState buildUpstreamNetworkState(final Network network,
|
||||||
boolean isMobile) {
|
final LinkAddress v4Addr, final LinkAddress v6Addr, final NetworkCapabilities cap) {
|
||||||
final String testIface;
|
|
||||||
final String testIpv4Address;
|
|
||||||
if (isMobile) {
|
|
||||||
testIface = TEST_MOBILE_IFNAME;
|
|
||||||
testIpv4Address = "10.0.0.1";
|
|
||||||
} else {
|
|
||||||
testIface = TEST_WIFI_IFNAME;
|
|
||||||
testIpv4Address = "192.168.43.5";
|
|
||||||
}
|
|
||||||
|
|
||||||
final LinkProperties prop = new LinkProperties();
|
final LinkProperties prop = new LinkProperties();
|
||||||
prop.setInterfaceName(testIface);
|
prop.setInterfaceName(TEST_IFNAME);
|
||||||
|
if (v4Addr != null) prop.addLinkAddress(v4Addr);
|
||||||
|
|
||||||
if (withIPv4) {
|
if (v6Addr != null) prop.addLinkAddress(v6Addr);
|
||||||
prop.addLinkAddress(
|
|
||||||
new LinkAddress(InetAddresses.parseNumericAddress(testIpv4Address),
|
return new UpstreamNetworkState(prop, cap, network);
|
||||||
NetworkConstants.IPV4_ADDR_BITS));
|
}
|
||||||
|
|
||||||
|
private NetworkCapabilities makeNetworkCapabilities(final int transportType) {
|
||||||
|
final NetworkCapabilities cap = new NetworkCapabilities();
|
||||||
|
cap.addTransportType(transportType);
|
||||||
|
if (transportType == TRANSPORT_VPN) {
|
||||||
|
cap.removeCapability(NET_CAPABILITY_NOT_VPN);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (withIPv6) {
|
return cap;
|
||||||
prop.addLinkAddress(
|
|
||||||
new LinkAddress(InetAddresses.parseNumericAddress("2001:db8::"),
|
|
||||||
NetworkConstants.RFC7421_PREFIX_LENGTH));
|
|
||||||
}
|
|
||||||
return prop;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -220,53 +213,76 @@ public final class PrivateAddressCoordinatorTest {
|
|||||||
final IpPrefix predefinedPrefix = new IpPrefix("192.168.43.0/24");
|
final IpPrefix predefinedPrefix = new IpPrefix("192.168.43.0/24");
|
||||||
// Force always get subAddress "43.5" for conflict testing.
|
// Force always get subAddress "43.5" for conflict testing.
|
||||||
when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(fakeHotspotSubAddr);
|
when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(fakeHotspotSubAddr);
|
||||||
// 1. Enable hotspot with prefix 192.168.43.0/24
|
// - Enable hotspot with prefix 192.168.43.0/24
|
||||||
final LinkAddress hotspotAddr = mPrivateAddressCoordinator.requestDownstreamAddress(
|
final LinkAddress hotspotAddr = mPrivateAddressCoordinator.requestDownstreamAddress(
|
||||||
mHotspotIpServer);
|
mHotspotIpServer);
|
||||||
final IpPrefix hotspotPrefix = PrefixUtils.asIpPrefix(hotspotAddr);
|
final IpPrefix hotspotPrefix = PrefixUtils.asIpPrefix(hotspotAddr);
|
||||||
assertEquals("Wrong wifi prefix: ", predefinedPrefix, hotspotPrefix);
|
assertEquals("Wrong wifi prefix: ", predefinedPrefix, hotspotPrefix);
|
||||||
when(mHotspotIpServer.getAddress()).thenReturn(hotspotAddr);
|
when(mHotspotIpServer.getAddress()).thenReturn(hotspotAddr);
|
||||||
// 2. Update v6 only mobile network, hotspot prefix should not be removed.
|
// - test mobile network with null NetworkCapabilities. Ideally this should not happen,
|
||||||
List<String> testConflicts;
|
// just make sure no crash in this case.
|
||||||
final LinkProperties v6OnlyMobileProp = buildUpstreamLinkProperties(false, true, true);
|
final UpstreamNetworkState noCapUpstream = buildUpstreamNetworkState(mMobileNetwork,
|
||||||
mPrivateAddressCoordinator.updateUpstreamPrefix(mMobileNetwork, v6OnlyMobileProp);
|
new LinkAddress("10.0.0.8/24"), null, null);
|
||||||
|
mPrivateAddressCoordinator.updateUpstreamPrefix(noCapUpstream);
|
||||||
|
verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
|
||||||
|
// - test mobile upstream with no address.
|
||||||
|
final UpstreamNetworkState noAddress = buildUpstreamNetworkState(mMobileNetwork,
|
||||||
|
null, null, makeNetworkCapabilities(TRANSPORT_CELLULAR));
|
||||||
|
mPrivateAddressCoordinator.updateUpstreamPrefix(noCapUpstream);
|
||||||
|
verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
|
||||||
|
// - Update v6 only mobile network, hotspot prefix should not be removed.
|
||||||
|
final UpstreamNetworkState v6OnlyMobile = buildUpstreamNetworkState(mMobileNetwork,
|
||||||
|
null, new LinkAddress("2001:db8::/64"),
|
||||||
|
makeNetworkCapabilities(TRANSPORT_CELLULAR));
|
||||||
|
mPrivateAddressCoordinator.updateUpstreamPrefix(v6OnlyMobile);
|
||||||
verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
|
verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
|
||||||
mPrivateAddressCoordinator.removeUpstreamPrefix(mMobileNetwork);
|
mPrivateAddressCoordinator.removeUpstreamPrefix(mMobileNetwork);
|
||||||
// 3. Update v4 only mobile network, hotspot prefix should not be removed.
|
// - Update v4 only mobile network, hotspot prefix should not be removed.
|
||||||
final LinkProperties v4OnlyMobileProp = buildUpstreamLinkProperties(true, false, true);
|
final UpstreamNetworkState v4OnlyMobile = buildUpstreamNetworkState(mMobileNetwork,
|
||||||
mPrivateAddressCoordinator.updateUpstreamPrefix(mMobileNetwork, v4OnlyMobileProp);
|
new LinkAddress("10.0.0.8/24"), null,
|
||||||
|
makeNetworkCapabilities(TRANSPORT_CELLULAR));
|
||||||
|
mPrivateAddressCoordinator.updateUpstreamPrefix(v4OnlyMobile);
|
||||||
verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
|
verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
|
||||||
// 4. Update v4v6 mobile network, hotspot prefix should not be removed.
|
// - Update v4v6 mobile network, hotspot prefix should not be removed.
|
||||||
final LinkProperties v4v6MobileProp = buildUpstreamLinkProperties(true, true, true);
|
final UpstreamNetworkState v4v6Mobile = buildUpstreamNetworkState(mMobileNetwork,
|
||||||
mPrivateAddressCoordinator.updateUpstreamPrefix(mMobileNetwork, v4v6MobileProp);
|
new LinkAddress("10.0.0.8/24"), new LinkAddress("2001:db8::/64"),
|
||||||
|
makeNetworkCapabilities(TRANSPORT_CELLULAR));
|
||||||
|
mPrivateAddressCoordinator.updateUpstreamPrefix(v4v6Mobile);
|
||||||
verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
|
verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
|
||||||
// 5. Update v6 only wifi network, hotspot prefix should not be removed.
|
// - Update v6 only wifi network, hotspot prefix should not be removed.
|
||||||
final LinkProperties v6OnlyWifiProp = buildUpstreamLinkProperties(false, true, false);
|
final UpstreamNetworkState v6OnlyWifi = buildUpstreamNetworkState(mWifiNetwork,
|
||||||
mPrivateAddressCoordinator.updateUpstreamPrefix(mWifiNetwork, v6OnlyWifiProp);
|
null, new LinkAddress("2001:db8::/64"), makeNetworkCapabilities(TRANSPORT_WIFI));
|
||||||
|
mPrivateAddressCoordinator.updateUpstreamPrefix(v6OnlyWifi);
|
||||||
verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
|
verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
|
||||||
mPrivateAddressCoordinator.removeUpstreamPrefix(mWifiNetwork);
|
mPrivateAddressCoordinator.removeUpstreamPrefix(mWifiNetwork);
|
||||||
// 6. Update v4 only wifi network, it conflict with hotspot prefix.
|
// - Update vpn network, it conflict with hotspot prefix but VPN networks are ignored.
|
||||||
final LinkProperties v4OnlyWifiProp = buildUpstreamLinkProperties(true, false, false);
|
final UpstreamNetworkState v4OnlyVpn = buildUpstreamNetworkState(mVpnNetwork,
|
||||||
mPrivateAddressCoordinator.updateUpstreamPrefix(mWifiNetwork, v4OnlyWifiProp);
|
new LinkAddress("192.168.43.5/24"), null, makeNetworkCapabilities(TRANSPORT_VPN));
|
||||||
|
mPrivateAddressCoordinator.updateUpstreamPrefix(v4OnlyVpn);
|
||||||
|
verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
|
||||||
|
// - Update v4 only wifi network, it conflict with hotspot prefix.
|
||||||
|
final UpstreamNetworkState v4OnlyWifi = buildUpstreamNetworkState(mWifiNetwork,
|
||||||
|
new LinkAddress("192.168.43.5/24"), null, makeNetworkCapabilities(TRANSPORT_WIFI));
|
||||||
|
mPrivateAddressCoordinator.updateUpstreamPrefix(v4OnlyWifi);
|
||||||
verify(mHotspotIpServer).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
|
verify(mHotspotIpServer).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
|
||||||
reset(mHotspotIpServer);
|
reset(mHotspotIpServer);
|
||||||
// 7. Restart hotspot again and its prefix is different previous.
|
// - Restart hotspot again and its prefix is different previous.
|
||||||
mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer);
|
mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer);
|
||||||
final LinkAddress hotspotAddr2 = mPrivateAddressCoordinator.requestDownstreamAddress(
|
final LinkAddress hotspotAddr2 = mPrivateAddressCoordinator.requestDownstreamAddress(
|
||||||
mHotspotIpServer);
|
mHotspotIpServer);
|
||||||
final IpPrefix hotspotPrefix2 = PrefixUtils.asIpPrefix(hotspotAddr2);
|
final IpPrefix hotspotPrefix2 = PrefixUtils.asIpPrefix(hotspotAddr2);
|
||||||
assertNotEquals(hotspotPrefix, hotspotPrefix2);
|
assertNotEquals(hotspotPrefix, hotspotPrefix2);
|
||||||
when(mHotspotIpServer.getAddress()).thenReturn(hotspotAddr2);
|
when(mHotspotIpServer.getAddress()).thenReturn(hotspotAddr2);
|
||||||
mPrivateAddressCoordinator.updateUpstreamPrefix(mWifiNetwork, v4OnlyWifiProp);
|
mPrivateAddressCoordinator.updateUpstreamPrefix(v4OnlyWifi);
|
||||||
verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
|
verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
|
||||||
// 7. Usb tethering can be enabled and its prefix is different with conflict one.
|
// - Usb tethering can be enabled and its prefix is different with conflict one.
|
||||||
final LinkAddress usbAddr = mPrivateAddressCoordinator.requestDownstreamAddress(
|
final LinkAddress usbAddr = mPrivateAddressCoordinator.requestDownstreamAddress(
|
||||||
mUsbIpServer);
|
mUsbIpServer);
|
||||||
final IpPrefix usbPrefix = PrefixUtils.asIpPrefix(usbAddr);
|
final IpPrefix usbPrefix = PrefixUtils.asIpPrefix(usbAddr);
|
||||||
assertNotEquals(predefinedPrefix, usbPrefix);
|
assertNotEquals(predefinedPrefix, usbPrefix);
|
||||||
assertNotEquals(hotspotPrefix2, usbPrefix);
|
assertNotEquals(hotspotPrefix2, usbPrefix);
|
||||||
when(mUsbIpServer.getAddress()).thenReturn(usbAddr);
|
when(mUsbIpServer.getAddress()).thenReturn(usbAddr);
|
||||||
// 8. Disable wifi upstream, then wifi's prefix can be selected again.
|
// - Disable wifi upstream, then wifi's prefix can be selected again.
|
||||||
mPrivateAddressCoordinator.removeUpstreamPrefix(mWifiNetwork);
|
mPrivateAddressCoordinator.removeUpstreamPrefix(mWifiNetwork);
|
||||||
final LinkAddress ethAddr = mPrivateAddressCoordinator.requestDownstreamAddress(
|
final LinkAddress ethAddr = mPrivateAddressCoordinator.requestDownstreamAddress(
|
||||||
mEthernetIpServer);
|
mEthernetIpServer);
|
||||||
|
|||||||
Reference in New Issue
Block a user